1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-07 00:04:31 +03:00

Merge sinisa@bk-internal.mysql.com:/home/bk/mysql-4.0

into sinisa.nasamreza.org:/mnt/work/mysql-4.0


sql/sql_acl.cc:
  Auto merged
sql/sql_parse.cc:
  Auto merged
sql/sql_select.cc:
  Auto merged
sql/sql_yacc.yy:
  Auto merged
This commit is contained in:
unknown
2003-06-25 18:40:31 +03:00
42 changed files with 743 additions and 346 deletions

View File

@@ -44,6 +44,7 @@ jorge@linux.jorge.mysql.com
kaj@work.mysql.com kaj@work.mysql.com
lenz@kallisto.mysql.com lenz@kallisto.mysql.com
lenz@mysql.com lenz@mysql.com
miguel@hegel.(none)
miguel@hegel.br miguel@hegel.br
miguel@hegel.local miguel@hegel.local
miguel@light. miguel@light.
@@ -84,6 +85,7 @@ sasha@mysql.sashanet.com
serg@build.mysql2.com serg@build.mysql2.com
serg@serg.mylan serg@serg.mylan
serg@serg.mysql.com serg@serg.mysql.com
serg@sergbook.mylan
serg@sergbook.mysql.com serg@sergbook.mysql.com
sinisa@rhols221.adsl.netsonic.fi sinisa@rhols221.adsl.netsonic.fi
tfr@beta.frontier86.ee tfr@beta.frontier86.ee

View File

@@ -711,7 +711,7 @@ AC_DEFUN(MYSQL_FIND_OPENSSL, [
done done
for d in /usr/ssl/lib /usr/local/ssl/lib /usr/lib/openssl \ for d in /usr/ssl/lib /usr/local/ssl/lib /usr/lib/openssl \
/usr/lib /opt/ssl/lib /opt/openssl/lib /usr/local/lib/ ; do /usr/lib /usr/lib64 /opt/ssl/lib /opt/openssl/lib /usr/local/lib/ ; do
if test -f $d/libssl.a ; then if test -f $d/libssl.a ; then
OPENSSL_LIB=$d OPENSSL_LIB=$d
fi fi
@@ -721,7 +721,7 @@ AC_DEFUN(MYSQL_FIND_OPENSSL, [
echo "Could not find an installation of OpenSSL" echo "Could not find an installation of OpenSSL"
if test -n "$OPENSSL_LIB" ; then if test -n "$OPENSSL_LIB" ; then
if test "$IS_LINUX" = "true"; then if test "$IS_LINUX" = "true"; then
echo "Looks like you've forgotted to install OpenSSL development RPM" echo "Looks like you've forgotten to install OpenSSL development RPM"
fi fi
fi fi
exit 1 exit 1

View File

@@ -396,8 +396,8 @@ static int check_header(IO_CACHE* file)
if (buf[4] == START_EVENT) if (buf[4] == START_EVENT)
{ {
uint event_len; uint event_len;
event_len = uint4korr(buf + 4); event_len = uint4korr(buf + EVENT_LEN_OFFSET);
old_format = (event_len < LOG_EVENT_HEADER_LEN + START_HEADER_LEN); old_format = (event_len < (LOG_EVENT_HEADER_LEN + START_HEADER_LEN));
} }
} }
my_b_seek(file, pos); my_b_seek(file, pos);

View File

@@ -757,7 +757,7 @@ AC_CHECK_LIB(crypt, crypt)
AC_CHECK_FUNC(crypt, AC_DEFINE(HAVE_CRYPT)) AC_CHECK_FUNC(crypt, AC_DEFINE(HAVE_CRYPT))
# For sem_xxx functions on Solaris 2.6 # For sem_xxx functions on Solaris 2.6
AC_CHECK_FUNC(sem_init, , AC_CHECK_LIB(posix4)) AC_CHECK_FUNC(sem_init, , AC_CHECK_LIB(posix4, sem_init))
# For compress in zlib # For compress in zlib
MYSQL_CHECK_ZLIB_WITH_COMPRESS($with_named_zlib) MYSQL_CHECK_ZLIB_WITH_COMPRESS($with_named_zlib)

View File

@@ -494,6 +494,46 @@ dict_index_get_nth_col_pos(
return(ULINT_UNDEFINED); return(ULINT_UNDEFINED);
} }
/************************************************************************
Returns TRUE if the index contains a column or a prefix of that column. */
ibool
dict_index_contains_col_or_prefix(
/*==============================*/
/* out: TRUE if contains the column or its
prefix */
dict_index_t* index, /* in: index */
ulint n) /* in: column number */
{
dict_field_t* field;
dict_col_t* col;
ulint pos;
ulint n_fields;
ut_ad(index);
ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
if (index->type & DICT_CLUSTERED) {
return(TRUE);
}
col = dict_table_get_nth_col(index->table, n);
n_fields = dict_index_get_n_fields(index);
for (pos = 0; pos < n_fields; pos++) {
field = dict_index_get_nth_field(index, pos);
if (col == field->col) {
return(TRUE);
}
}
return(FALSE);
}
/************************************************************************ /************************************************************************
Looks for a matching field in an index. The column and the prefix len have Looks for a matching field in an index. The column and the prefix len have
to be the same. */ to be the same. */

View File

@@ -569,6 +569,16 @@ dict_index_get_nth_col_pos(
dict_index_t* index, /* in: index */ dict_index_t* index, /* in: index */
ulint n); /* in: column number */ ulint n); /* in: column number */
/************************************************************************ /************************************************************************
Returns TRUE if the index contains a column or a prefix of that column. */
ibool
dict_index_contains_col_or_prefix(
/*==============================*/
/* out: TRUE if contains the column or its
prefix */
dict_index_t* index, /* in: index */
ulint n); /* in: column number */
/************************************************************************
Looks for a matching field in an index. The column and the prefix len has Looks for a matching field in an index. The column and the prefix len has
to be the same. */ to be the same. */

View File

@@ -446,7 +446,6 @@ page_copy_rec_list_end_no_locks(
page_cur_move_to_next(&cur1); page_cur_move_to_next(&cur1);
} }
/* Track a memory corruption bug in Windows */
ut_a(mach_read_from_2(new_page + UNIV_PAGE_SIZE - 10) == PAGE_INFIMUM); ut_a(mach_read_from_2(new_page + UNIV_PAGE_SIZE - 10) == PAGE_INFIMUM);
page_cur_set_before_first(new_page, &cur2); page_cur_set_before_first(new_page, &cur2);
@@ -456,11 +455,23 @@ page_copy_rec_list_end_no_locks(
sup = page_get_supremum_rec(page); sup = page_get_supremum_rec(page);
while (sup != page_cur_get_rec(&cur1)) { while (sup != page_cur_get_rec(&cur1)) {
ut_a( if (!page_cur_rec_insert(&cur2,
page_cur_rec_insert(&cur2, page_cur_get_rec(&cur1), mtr)); page_cur_get_rec(&cur1), mtr)) {
/* Track an assertion failure reported on the mailing
list on June 18th, 2003 */
buf_page_print(new_page);
buf_page_print(page);
ut_print_timestamp(stderr);
fprintf(stderr,
"InnoDB: rec offset %lu, cur1 offset %lu, cur2 offset %lu\n",
(ulint)(rec - page),
(ulint)(page_cur_get_rec(&cur1) - page),
(ulint)(page_cur_get_rec(&cur2) - new_page));
ut_a(0);
}
ut_a(mach_read_from_2(new_page + UNIV_PAGE_SIZE - 10)
== PAGE_INFIMUM);
page_cur_move_to_next(&cur1); page_cur_move_to_next(&cur1);
page_cur_move_to_next(&cur2); page_cur_move_to_next(&cur2);
} }

View File

@@ -791,27 +791,30 @@ row_ins_foreign_check_on_constraint(
mem_heap_free(tmp_heap); mem_heap_free(tmp_heap);
clust_rec = btr_pcur_get_rec(cascade->pcur); clust_rec = btr_pcur_get_rec(cascade->pcur);
}
if (!page_rec_is_user_rec(clust_rec)) { if (!page_rec_is_user_rec(clust_rec)
fprintf(stderr, || btr_pcur_get_low_match(cascade->pcur)
< dict_index_get_n_unique(clust_index)) {
fprintf(stderr,
"InnoDB: error in cascade of a foreign key op\n" "InnoDB: error in cascade of a foreign key op\n"
"InnoDB: index %s table %s\n", index->name, "InnoDB: index %s table %s\n", index->name,
index->table->name); index->table->name);
rec_sprintf(err_buf, 900, rec); rec_sprintf(err_buf, 900, rec);
fprintf(stderr, "InnoDB: record %s\n", err_buf); fprintf(stderr, "InnoDB: record %s\n", err_buf);
rec_sprintf(err_buf, 900, clust_rec); rec_sprintf(err_buf, 900, clust_rec);
fprintf(stderr, "InnoDB: clustered record %s\n", err_buf); fprintf(stderr, "InnoDB: clustered record %s\n",
err_buf);
fprintf(stderr, fprintf(stderr,
"InnoDB: Make a detailed bug report and send it\n"); "InnoDB: Make a detailed bug report and send it\n");
fprintf(stderr, "InnoDB: to mysql@lists.mysql.com\n"); fprintf(stderr, "InnoDB: to mysql@lists.mysql.com\n");
err = DB_SUCCESS; err = DB_SUCCESS;
goto nonstandard_exit_func; goto nonstandard_exit_func;
}
} }
/* Set an X-lock on the row to delete or update in the child table */ /* Set an X-lock on the row to delete or update in the child table */

View File

@@ -609,7 +609,29 @@ row_sel_get_clust_rec(
clust_rec = btr_pcur_get_rec(&(plan->clust_pcur)); clust_rec = btr_pcur_get_rec(&(plan->clust_pcur));
ut_ad(page_rec_is_user_rec(clust_rec)); /* Note: only if the search ends up on a non-infimum record is the
low_match value the real match to the search tuple */
if (!page_rec_is_user_rec(clust_rec)
|| btr_pcur_get_low_match(&(plan->clust_pcur))
< dict_index_get_n_unique(index)) {
ut_a(rec_get_deleted_flag(rec));
ut_a(node->read_view);
/* In a rare case it is possible that no clust rec is found
for a delete-marked secondary index record: if in row0umod.c
in row_undo_mod_remove_clust_low() we have already removed
the clust rec, while purge is still cleaning and removing
secondary index records associated with earlier versions of
the clustered index record. In that case we know that the
clustered index record did not exist in the read view of
trx. */
clust_rec = NULL;
goto func_exit;
}
if (!node->read_view) { if (!node->read_view) {
/* Try to place a lock on the index record */ /* Try to place a lock on the index record */
@@ -672,6 +694,7 @@ row_sel_get_clust_rec(
row_sel_fetch_columns(index, clust_rec, row_sel_fetch_columns(index, clust_rec,
UT_LIST_GET_FIRST(plan->columns)); UT_LIST_GET_FIRST(plan->columns));
func_exit:
*out_rec = clust_rec; *out_rec = clust_rec;
return(DB_SUCCESS); return(DB_SUCCESS);
@@ -1253,6 +1276,8 @@ rec_loop:
/* PHASE 3: Get previous version in a consistent read */ /* PHASE 3: Get previous version in a consistent read */
cons_read_requires_clust_rec = FALSE;
if (consistent_read) { if (consistent_read) {
/* This is a non-locking consistent read: if necessary, fetch /* This is a non-locking consistent read: if necessary, fetch
a previous version of the record */ a previous version of the record */
@@ -2269,7 +2294,10 @@ row_sel_get_clust_rec_for_mysql(
/* out: DB_SUCCESS or error code */ /* out: DB_SUCCESS or error code */
row_prebuilt_t* prebuilt,/* in: prebuilt struct in the handle */ row_prebuilt_t* prebuilt,/* in: prebuilt struct in the handle */
dict_index_t* sec_index,/* in: secondary index where rec resides */ dict_index_t* sec_index,/* in: secondary index where rec resides */
rec_t* rec, /* in: record in a non-clustered index */ rec_t* rec, /* in: record in a non-clustered index; if
this is a locking read, then rec is not
allowed to be delete-marked, and that would
not make sense either */
que_thr_t* thr, /* in: query thread */ que_thr_t* thr, /* in: query thread */
rec_t** out_rec,/* out: clustered record or an old version of rec_t** out_rec,/* out: clustered record or an old version of
it, NULL if the old version did not exist it, NULL if the old version did not exist
@@ -2285,7 +2313,7 @@ row_sel_get_clust_rec_for_mysql(
ulint err; ulint err;
trx_t* trx; trx_t* trx;
char err_buf[1000]; char err_buf[1000];
*out_rec = NULL; *out_rec = NULL;
row_build_row_ref_in_tuple(prebuilt->clust_ref, sec_index, rec); row_build_row_ref_in_tuple(prebuilt->clust_ref, sec_index, rec);
@@ -2298,26 +2326,47 @@ row_sel_get_clust_rec_for_mysql(
clust_rec = btr_pcur_get_rec(prebuilt->clust_pcur); clust_rec = btr_pcur_get_rec(prebuilt->clust_pcur);
if (!page_rec_is_user_rec(clust_rec)) { /* Note: only if the search ends up on a non-infimum record is the
ut_print_timestamp(stderr); low_match value the real match to the search tuple */
fprintf(stderr,
" InnoDB: error clustered record for sec rec not found\n"
"InnoDB: index %s table %s\n", sec_index->name,
sec_index->table->name);
rec_sprintf(err_buf, 900, rec); if (!page_rec_is_user_rec(clust_rec)
fprintf(stderr, "InnoDB: sec index record %s\n", err_buf); || btr_pcur_get_low_match(prebuilt->clust_pcur)
< dict_index_get_n_unique(clust_index)) {
/* In a rare case it is possible that no clust rec is found
for a delete-marked secondary index record: if in row0umod.c
in row_undo_mod_remove_clust_low() we have already removed
the clust rec, while purge is still cleaning and removing
secondary index records associated with earlier versions of
the clustered index record. In that case we know that the
clustered index record did not exist in the read view of
trx. */
rec_sprintf(err_buf, 900, clust_rec); if (!rec_get_deleted_flag(rec)
fprintf(stderr, "InnoDB: clust index record %s\n", err_buf); || prebuilt->select_lock_type != LOCK_NONE) {
trx = thr_get_trx(thr); ut_print_timestamp(stderr);
trx_print(err_buf, trx); fprintf(stderr,
" InnoDB: error clustered record for sec rec not found\n"
"InnoDB: index %s table %s\n", sec_index->name,
sec_index->table->name);
fprintf(stderr, rec_sprintf(err_buf, 900, rec);
"%s\nInnoDB: Make a detailed bug report and send it\n", fprintf(stderr,
err_buf); "InnoDB: sec index record %s\n", err_buf);
fprintf(stderr, "InnoDB: to mysql@lists.mysql.com\n");
rec_sprintf(err_buf, 900, clust_rec);
fprintf(stderr,
"InnoDB: clust index record %s\n", err_buf);
trx = thr_get_trx(thr);
trx_print(err_buf, trx);
fprintf(stderr,
"%s\nInnoDB: Make a detailed bug report and send it\n",
err_buf);
fprintf(stderr, "InnoDB: to mysql@lists.mysql.com\n");
}
clust_rec = NULL; clust_rec = NULL;
@@ -2989,8 +3038,6 @@ rec_loop:
/*-------------------------------------------------------------*/ /*-------------------------------------------------------------*/
/* PHASE 4: Look for matching records in a loop */ /* PHASE 4: Look for matching records in a loop */
cons_read_requires_clust_rec = FALSE;
rec = btr_pcur_get_rec(pcur); rec = btr_pcur_get_rec(pcur);
/* /*
printf("Using index %s cnt %lu ", index->name, cnt); printf("Using index %s cnt %lu ", index->name, cnt);
@@ -3145,6 +3192,8 @@ rec_loop:
/* We are ready to look at a possible new index entry in the result /* We are ready to look at a possible new index entry in the result
set: the cursor is now placed on a user record */ set: the cursor is now placed on a user record */
cons_read_requires_clust_rec = FALSE;
if (prebuilt->select_lock_type != LOCK_NONE) { if (prebuilt->select_lock_type != LOCK_NONE) {
/* Try to place a lock on the index record; note that delete /* Try to place a lock on the index record; note that delete
marked records are a special case in a unique search. If there marked records are a special case in a unique search. If there
@@ -3170,8 +3219,6 @@ rec_loop:
/* This is a non-locking consistent read: if necessary, fetch /* This is a non-locking consistent read: if necessary, fetch
a previous version of the record */ a previous version of the record */
cons_read_requires_clust_rec = FALSE;
if (trx->isolation_level == TRX_ISO_READ_UNCOMMITTED) { if (trx->isolation_level == TRX_ISO_READ_UNCOMMITTED) {
/* Do nothing: we let a non-locking SELECT read the /* Do nothing: we let a non-locking SELECT read the
@@ -3215,7 +3262,7 @@ rec_loop:
if (rec_get_deleted_flag(rec) && !cons_read_requires_clust_rec) { if (rec_get_deleted_flag(rec) && !cons_read_requires_clust_rec) {
/* The record is delete marked: we can skip it if this is /* The record is delete-marked: we can skip it if this is
not a consistent read which might see an earlier version not a consistent read which might see an earlier version
of a non-clustered index record */ of a non-clustered index record */
@@ -3324,7 +3371,7 @@ got_row:
goto normal_return; goto normal_return;
next_rec: next_rec:
/*-------------------------------------------------------------*/ /*-------------------------------------------------------------*/
/* PHASE 5: Move the cursor to the next index record */ /* PHASE 5: Move the cursor to the next index record */
if (mtr_has_extra_clust_latch) { if (mtr_has_extra_clust_latch) {

View File

@@ -59,7 +59,6 @@ row_vers_impl_x_locked_off_kernel(
ibool rec_del; ibool rec_del;
ulint err; ulint err;
mtr_t mtr; mtr_t mtr;
char err_buf[1000];
ut_ad(mutex_own(&kernel_mutex)); ut_ad(mutex_own(&kernel_mutex));
ut_ad(!rw_lock_own(&(purge_sys->latch), RW_LOCK_SHARED)); ut_ad(!rw_lock_own(&(purge_sys->latch), RW_LOCK_SHARED));
@@ -77,22 +76,20 @@ row_vers_impl_x_locked_off_kernel(
clust_rec = row_get_clust_rec(BTR_SEARCH_LEAF, rec, index, clust_rec = row_get_clust_rec(BTR_SEARCH_LEAF, rec, index,
&clust_index, &mtr); &clust_index, &mtr);
if (!clust_rec) { if (!clust_rec) {
rec_sprintf(err_buf, 900, rec); /* In a rare case it is possible that no clust rec is found
for a secondary index record: if in row0umod.c
row_undo_mod_remove_clust_low() we have already removed the
clust rec, while purge is still cleaning and removing
secondary index records associated with earlier versions of
the clustered index record. In that case there cannot be
any implicit lock on the secondary index record, because
an active transaction which has modified the secondary index
record has also modified the clustered index record. And in
a rollback we always undo the modifications to secondary index
records before the clustered index record. */
ut_print_timestamp(stderr); mutex_enter(&kernel_mutex);
fprintf(stderr, mtr_commit(&mtr);
" InnoDB: Error: cannot find the clustered index record\n"
"InnoDB: for a secondary index record in table %s index %s.\n"
"InnoDB: Secondary index record %s.\n"
"InnoDB: The table is probably corrupt. Please run CHECK TABLE on it.\n"
"InnoDB: You can try to repair the table by dump + drop + reimport.\n"
"InnoDB: Send a detailed bug report to mysql@lists.mysql.com.\n",
index->table_name, index->name, err_buf);
mutex_enter(&kernel_mutex);
mtr_commit(&mtr);
/* We assume there is no lock on the record, though this
is not certain because the table is apparently corrupt */
return(NULL); return(NULL);
} }

View File

@@ -40,14 +40,17 @@
#include <arpa/inet.h> #include <arpa/inet.h>
#include <netdb.h> #include <netdb.h>
#ifdef HAVE_SELECT_H #ifdef HAVE_SELECT_H
# include <select.h> #include <select.h>
#endif #endif
#ifdef HAVE_SYS_SELECT_H #ifdef HAVE_SYS_SELECT_H
#include <sys/select.h> #include <sys/select.h>
#endif #endif
#ifdef HAVE_POLL
#include <sys/poll.h>
#endif #endif
#endif /* !defined(MSDOS) && !defined(__WIN__) */
#ifdef HAVE_SYS_UN_H #ifdef HAVE_SYS_UN_H
# include <sys/un.h> #include <sys/un.h>
#endif #endif
#if defined(THREAD) && !defined(__WIN__) #if defined(THREAD) && !defined(__WIN__)
#include <my_pthread.h> /* because of signal() */ #include <my_pthread.h> /* because of signal() */
@@ -148,9 +151,12 @@ static MYSQL* spawn_init(MYSQL* parent, const char* host,
const char* user, const char* user,
const char* passwd); const char* passwd);
#if !(defined(__WIN__) || defined(OS2) || defined(__NETWARE__))
static int wait_for_data(my_socket fd, uint timeout);
#endif
/**************************************************************************** /****************************************************************************
A modified version of connect(). connect2() allows you to specify A modified version of connect(). my_connect() allows you to specify
a timeout value, in seconds, that we should wait until we a timeout value, in seconds, that we should wait until we
derermine we can't connect to a particular host. If timeout is 0, derermine we can't connect to a particular host. If timeout is 0,
my_connect() will behave exactly like connect(). my_connect() will behave exactly like connect().
@@ -158,17 +164,13 @@ static MYSQL* spawn_init(MYSQL* parent, const char* host,
Base version coded by Steve Bernacki, Jr. <steve@navinet.net> Base version coded by Steve Bernacki, Jr. <steve@navinet.net>
*****************************************************************************/ *****************************************************************************/
int my_connect(my_socket s, const struct sockaddr *name, uint namelen, int my_connect(my_socket fd, const struct sockaddr *name, uint namelen,
uint timeout) uint timeout)
{ {
#if defined(__WIN__) || defined(OS2) || defined(__NETWARE__) #if defined(__WIN__) || defined(OS2) || defined(__NETWARE__)
return connect(s, (struct sockaddr*) name, namelen); return connect(fd, (struct sockaddr*) name, namelen);
#else #else
int flags, res, s_err; int flags, res, s_err;
SOCKOPT_OPTLEN_TYPE s_err_size = sizeof(uint);
fd_set sfds;
struct timeval tv;
time_t start_time, now_time;
/* /*
If they passed us a timeout of zero, we should behave If they passed us a timeout of zero, we should behave
@@ -176,30 +178,68 @@ int my_connect(my_socket s, const struct sockaddr *name, uint namelen,
*/ */
if (timeout == 0) if (timeout == 0)
return connect(s, (struct sockaddr*) name, namelen); return connect(fd, (struct sockaddr*) name, namelen);
flags = fcntl(s, F_GETFL, 0); /* Set socket to not block */ flags = fcntl(fd, F_GETFL, 0); /* Set socket to not block */
#ifdef O_NONBLOCK #ifdef O_NONBLOCK
fcntl(s, F_SETFL, flags | O_NONBLOCK); /* and save the flags.. */ fcntl(fd, F_SETFL, flags | O_NONBLOCK); /* and save the flags.. */
#endif #endif
res = connect(s, (struct sockaddr*) name, namelen); res= connect(fd, (struct sockaddr*) name, namelen);
s_err = errno; /* Save the error... */ s_err= errno; /* Save the error... */
fcntl(s, F_SETFL, flags); fcntl(fd, F_SETFL, flags);
if ((res != 0) && (s_err != EINPROGRESS)) if ((res != 0) && (s_err != EINPROGRESS))
{ {
errno = s_err; /* Restore it */ errno= s_err; /* Restore it */
return(-1); return(-1);
} }
if (res == 0) /* Connected quickly! */ if (res == 0) /* Connected quickly! */
return(0); return(0);
return wait_for_data(fd, timeout);
#endif
}
/*
Wait up to timeout seconds for a connection to be established.
We prefer to do this with poll() as there is no limitations with this.
If not, we will use select()
*/
#if !(defined(__WIN__) || defined(OS2) || defined(__NETWARE__))
static int wait_for_data(my_socket fd, uint timeout)
{
#ifdef HAVE_POLL
struct pollfd ufds;
int res;
ufds.fd= fd;
ufds.events= POLLIN | POLLPRI;
if (!(res= poll(&ufds, 1, (int) timeout*1000)))
{
errno= EINTR;
return -1;
}
if (res < 0 || !(ufds.revents & (POLLIN | POLLPRI)))
return -1;
return 0;
#else
SOCKOPT_OPTLEN_TYPE s_err_size = sizeof(uint);
fd_set sfds;
struct timeval tv;
time_t start_time, now_time;
int res, s_err;
if (fd >= FD_SETSIZE) /* Check if wrong error */
return 0; /* Can't use timeout */
/* /*
Otherwise, our connection is "in progress." We can use Our connection is "in progress." We can use the select() call to wait
the select() call to wait up to a specified period of time up to a specified period of time for the connection to suceed.
for the connection to suceed. If select() returns 0 If select() returns 0 (after waiting howevermany seconds), our socket
(after waiting howevermany seconds), our socket never became never became writable (host is probably unreachable.) Otherwise, if
writable (host is probably unreachable.) Otherwise, if
select() returns 1, then one of two conditions exist: select() returns 1, then one of two conditions exist:
1. An error occured. We use getsockopt() to check for this. 1. An error occured. We use getsockopt() to check for this.
@@ -212,7 +252,7 @@ int my_connect(my_socket s, const struct sockaddr *name, uint namelen,
*/ */
FD_ZERO(&sfds); FD_ZERO(&sfds);
FD_SET(s, &sfds); FD_SET(fd, &sfds);
/* /*
select could be interrupted by a signal, and if it is, select could be interrupted by a signal, and if it is,
the timeout should be adjusted and the select restarted the timeout should be adjusted and the select restarted
@@ -226,10 +266,10 @@ int my_connect(my_socket s, const struct sockaddr *name, uint namelen,
tv.tv_sec = (long) timeout; tv.tv_sec = (long) timeout;
tv.tv_usec = 0; tv.tv_usec = 0;
#if defined(HPUX10) && defined(THREAD) #if defined(HPUX10) && defined(THREAD)
if ((res = select(s+1, NULL, (int*) &sfds, NULL, &tv)) > 0) if ((res = select(fd+1, NULL, (int*) &sfds, NULL, &tv)) > 0)
break; break;
#else #else
if ((res = select(s+1, NULL, &sfds, NULL, &tv)) > 0) if ((res = select(fd+1, NULL, &sfds, NULL, &tv)) > 0)
break; break;
#endif #endif
if (res == 0) /* timeout */ if (res == 0) /* timeout */
@@ -247,7 +287,7 @@ int my_connect(my_socket s, const struct sockaddr *name, uint namelen,
*/ */
s_err=0; s_err=0;
if (getsockopt(s, SOL_SOCKET, SO_ERROR, (char*) &s_err, &s_err_size) != 0) if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (char*) &s_err, &s_err_size) != 0)
return(-1); return(-1);
if (s_err) if (s_err)
@@ -256,9 +296,9 @@ int my_connect(my_socket s, const struct sockaddr *name, uint namelen,
return(-1); /* but return an error... */ return(-1); /* but return an error... */
} }
return (0); /* ok */ return (0); /* ok */
#endif /* HAVE_POLL */
#endif
} }
#endif /* defined(__WIN__) || defined(OS2) || defined(__NETWARE__) */
/* /*
Create a named pipe connection Create a named pipe connection

View File

@@ -569,7 +569,9 @@ error () {
} }
error_is () { error_is () {
$CAT < $TIMEFILE | $SED -e 's/.* At line \(.*\)\: \(.*\)/ \>\> Error at line \1: \2<\</' | $HEAD -1 $ECHO "Errors are (from $TIMEFILE) :"
$CAT < $TIMEFILE
$ECHO "(the last line(s) may be the ones that caused the die() in mysqltest)"
} }
prefix_to_8() { prefix_to_8() {

View File

@@ -234,3 +234,16 @@ INSERT INTO t1 VALUES (1, 'a545f661efdd1fb66fdee3aab79945bf');
SELECT 1 FROM t1 WHERE tmp=AES_DECRYPT(tmp,"password"); SELECT 1 FROM t1 WHERE tmp=AES_DECRYPT(tmp,"password");
1 1
DROP TABLE t1; DROP TABLE t1;
CREATE TABLE t1 (
wid int(10) unsigned NOT NULL auto_increment,
data_podp date default NULL,
status_wnio enum('nowy','podp','real','arch') NOT NULL default 'nowy',
PRIMARY KEY(wid),
);
INSERT INTO t1 VALUES (8,NULL,'real');
INSERT INTO t1 VALUES (9,NULL,'nowy');
SELECT elt(status_wnio,data_podp) FROM t1 GROUP BY wid;
elt(status_wnio,data_podp)
NULL
NULL
DROP TABLE t1;

View File

@@ -96,6 +96,11 @@ week(19981231,2) week(19981231,3) week(20000101,2) week(20000101,3)
select week(20001231,2),week(20001231,3); select week(20001231,2),week(20001231,3);
week(20001231,2) week(20001231,3) week(20001231,2) week(20001231,3)
1 52 1 52
set default_week_format = 2;
select week(20001231),week(20001231,2),week(20001231,0);
week(20001231) week(20001231,2) week(20001231,0)
1 1 53
set default_week_format = 0;
select date_format('1998-12-31','%x-%v'),date_format('1999-01-01','%x-%v'); select date_format('1998-12-31','%x-%v'),date_format('1999-01-01','%x-%v');
date_format('1998-12-31','%x-%v') date_format('1999-01-01','%x-%v') date_format('1998-12-31','%x-%v') date_format('1999-01-01','%x-%v')
1998-53 1998-53 1998-53 1998-53

View File

@@ -1,3 +1,4 @@
drop table if exists t1;
delete from mysql.user where user='mysqltest_1'; delete from mysql.user where user='mysqltest_1';
delete from mysql.db where user='mysqltest_1'; delete from mysql.db where user='mysqltest_1';
flush privileges; flush privileges;
@@ -64,8 +65,44 @@ GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, REFERENCES, INDEX, CREATE TE
revoke all privileges on mysqltest.* from mysqltest_1@localhost; revoke all privileges on mysqltest.* from mysqltest_1@localhost;
delete from mysql.user where user='mysqltest_1'; delete from mysql.user where user='mysqltest_1';
flush privileges; flush privileges;
grant usage on test.* to user@localhost with grant option; grant usage on test.* to mysqltest_1@localhost with grant option;
show grants for user@localhost; show grants for mysqltest_1@localhost;
Grants for user@localhost Grants for mysqltest_1@localhost
GRANT USAGE ON *.* TO 'user'@'localhost' GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost'
GRANT USAGE ON `test`.* TO 'user'@'localhost' WITH GRANT OPTION GRANT USAGE ON `mysqltest`.* TO 'mysqltest_1'@'localhost' WITH GRANT OPTION
GRANT USAGE ON `test`.* TO 'mysqltest_1'@'localhost' WITH GRANT OPTION
delete from mysql.user where user='mysqltest_1';
delete from mysql.db where user='mysqltest_1';
delete from mysql.tables_priv where user='mysqltest_1';
delete from mysql.columns_priv where user='mysqltest_1';
flush privileges;
create table t1 (a int);
GRANT select,update,insert on t1 to mysqltest_1@localhost;
GRANT select (a), update (a),insert(a), references(a) on t1 to mysqltest_1@localhost;
show grants for mysqltest_1@localhost;
Grants for mysqltest_1@localhost
GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost'
GRANT SELECT, SELECT (a), INSERT, INSERT (a), UPDATE, UPDATE (a), REFERENCES (a) ON `test`.`t1` TO 'mysqltest_1'@'localhost'
select table_priv,column_priv from mysql.tables_priv where user="mysqltest_1";
table_priv column_priv
Select,Insert,Update Select,Insert,Update,References
REVOKE select (a), update on t1 from mysqltest_1@localhost;
show grants for mysqltest_1@localhost;
Grants for mysqltest_1@localhost
GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost'
GRANT SELECT, INSERT, INSERT (a), REFERENCES (a) ON `test`.`t1` TO 'mysqltest_1'@'localhost'
REVOKE insert,insert (a) on t1 from mysqltest_1@localhost;
GRANT references on t1 to mysqltest_1@localhost;
show grants for mysqltest_1@localhost;
Grants for mysqltest_1@localhost
GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost'
GRANT SELECT, REFERENCES, REFERENCES (a) ON `test`.`t1` TO 'mysqltest_1'@'localhost'
select table_priv,column_priv from mysql.tables_priv where user="mysqltest_1";
table_priv column_priv
Select,References References
delete from mysql.user where user='mysqltest_1';
delete from mysql.db where user='mysqltest_1';
delete from mysql.tables_priv where user='mysqltest_1';
delete from mysql.columns_priv where user='mysqltest_1';
flush privileges;
drop table t1;

View File

@@ -156,7 +156,7 @@ level id parent_id
1 1007 101 1 1007 101
optimize table t1; optimize table t1;
Table Op Msg_type Msg_text Table Op Msg_type Msg_text
test.t1 optimize error The handler for the table doesn't support optimize test.t1 optimize status OK
show keys from t1; show keys from t1;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
t1 0 PRIMARY 1 id A 87 NULL NULL BTREE t1 0 PRIMARY 1 id A 87 NULL NULL BTREE
@@ -180,7 +180,7 @@ create table t1 (a int) type=innodb;
insert into t1 values (1), (2); insert into t1 values (1), (2);
optimize table t1; optimize table t1;
Table Op Msg_type Msg_text Table Op Msg_type Msg_text
test.t1 optimize error The handler for the table doesn't support optimize test.t1 optimize status OK
delete from t1 where a = 1; delete from t1 where a = 1;
select * from t1; select * from t1;
a a
@@ -712,7 +712,7 @@ world 2
hello 1 hello 1
optimize table t1; optimize table t1;
Table Op Msg_type Msg_text Table Op Msg_type Msg_text
test.t1 optimize error The handler for the table doesn't support optimize test.t1 optimize status OK
show keys from t1; show keys from t1;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
t1 0 PRIMARY 1 a A 2 NULL NULL BTREE t1 0 PRIMARY 1 a A 2 NULL NULL BTREE
@@ -1240,7 +1240,7 @@ t1 range c c 5 NULL 1 Using where
update t1 set c=a; update t1 set c=a;
explain select * from t1 where c between 1 and 10000; explain select * from t1 where c between 1 and 10000;
table type possible_keys key key_len ref rows Extra table type possible_keys key key_len ref rows Extra
t1 ALL c NULL NULL NULL 29537 Using where t1 ALL c NULL NULL NULL 27682 Using where
drop table t1,t2; drop table t1,t2;
create table t1 (id int primary key auto_increment, fk int, index index_fk (fk)) type=innodb; create table t1 (id int primary key auto_increment, fk int, index index_fk (fk)) type=innodb;
insert into t1 (id) values (null),(null),(null),(null),(null); insert into t1 (id) values (null),(null),(null),(null),(null);

View File

@@ -93,6 +93,6 @@ slave-bin.002 62 Query 1 168 use test; insert into t1 values (1)
slave-bin.002 122 Query 1 228 use test; drop table t1 slave-bin.002 122 Query 1 228 use test; drop table t1
show slave status; show slave status;
Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space
127.0.0.1 root MASTER_PORT 1 master-bin.002 276 slave-relay-bin.002 1522 master-bin.002 Yes Yes 0 0 276 1526 127.0.0.1 root MASTER_PORT 1 master-bin.002 276 slave-relay-bin.002 1563 master-bin.002 Yes Yes 0 0 276 1567
show binlog events in 'slave-bin.005' from 4; show binlog events in 'slave-bin.005' from 4;
Error when executing command SHOW BINLOG EVENTS: Could not find target log Error when executing command SHOW BINLOG EVENTS: Could not find target log

View File

@@ -21,7 +21,7 @@ Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Lo
slave start; slave start;
show slave status; show slave status;
Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space Master_Host Master_User Master_Port Connect_retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_do_db Replicate_ignore_db Last_errno Last_error Skip_counter Exec_master_log_pos Relay_log_space
127.0.0.1 root MASTER_PORT 1 master-bin.001 73 slave-relay-bin.001 4 master-bin.001 No Yes 0 0 73 4 127.0.0.1 root MASTER_PORT 1 master-bin.001 73 slave-relay-bin.001 45 master-bin.001 No Yes 0 0 73 45
slave stop; slave stop;
change master to master_log_pos=173; change master to master_log_pos=173;
slave start; slave start;

View File

@@ -5,7 +5,7 @@ Could not initialize master info structure, check permisions on master.info
slave start; slave start;
Could not initialize master info structure, check permisions on master.info Could not initialize master info structure, check permisions on master.info
change master to master_host='127.0.0.1',master_port=MASTER_PORT, master_user='root'; change master to master_host='127.0.0.1',master_port=MASTER_PORT, master_user='root';
Could not initialize master info Could not initialize master info structure, check permisions on master.info
reset slave; reset slave;
change master to master_host='127.0.0.1',master_port=MASTER_PORT, master_user='root'; change master to master_host='127.0.0.1',master_port=MASTER_PORT, master_user='root';
reset master; reset master;

View File

@@ -26,3 +26,13 @@ ORDER BY link;
key_link_id link key_link_id link
NULL NULL NULL NULL
drop table t1,t2; drop table t1,t2;
CREATE TABLE t1 (
html varchar(5) default NULL,
rin int(11) default '0',
out int(11) default '0'
) TYPE=MyISAM;
INSERT INTO t1 VALUES ('1',1,0);
SELECT DISTINCT html,SUM(out)/(SUM(rin)+1) as 'prod' FROM t1 GROUP BY rin;
html prod
1 0.00
drop table t1;

View File

@@ -125,3 +125,15 @@ CREATE TABLE t1 (id int(11) NOT NULL auto_increment, tmp text NOT NULL, KEY id (
INSERT INTO t1 VALUES (1, 'a545f661efdd1fb66fdee3aab79945bf'); INSERT INTO t1 VALUES (1, 'a545f661efdd1fb66fdee3aab79945bf');
SELECT 1 FROM t1 WHERE tmp=AES_DECRYPT(tmp,"password"); SELECT 1 FROM t1 WHERE tmp=AES_DECRYPT(tmp,"password");
DROP TABLE t1; DROP TABLE t1;
CREATE TABLE t1 (
wid int(10) unsigned NOT NULL auto_increment,
data_podp date default NULL,
status_wnio enum('nowy','podp','real','arch') NOT NULL default 'nowy',
PRIMARY KEY(wid),
);
INSERT INTO t1 VALUES (8,NULL,'real');
INSERT INTO t1 VALUES (9,NULL,'nowy');
SELECT elt(status_wnio,data_podp) FROM t1 GROUP BY wid;
DROP TABLE t1;

View File

@@ -39,6 +39,10 @@ select yearweek("2000-01-06",1) as '2000', yearweek("2001-01-06",1) as '2001', y
select week(19981231,2), week(19981231,3), week(20000101,2), week(20000101,3); select week(19981231,2), week(19981231,3), week(20000101,2), week(20000101,3);
select week(20001231,2),week(20001231,3); select week(20001231,2),week(20001231,3);
set default_week_format = 2;
select week(20001231),week(20001231,2),week(20001231,0);
set default_week_format = 0;
select date_format('1998-12-31','%x-%v'),date_format('1999-01-01','%x-%v'); select date_format('1998-12-31','%x-%v'),date_format('1999-01-01','%x-%v');
select date_format('1999-12-31','%x-%v'),date_format('2000-01-01','%x-%v'); select date_format('1999-12-31','%x-%v'),date_format('2000-01-01','%x-%v');

View File

@@ -1,3 +1,7 @@
--disable_warnings
drop table if exists t1;
--enable_warnings
# #
# Test that SSL options works properly # Test that SSL options works properly
# #
@@ -39,6 +43,32 @@ show grants for mysqltest_1@localhost;
revoke all privileges on mysqltest.* from mysqltest_1@localhost; revoke all privileges on mysqltest.* from mysqltest_1@localhost;
delete from mysql.user where user='mysqltest_1'; delete from mysql.user where user='mysqltest_1';
flush privileges; flush privileges;
grant usage on test.* to user@localhost with grant option; grant usage on test.* to mysqltest_1@localhost with grant option;
show grants for user@localhost; show grants for mysqltest_1@localhost;
delete from mysql.user where user='mysqltest_1';
delete from mysql.db where user='mysqltest_1';
delete from mysql.tables_priv where user='mysqltest_1';
delete from mysql.columns_priv where user='mysqltest_1';
flush privileges;
#
# Test what happens when you have same table and colum level grants
#
create table t1 (a int);
GRANT select,update,insert on t1 to mysqltest_1@localhost;
GRANT select (a), update (a),insert(a), references(a) on t1 to mysqltest_1@localhost;
show grants for mysqltest_1@localhost;
select table_priv,column_priv from mysql.tables_priv where user="mysqltest_1";
REVOKE select (a), update on t1 from mysqltest_1@localhost;
show grants for mysqltest_1@localhost;
REVOKE insert,insert (a) on t1 from mysqltest_1@localhost;
GRANT references on t1 to mysqltest_1@localhost;
show grants for mysqltest_1@localhost;
select table_priv,column_priv from mysql.tables_priv where user="mysqltest_1";
delete from mysql.user where user='mysqltest_1';
delete from mysql.db where user='mysqltest_1';
delete from mysql.tables_priv where user='mysqltest_1';
delete from mysql.columns_priv where user='mysqltest_1';
flush privileges;
drop table t1;

View File

@@ -16,14 +16,20 @@ system cat /dev/null > var/slave-data/master.info;
system chmod 000 var/slave-data/master.info; system chmod 000 var/slave-data/master.info;
connection slave; connection slave;
drop table if exists t1, t2, t3, t4; drop table if exists t1, t2, t3, t4;
# START SLAVE will fail because it can't read the file (mode 000) (system error 13)
--error 1201 --error 1201
slave start; slave start;
system chmod 600 var/slave-data/master.info; system chmod 600 var/slave-data/master.info;
# It will fail again because the file is empty so the slave cannot get valuable
# info about how to connect to the master from it (failure in
# init_strvar_from_file() in init_master_info()).
--error 1201 --error 1201
slave start; slave start;
--replace_result 3306 MASTER_PORT 9306 MASTER_PORT 3334 MASTER_PORT 3336 MASTER_PORT --replace_result 3306 MASTER_PORT 9306 MASTER_PORT 3334 MASTER_PORT 3336 MASTER_PORT
# Will get error 13 on Unix systems becasue file is not readable # CHANGE MASTER will fail because it first parses master.info before changing it
!eval change master to master_host='127.0.0.1',master_port=$MASTER_MYPORT, master_user='root'; # (so when master.info is bad, people have to use RESET SLAVE first).
--error 1201
eval change master to master_host='127.0.0.1',master_port=$MASTER_MYPORT, master_user='root';
reset slave; reset slave;
--replace_result 3306 MASTER_PORT 9306 MASTER_PORT 3334 MASTER_PORT 3336 MASTER_PORT --replace_result 3306 MASTER_PORT 9306 MASTER_PORT 3334 MASTER_PORT 3336 MASTER_PORT
eval change master to master_host='127.0.0.1',master_port=$MASTER_MYPORT, master_user='root'; eval change master to master_host='127.0.0.1',master_port=$MASTER_MYPORT, master_user='root';
@@ -73,12 +79,9 @@ insert into t2 values(1234);
#same value on the master #same value on the master
connection master; connection master;
save_master_pos;
set insert_id=1234; set insert_id=1234;
insert into t2 values(NULL); insert into t2 values(NULL);
connection slave; connection slave;
sync_with_master;
wait_for_slave_to_stop; wait_for_slave_to_stop;
#restart slave skipping one event #restart slave skipping one event

View File

@@ -29,3 +29,18 @@ GROUP BY t1.id
ORDER BY link; ORDER BY link;
drop table t1,t2; drop table t1,t2;
#
# test case for #674
#
CREATE TABLE t1 (
html varchar(5) default NULL,
rin int(11) default '0',
out int(11) default '0'
) TYPE=MyISAM;
INSERT INTO t1 VALUES ('1',1,0);
SELECT DISTINCT html,SUM(out)/(SUM(rin)+1) as 'prod' FROM t1 GROUP BY rin;
drop table t1;

View File

@@ -253,15 +253,27 @@ void symdirget(char *dir)
} }
#endif /* USE_SYMDIR */ #endif /* USE_SYMDIR */
/* Unpacks dirname to name that can be used by open... */
/* Make that last char of to is '/' if from not empty and /*
from doesn't end in FN_DEVCHAR */ Fixes a directroy name so that can be used by open()
/* Uses cleanup_dirname and changes ~/.. to home_dir/.. */
/* Returns length of new directory */ SYNOPSIS
unpack_dirname()
to Store result here. May be = from
from 'Packed' directory name (may contain ~)
IMPLEMENTATION
Make that last char of to is '/' if from not empty and
from doesn't end in FN_DEVCHAR
Uses cleanup_dirname and changes ~/.. to home_dir/..
Changes a UNIX filename to system filename (replaces / with \ on windows)
RETURN
Length of new directory name (= length of to)
*/
uint unpack_dirname(my_string to, const char *from) uint unpack_dirname(my_string to, const char *from)
/* to may be == from */
{ {
uint length,h_length; uint length,h_length;
char buff[FN_REFLEN+1+4],*suffix,*tilde_expansion; char buff[FN_REFLEN+1+4],*suffix,*tilde_expansion;

View File

@@ -114,8 +114,8 @@ sql_yacc.o: sql_yacc.cc sql_yacc.h
$(CXXCOMPILE) $(LM_CFLAGS) -c $< $(CXXCOMPILE) $(LM_CFLAGS) -c $<
lex_hash.h: lex.h gen_lex_hash.cc sql_yacc.h lex_hash.h: lex.h gen_lex_hash.cc sql_yacc.h
$(MAKE) gen_lex_hash $(MAKE) gen_lex_hash$(EXEEXT)
./gen_lex_hash > $@ ./gen_lex_hash$(EXEEXT) > $@
# Hack to ensure that lex_hash.h is built early # Hack to ensure that lex_hash.h is built early
sql_lex.o: lex_hash.h sql_lex.o: lex_hash.h

View File

@@ -1863,7 +1863,11 @@ build_template(
if (prebuilt->read_just_key) { if (prebuilt->read_just_key) {
/* MySQL has instructed us that it is enough to /* MySQL has instructed us that it is enough to
fetch the columns in the key */ fetch the columns in the key; looks like MySQL
can set this flag also when there is only a
prefix of the column in the key: in that case we
retrieve the whole column from the clustered
index */
fetch_all_in_key = TRUE; fetch_all_in_key = TRUE;
} else { } else {
@@ -1924,9 +1928,8 @@ build_template(
field = table->field[i]; field = table->field[i];
if (templ_type == ROW_MYSQL_REC_FIELDS if (templ_type == ROW_MYSQL_REC_FIELDS
&& !(fetch_all_in_key && && !(fetch_all_in_key
ULINT_UNDEFINED != dict_index_get_nth_col_pos( && dict_index_contains_col_or_prefix(index, i))
index, i))
&& thd->query_id != field->query_id && thd->query_id != field->query_id
&& thd->query_id != (field->query_id ^ MAX_ULONG_BIT) && thd->query_id != (field->query_id ^ MAX_ULONG_BIT)
&& thd->query_id != && thd->query_id !=
@@ -4127,6 +4130,12 @@ ha_innobase::analyze(
return(0); return(0);
} }
int ha_innobase::optimize(THD* thd, HA_CHECK_OPT* check_opt)
{
return ha_innobase::analyze(thd,check_opt);
}
/*********************************************************************** /***********************************************************************
Tries to check that an InnoDB table is not corrupted. If corruption is Tries to check that an InnoDB table is not corrupted. If corruption is
noticed, prints to stderr information about it. In case of corruption noticed, prints to stderr information about it. In case of corruption

View File

@@ -159,6 +159,7 @@ class ha_innobase: public handler
void position(const byte *record); void position(const byte *record);
void info(uint); void info(uint);
int analyze(THD* thd,HA_CHECK_OPT* check_opt); int analyze(THD* thd,HA_CHECK_OPT* check_opt);
int optimize(THD* thd,HA_CHECK_OPT* check_opt);
int extra(enum ha_extra_function operation); int extra(enum ha_extra_function operation);
int reset(void); int reset(void);
int external_lock(THD *thd, int lock_type); int external_lock(THD *thd, int lock_type);

View File

@@ -1539,37 +1539,46 @@ void Item_func_elt::update_used_tables()
double Item_func_elt::val() double Item_func_elt::val()
{ {
uint tmp; uint tmp;
null_value=1;
if ((tmp=(uint) item->val_int()) == 0 || tmp > arg_count) if ((tmp=(uint) item->val_int()) == 0 || tmp > arg_count)
{
null_value=1;
return 0.0; return 0.0;
}
double result= args[tmp-1]->val();
if (args[tmp-1]->is_null())
return 0.0;
null_value=0; null_value=0;
return args[tmp-1]->val(); return result;
} }
longlong Item_func_elt::val_int() longlong Item_func_elt::val_int()
{ {
uint tmp; uint tmp;
null_value=1;
if ((tmp=(uint) item->val_int()) == 0 || tmp > arg_count) if ((tmp=(uint) item->val_int()) == 0 || tmp > arg_count)
{
null_value=1;
return 0; return 0;
}
int result= args[tmp-1]->val_int();
if (args[tmp-1]->is_null())
return 0;
null_value=0; null_value=0;
return args[tmp-1]->val_int(); return result;
} }
String *Item_func_elt::val_str(String *str) String *Item_func_elt::val_str(String *str)
{ {
uint tmp; uint tmp;
null_value=1;
if ((tmp=(uint) item->val_int()) == 0 || tmp > arg_count) if ((tmp=(uint) item->val_int()) == 0 || tmp > arg_count)
{
null_value=1;
return NULL; return NULL;
}
String *result= args[tmp-1]->val_str(str);
if (args[tmp-1]->is_null())
return NULL;
null_value=0; null_value=0;
return args[tmp-1]->val_str(str); return result;
} }

View File

@@ -100,7 +100,7 @@ static void pretty_print_str(String* packet, char* str, int len)
static inline char* slave_load_file_stem(char*buf, uint file_id, static inline char* slave_load_file_stem(char*buf, uint file_id,
int event_server_id) int event_server_id)
{ {
fn_format(buf,"SQL_LOAD-",slave_load_tmpdir,"",0); /* 4+32); */ fn_format(buf,"SQL_LOAD-",slave_load_tmpdir, "", MY_UNPACK_FILENAME);
buf = strend(buf); buf = strend(buf);
buf = int10_to_str(::server_id, buf, 10); buf = int10_to_str(::server_id, buf, 10);
*buf++ = '-'; *buf++ = '-';
@@ -168,19 +168,22 @@ static void cleanup_load_tmpdir()
uint i; uint i;
if (!(dirp=my_dir(slave_load_tmpdir,MYF(MY_WME)))) if (!(dirp=my_dir(slave_load_tmpdir,MYF(MY_WME))))
return; return;
char fname[FN_REFLEN];
for (i=0 ; i < (uint)dirp->number_off_files; i++) for (i=0 ; i < (uint)dirp->number_off_files; i++)
{ {
file=dirp->dir_entry+i; file=dirp->dir_entry+i;
if (is_prefix(file->name,"SQL_LOAD-")) if (is_prefix(file->name,"SQL_LOAD-"))
my_delete(file->name, MYF(0)); {
fn_format(fname,file->name,slave_load_tmpdir,"",MY_UNPACK_FILENAME);
my_delete(fname, MYF(0));
}
} }
my_dirend(dirp); my_dirend(dirp);
} }
#endif #endif
Log_event::Log_event(const char* buf, bool old_format) Log_event::Log_event(const char* buf, bool old_format)
:temp_buf(0), cached_event_len(0), cache_stmt(0) :temp_buf(0), cached_event_len(0), cache_stmt(0)
{ {
@@ -813,7 +816,7 @@ Rotate_log_event::Rotate_log_event(const char* buf, int event_len,
int Rotate_log_event::write_data(IO_CACHE* file) int Rotate_log_event::write_data(IO_CACHE* file)
{ {
char buf[ROTATE_HEADER_LEN]; char buf[ROTATE_HEADER_LEN];
int8store(buf, pos + R_POS_OFFSET); int8store(buf + R_POS_OFFSET, pos);
return (my_b_safe_write(file, (byte*)buf, ROTATE_HEADER_LEN) || return (my_b_safe_write(file, (byte*)buf, ROTATE_HEADER_LEN) ||
my_b_safe_write(file, (byte*)new_log_ident, (uint) ident_len)); my_b_safe_write(file, (byte*)new_log_ident, (uint) ident_len));
} }

View File

@@ -2322,6 +2322,12 @@ The server will not act as a slave.");
opt_binlog_index_name,LOG_BIN); opt_binlog_index_name,LOG_BIN);
using_update_log=1; using_update_log=1;
} }
else if (opt_log_slave_updates)
{
sql_print_error("\
Warning: you need to use --log-bin to make --log-slave-updates work. \
Now disabling --log-slave-updates.");
}
if (opt_bootstrap) if (opt_bootstrap)
{ {
@@ -3179,7 +3185,8 @@ enum options {
OPT_BDB_CACHE_SIZE, OPT_BDB_CACHE_SIZE,
OPT_BDB_LOG_BUFFER_SIZE, OPT_BDB_LOG_BUFFER_SIZE,
OPT_BDB_MAX_LOCK, OPT_BDB_MAX_LOCK,
OPT_ERROR_LOG_FILE OPT_ERROR_LOG_FILE,
OPT_DEFAULT_WEEK_FORMAT
}; };
@@ -3988,6 +3995,11 @@ replicating a LOAD DATA INFILE command",
(gptr*) &global_system_variables.net_wait_timeout, (gptr*) &global_system_variables.net_wait_timeout,
(gptr*) &max_system_variables.net_wait_timeout, 0, GET_ULONG, (gptr*) &max_system_variables.net_wait_timeout, 0, GET_ULONG,
REQUIRED_ARG, NET_WAIT_TIMEOUT, 1, LONG_TIMEOUT, 0, 1, 0}, REQUIRED_ARG, NET_WAIT_TIMEOUT, 1, LONG_TIMEOUT, 0, 1, 0},
{ "default-week-format", OPT_DEFAULT_WEEK_FORMAT,
"The default week format used by WEEK() functions.",
(gptr*) &global_system_variables.default_week_format,
(gptr*) &max_system_variables.default_week_format,
0, GET_ULONG, REQUIRED_ARG, 0, 0, 3L, 0, 1, 0},
{0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0} {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
}; };

View File

@@ -462,7 +462,7 @@ BOOL NTService::SeekStatus(LPCSTR szInternName, int OperationType)
{ {
/* a remove operation */ /* a remove operation */
if (!(service = OpenService(scm,szInternName, SERVICE_ALL_ACCESS ))) if (!(service = OpenService(scm,szInternName, SERVICE_ALL_ACCESS )))
printf("The service doesn't exists!\n"); printf("The service doesn't exist!\n");
else else
{ {
SERVICE_STATUS ss; SERVICE_STATUS ss;

View File

@@ -296,6 +296,8 @@ static sys_var_slave_skip_counter sys_slave_skip_counter("sql_slave_skip_counter
static sys_var_rand_seed1 sys_rand_seed1("rand_seed1"); static sys_var_rand_seed1 sys_rand_seed1("rand_seed1");
static sys_var_rand_seed2 sys_rand_seed2("rand_seed2"); static sys_var_rand_seed2 sys_rand_seed2("rand_seed2");
static sys_var_thd_ulong sys_default_week_format("default_week_format",
&SV::default_week_format);
/* /*
List of all variables for initialisation and storage in hash List of all variables for initialisation and storage in hash
@@ -316,6 +318,7 @@ sys_var *sys_variables[]=
&sys_bulk_insert_buff_size, &sys_bulk_insert_buff_size,
&sys_concurrent_insert, &sys_concurrent_insert,
&sys_connect_timeout, &sys_connect_timeout,
&sys_default_week_format,
&sys_convert_charset, &sys_convert_charset,
&sys_delay_key_write, &sys_delay_key_write,
&sys_delayed_insert_limit, &sys_delayed_insert_limit,
@@ -421,6 +424,7 @@ struct show_var_st init_vars[]= {
{sys_connect_timeout.name, (char*) &sys_connect_timeout, SHOW_SYS}, {sys_connect_timeout.name, (char*) &sys_connect_timeout, SHOW_SYS},
{sys_convert_charset.name, (char*) &sys_convert_charset, SHOW_SYS}, {sys_convert_charset.name, (char*) &sys_convert_charset, SHOW_SYS},
{"datadir", mysql_real_data_home, SHOW_CHAR}, {"datadir", mysql_real_data_home, SHOW_CHAR},
{"default_week_format", (char*) &sys_default_week_format, SHOW_SYS},
{sys_delay_key_write.name, (char*) &sys_delay_key_write, SHOW_SYS}, {sys_delay_key_write.name, (char*) &sys_delay_key_write, SHOW_SYS},
{sys_delayed_insert_limit.name, (char*) &sys_delayed_insert_limit,SHOW_SYS}, {sys_delayed_insert_limit.name, (char*) &sys_delayed_insert_limit,SHOW_SYS},
{sys_delayed_insert_timeout.name, (char*) &sys_delayed_insert_timeout, SHOW_SYS}, {sys_delayed_insert_timeout.name, (char*) &sys_delayed_insert_timeout, SHOW_SYS},

View File

@@ -134,7 +134,7 @@ int init_slave()
goto err; goto err;
} }
if(init_master_info(active_mi,master_info_file,relay_log_info_file, if (init_master_info(active_mi,master_info_file,relay_log_info_file,
!master_host)) !master_host))
{ {
sql_print_error("Failed to initialize the master info structure"); sql_print_error("Failed to initialize the master info structure");
@@ -1644,6 +1644,7 @@ int show_master_info(THD* thd, MASTER_INFO* mi)
if (mi->host[0]) if (mi->host[0])
{ {
DBUG_PRINT("info",("host is set: '%s'", mi->host));
String *packet= &thd->packet; String *packet= &thd->packet;
packet->length(0); packet->length(0);
@@ -1776,18 +1777,17 @@ int st_relay_log_info::wait_for_pos(THD* thd, String* log_name,
pthread_mutex_lock(&data_lock); pthread_mutex_lock(&data_lock);
/* /*
This function will abort when it notices that This function will abort when it notices that some CHANGE MASTER or
some CHANGE MASTER or RESET MASTER has changed RESET MASTER has changed the master info.
the master info. To catch this, these commands To catch this, these commands modify abort_pos_wait ; We just monitor
modify abort_pos_wait ; we just monitor abort_pos_wait abort_pos_wait and see if it has changed.
and see if it has changed. Why do we have this mechanism instead of simply monitoring slave_running
Why do we have this mechanism instead of simply monitoring slave_running in in the loop (we do this too), as CHANGE MASTER/RESET SLAVE require that
the loop (we do this too), as CHANGE MASTER/RESET SLAVE require that the the SQL thread be stopped?
SQL thread be stopped? This is in case This is becasue if someones does:
STOP SLAVE;CHANGE MASTER/RESET SLAVE; START SLAVE; STOP SLAVE;CHANGE MASTER/RESET SLAVE; START SLAVE;
happens very quickly between the moment pthread_cond_wait() wakes up and the change may happen very quickly and we may not notice that
the while() is evaluated: in that case slave_running is again 1 when the slave_running briefly switches between 1/0/1.
while() is evaluated.
*/ */
init_abort_pos_wait= abort_pos_wait; init_abort_pos_wait= abort_pos_wait;
@@ -1808,7 +1808,7 @@ int st_relay_log_info::wait_for_pos(THD* thd, String* log_name,
error= -2; //means improper arguments error= -2; //means improper arguments
goto err; goto err;
} }
//p points to '.' /* p points to '.' */
log_name_extension= strtoul(++p, &p_end, 10); log_name_extension= strtoul(++p, &p_end, 10);
/* /*
p_end points to the first invalid character. p_end points to the first invalid character.
@@ -1821,14 +1821,9 @@ int st_relay_log_info::wait_for_pos(THD* thd, String* log_name,
goto err; goto err;
} }
//"compare and wait" main loop /* The "compare and wait" main loop */
while (!thd->killed && while (!thd->killed &&
init_abort_pos_wait == abort_pos_wait && init_abort_pos_wait == abort_pos_wait &&
/*
formerly we tested mi->slave_running, but what we care about is
rli->slave_running (because this concerns the SQL thread, while
mi->slave_running concerns the I/O thread).
*/
slave_running) slave_running)
{ {
bool pos_reached; bool pos_reached;

View File

@@ -1,4 +1,4 @@
/* Copyright (C) 2000 MySQL AB /* Copyright (C) 2000-2003 MySQL AB
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -193,7 +193,7 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables)
host.db= get_field(&mem, table,1); host.db= get_field(&mem, table,1);
host.access= get_access(table,2); host.access= get_access(table,2);
host.access= fix_rights_for_db(host.access); host.access= fix_rights_for_db(host.access);
host.sort= get_sort(2,host.host.hostname,host.db); host.sort= get_sort(2,host.host.hostname,host.db);
#ifndef TO_BE_REMOVED #ifndef TO_BE_REMOVED
if (table->fields == 8) if (table->fields == 8)
{ // Without grant { // Without grant
@@ -213,8 +213,7 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables)
if (table->field[2]->field_length == 8 && if (table->field[2]->field_length == 8 &&
protocol_version == PROTOCOL_VERSION) protocol_version == PROTOCOL_VERSION)
{ {
sql_print_error( sql_print_error("Old 'user' table. (Check README or the Reference manual). Continuing --old-protocol"); /* purecov: tested */
"Old 'user' table. (Check README or the Reference manual). Continuing --old-protocol"); /* purecov: tested */
protocol_version=9; /* purecov: tested */ protocol_version=9; /* purecov: tested */
} }
@@ -247,7 +246,7 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables)
user.sort=get_sort(2,user.host.hostname,user.user); user.sort=get_sort(2,user.host.hostname,user.user);
user.hostname_length= (user.host.hostname ? user.hostname_length= (user.host.hostname ?
(uint) strlen(user.host.hostname) : 0); (uint) strlen(user.host.hostname) : 0);
if (table->fields >= 31) /* Starting from 4.0.2 we have more fields */ if (table->fields >= 31) /* Starting from 4.0.2 we have more fields */
{ {
char *ssl_type=get_field(&mem, table, 24); char *ssl_type=get_field(&mem, table, 24);
if (!ssl_type) if (!ssl_type)
@@ -259,7 +258,7 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables)
else /* !strcmp(ssl_type, "SPECIFIED") */ else /* !strcmp(ssl_type, "SPECIFIED") */
user.ssl_type=SSL_TYPE_SPECIFIED; user.ssl_type=SSL_TYPE_SPECIFIED;
user.ssl_cipher= get_field(&mem, table, 25); user.ssl_cipher= get_field(&mem, table, 25);
user.x509_issuer= get_field(&mem, table, 26); user.x509_issuer= get_field(&mem, table, 26);
user.x509_subject= get_field(&mem, table, 27); user.x509_subject= get_field(&mem, table, 27);
@@ -368,7 +367,14 @@ void acl_free(bool end)
} }
} }
/* Reload acl list if possible */
/*
Forget current privileges and read new privileges from the privilege tables
SYNOPSIS
acl_reload()
thd Thread handle
*/
void acl_reload(THD *thd) void acl_reload(THD *thd)
{ {
@@ -493,8 +499,8 @@ static int acl_compare(ACL_ACCESS *a,ACL_ACCESS *b)
ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user, ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
const char *password,const char *message, const char *password,const char *message,
char **priv_user, char *priv_host, char **priv_user, char *priv_host,
bool old_ver, USER_RESOURCES *mqh) bool old_ver, USER_RESOURCES *mqh)
{ {
ulong user_access=NO_ACCESS; ulong user_access=NO_ACCESS;
*priv_user=(char*) user; *priv_user=(char*) user;
@@ -526,15 +532,15 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
{ {
#ifdef HAVE_OPENSSL #ifdef HAVE_OPENSSL
Vio *vio=thd->net.vio; Vio *vio=thd->net.vio;
/* /*
In this point we know that user is allowed to connect In this point we know that user is allowed to connect
from given host by given username/password pair. Now from given host by given username/password pair. Now
we check if SSL is required, if user is using SSL and we check if SSL is required, if user is using SSL and
if X509 certificate attributes are OK if X509 certificate attributes are OK
*/ */
switch (acl_user->ssl_type) { switch (acl_user->ssl_type) {
case SSL_TYPE_NOT_SPECIFIED: // Impossible case SSL_TYPE_NOT_SPECIFIED: // Impossible
case SSL_TYPE_NONE: /* SSL is not required to connect */ case SSL_TYPE_NONE: /* SSL is not required to connect */
user_access=acl_user->access; user_access=acl_user->access;
break; break;
case SSL_TYPE_ANY: /* Any kind of SSL is good enough */ case SSL_TYPE_ANY: /* Any kind of SSL is good enough */
@@ -544,7 +550,7 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
case SSL_TYPE_X509: /* Client should have any valid certificate. */ case SSL_TYPE_X509: /* Client should have any valid certificate. */
/* /*
We need to check for absence of SSL because without SSL We need to check for absence of SSL because without SSL
we should reject connection. we should reject connection.
*/ */
if (vio_type(vio) == VIO_TYPE_SSL && SSL_get_peer_certificate(vio->ssl_)) if (vio_type(vio) == VIO_TYPE_SSL && SSL_get_peer_certificate(vio->ssl_))
user_access=acl_user->access; user_access=acl_user->access;
@@ -653,12 +659,12 @@ static byte* check_get_key(ACL_USER *buff,uint *length,
} }
static void acl_update_user(const char *user, const char *host, static void acl_update_user(const char *user, const char *host,
const char *password, const char *password,
enum SSL_type ssl_type, enum SSL_type ssl_type,
const char *ssl_cipher, const char *ssl_cipher,
const char *x509_issuer, const char *x509_issuer,
const char *x509_subject, const char *x509_subject,
USER_RESOURCES *mqh, USER_RESOURCES *mqh,
ulong privileges) ulong privileges)
{ {
for (uint i=0 ; i < acl_users.elements ; i++) for (uint i=0 ; i < acl_users.elements ; i++)
@@ -707,7 +713,7 @@ static void acl_update_user(const char *user, const char *host,
static void acl_insert_user(const char *user, const char *host, static void acl_insert_user(const char *user, const char *host,
const char *password, const char *password,
enum SSL_type ssl_type, enum SSL_type ssl_type,
const char *ssl_cipher, const char *ssl_cipher,
const char *x509_issuer, const char *x509_issuer,
@@ -805,9 +811,10 @@ static void acl_insert_db(const char *user, const char *host, const char *db,
} }
/*****************************************************************************
** Get privilege for a host, user and db combination /*
*****************************************************************************/ Get privilege for a host, user and db combination
*/
ulong acl_get(const char *host, const char *ip, const char *bin_ip, ulong acl_get(const char *host, const char *ip, const char *bin_ip,
const char *user, const char *db) const char *user, const char *db)
@@ -929,11 +936,14 @@ int wild_case_compare(const char *str,const char *wildstr)
DBUG_RETURN (*str != '\0'); DBUG_RETURN (*str != '\0');
} }
/*****************************************************************************
** check if there are any possible matching entries for this host /*
** All host names without wild cards are stored in a hash table, Check if there are any possible matching entries for this host
** entries with wildcards are stored in a dynamic array
*****************************************************************************/ NOTES
All host names without wild cards are stored in a hash table,
entries with wildcards are stored in a dynamic array
*/
static void init_check_host(void) static void init_check_host(void)
{ {
@@ -1006,10 +1016,6 @@ bool acl_check_host(const char *host, const char *ip)
return 1; // Host is not allowed return 1; // Host is not allowed
} }
/*****************************************************************************
Change password for the user if it's not an anonymous user
Note: This should write the error directly to the client!
*****************************************************************************/
/* /*
Check if the user is allowed to change password Check if the user is allowed to change password
@@ -1021,8 +1027,8 @@ bool acl_check_host(const char *host, const char *ip)
user user name user user name
RETURN VALUE RETURN VALUE
0 OK 0 OK
1 ERROR ; In this case the error is sent to the client. 1 ERROR ; In this case the error is sent to the client.
*/ */
bool check_change_password(THD *thd, const char *host, const char *user) bool check_change_password(THD *thd, const char *host, const char *user)
@@ -1061,7 +1067,7 @@ bool check_change_password(THD *thd, const char *host, const char *user)
RETURN VALUES RETURN VALUES
0 ok 0 ok
1 ERROR; In this case the error is sent to the client. 1 ERROR; In this case the error is sent to the client.
*/ */
bool change_password(THD *thd, const char *host, const char *user, bool change_password(THD *thd, const char *host, const char *user,
char *new_password) char *new_password)
@@ -1127,7 +1133,7 @@ find_acl_user(const char *host, const char *user)
{ {
ACL_USER *acl_user=dynamic_element(&acl_users,i,ACL_USER*); ACL_USER *acl_user=dynamic_element(&acl_users,i,ACL_USER*);
DBUG_PRINT("info",("strcmp('%s','%s'), compare_hostname('%s','%s'),", DBUG_PRINT("info",("strcmp('%s','%s'), compare_hostname('%s','%s'),",
user,acl_user->user,(host),(acl_user->host))); user,acl_user->user,(host),(acl_user->host)));
if (!acl_user->user && !user[0] || if (!acl_user->user && !user[0] ||
acl_user->user && !strcmp(user,acl_user->user)) acl_user->user && !strcmp(user,acl_user->user))
{ {
@@ -1140,15 +1146,18 @@ find_acl_user(const char *host, const char *user)
DBUG_RETURN(0); DBUG_RETURN(0);
} }
/*****************************************************************************
Handle comparing of hostname
A hostname may be of type:
hostname (May include wildcards); monty.pp.sci.fi
ip (May include wildcards); 192.168.0.0
ip/netmask 192.168.0.0/255.255.255.0
A net mask of 0.0.0.0 is not allowed. /*
*****************************************************************************/ Comparing of hostnames
NOTES
A hostname may be of type:
hostname (May include wildcards); monty.pp.sci.fi
ip (May include wildcards); 192.168.0.0
ip/netmask 192.168.0.0/255.255.255.0
A net mask of 0.0.0.0 is not allowed.
*/
static const char *calc_ip(const char *ip, long *val, char end) static const char *calc_ip(const char *ip, long *val, char end)
{ {
@@ -1195,9 +1204,9 @@ static bool compare_hostname(const acl_host_and_ip *host, const char *hostname,
} }
/**************************************************************************** /*
Code to update grants in the user and database privilege tables Update grants in the user and database privilege tables
****************************************************************************/ */
static bool update_user_table(THD *thd, const char *host, const char *user, static bool update_user_table(THD *thd, const char *host, const char *user,
const char *new_password) const char *new_password)
@@ -1263,7 +1272,7 @@ static bool test_if_create_new_users(THD *thd)
/**************************************************************************** /****************************************************************************
** Handle GRANT commands Handle GRANT commands
****************************************************************************/ ****************************************************************************/
static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo, static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo,
@@ -1285,8 +1294,8 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo,
if (combo.password.length != HASH_PASSWORD_LENGTH) if (combo.password.length != HASH_PASSWORD_LENGTH)
{ {
my_printf_error(ER_PASSWORD_NO_MATCH, my_printf_error(ER_PASSWORD_NO_MATCH,
"Password hash should be a %d-digit hexadecimal number", "Password hash should be a %d-digit hexadecimal number",
MYF(0),HASH_PASSWORD_LENGTH); MYF(0),HASH_PASSWORD_LENGTH);
DBUG_RETURN(-1); DBUG_RETURN(-1);
} }
password=combo.password.str; password=combo.password.str;
@@ -1459,7 +1468,7 @@ static int replace_db_table(TABLE *table, const char *db,
char what= (revoke_grant) ? 'N' : 'Y'; char what= (revoke_grant) ? 'N' : 'Y';
DBUG_ENTER("replace_db_table"); DBUG_ENTER("replace_db_table");
// is there such a user in user table in memory ???? /* Check if there is such a user in user table in memory? */
if (!initialized || !find_acl_user(combo.host.str,combo.user.str)) if (!initialized || !find_acl_user(combo.host.str,combo.user.str))
{ {
my_error(ER_PASSWORD_NO_MATCH,MYF(0)); my_error(ER_PASSWORD_NO_MATCH,MYF(0));
@@ -1471,7 +1480,7 @@ static int replace_db_table(TABLE *table, const char *db,
table->field[2]->store(combo.user.str,combo.user.length); table->field[2]->store(combo.user.str,combo.user.length);
table->file->index_init(0); table->file->index_init(0);
if (table->file->index_read(table->record[0],(byte*) table->field[0]->ptr,0, if (table->file->index_read(table->record[0],(byte*) table->field[0]->ptr,0,
HA_READ_KEY_EXACT)) HA_READ_KEY_EXACT))
{ {
if (what == 'N') if (what == 'N')
{ // no row, no revoke { // no row, no revoke
@@ -1502,7 +1511,7 @@ static int replace_db_table(TABLE *table, const char *db,
if (old_row_exists) if (old_row_exists)
{ {
// update old existing row /* update old existing row */
if (rights) if (rights)
{ {
if ((error=table->file->update_row(table->record[1],table->record[0]))) if ((error=table->file->update_row(table->record[1],table->record[0])))
@@ -1529,11 +1538,11 @@ static int replace_db_table(TABLE *table, const char *db,
DBUG_RETURN(0); DBUG_RETURN(0);
/* This could only happen if the grant tables got corrupted */ /* This could only happen if the grant tables got corrupted */
table_error: table_error:
table->file->print_error(error,MYF(0)); /* purecov: deadcode */ table->file->print_error(error,MYF(0)); /* purecov: deadcode */
table->file->index_end(); table->file->index_end();
abort: abort:
DBUG_RETURN(-1); DBUG_RETURN(-1);
} }
@@ -1649,7 +1658,7 @@ public:
if (!(mem_check = new GRANT_COLUMN(*res, if (!(mem_check = new GRANT_COLUMN(*res,
fix_rights_for_column(priv)))) fix_rights_for_column(priv))))
{ {
// Don't use this entry /* Don't use this entry */
privs = cols = 0; /* purecov: deadcode */ privs = cols = 0; /* purecov: deadcode */
return; /* purecov: deadcode */ return; /* purecov: deadcode */
} }
@@ -1827,7 +1836,7 @@ static int replace_column_table(GRANT_TABLE *g_t,
key_length, HA_READ_KEY_EXACT)) key_length, HA_READ_KEY_EXACT))
goto end; goto end;
// Scan trough all rows with the same host,db,user and table /* Scan through all rows with the same host,db,user and table */
do do
{ {
ulong privileges = (ulong) table->field[6]->val_int(); ulong privileges = (ulong) table->field[6]->val_int();
@@ -1877,7 +1886,7 @@ static int replace_column_table(GRANT_TABLE *g_t,
!key_cmp(table,key,0,key_length)); !key_cmp(table,key,0,key_length));
} }
end: end:
table->file->index_end(); table->file->index_end();
DBUG_RETURN(result); DBUG_RETURN(result);
} }
@@ -1947,7 +1956,7 @@ static int replace_table_table(THD *thd, GRANT_TABLE *grant_table,
if (revoke_grant) if (revoke_grant)
{ {
// column rights are already fixed in mysql_table_grant ! /* column rights are already fixed in mysql_table_grant */
store_table_rights=j & ~store_table_rights; store_table_rights=j & ~store_table_rights;
} }
else else
@@ -1983,7 +1992,7 @@ static int replace_table_table(THD *thd, GRANT_TABLE *grant_table,
if (rights | col_rights) if (rights | col_rights)
{ {
grant_table->privs= rights; grant_table->privs= rights;
grant_table->cols= col_rights; grant_table->cols= col_rights;
} }
else else
{ {
@@ -1991,19 +2000,36 @@ static int replace_table_table(THD *thd, GRANT_TABLE *grant_table,
} }
DBUG_RETURN(0); DBUG_RETURN(0);
/* This should never happen */ /* This should never happen */
table_error: table_error:
table->file->print_error(error,MYF(0)); /* purecov: deadcode */ table->file->print_error(error,MYF(0)); /* purecov: deadcode */
DBUG_RETURN(-1); /* purecov: deadcode */ DBUG_RETURN(-1); /* purecov: deadcode */
} }
/*
Store table level and column level grants in the privilege tables
SYNOPSIS
mysql_table_grant()
thd Thread handle
table_list List of tables to give grant
user_list List of users to give grant
columns List of columns to give grant
rights Table level grant
revoke_grant Set to 1 if this is a REVOKE command
RETURN
0 ok
1 error
*/
int mysql_table_grant(THD *thd, TABLE_LIST *table_list, int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
List <LEX_USER> &user_list, List <LEX_USER> &user_list,
List <LEX_COLUMN> &columns, ulong rights, List <LEX_COLUMN> &columns, ulong rights,
bool revoke_grant) bool revoke_grant)
{ {
ulong column_priv = 0; ulong column_priv= 0;
List_iterator <LEX_USER> str_list (user_list); List_iterator <LEX_USER> str_list (user_list);
LEX_USER *Str; LEX_USER *Str;
TABLE_LIST tables[3]; TABLE_LIST tables[3];
@@ -2024,21 +2050,21 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
if (columns.elements && !revoke_grant) if (columns.elements && !revoke_grant)
{ {
TABLE *table; TABLE *table;
class LEX_COLUMN *check; class LEX_COLUMN *column;
List_iterator <LEX_COLUMN> iter(columns); List_iterator <LEX_COLUMN> column_iter(columns);
if (!(table=open_ltable(thd,table_list,TL_READ))) if (!(table=open_ltable(thd,table_list,TL_READ)))
DBUG_RETURN(-1); DBUG_RETURN(-1);
while ((check = iter++)) while ((column = column_iter++))
{ {
if (!find_field_in_table(thd,table,check->column.ptr(), if (!find_field_in_table(thd,table,column->column.ptr(),
check->column.length(),0,0)) column->column.length(),0,0))
{ {
my_printf_error(ER_BAD_FIELD_ERROR,ER(ER_BAD_FIELD_ERROR),MYF(0), my_printf_error(ER_BAD_FIELD_ERROR,ER(ER_BAD_FIELD_ERROR),MYF(0),
check->column.c_ptr(), table_list->alias); column->column.c_ptr(), table_list->alias);
DBUG_RETURN(-1); DBUG_RETURN(-1);
} }
column_priv |= check->rights | (rights & COL_ACLS); column_priv|= column->rights;
} }
close_thread_tables(thd); close_thread_tables(thd);
} }
@@ -2148,21 +2174,21 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
/* If revoke_grant, calculate the new column privilege for tables_priv */ /* If revoke_grant, calculate the new column privilege for tables_priv */
if (revoke_grant) if (revoke_grant)
{ {
class LEX_COLUMN *check; class LEX_COLUMN *column;
List_iterator <LEX_COLUMN> iter(columns); List_iterator <LEX_COLUMN> column_iter(columns);
GRANT_COLUMN *grant_column; GRANT_COLUMN *grant_column;
/* Fix old grants */ /* Fix old grants */
while ((check = iter++)) while ((column = column_iter++))
{ {
grant_column = column_hash_search(grant_table, grant_column = column_hash_search(grant_table,
check->column.ptr(), column->column.ptr(),
check->column.length()); column->column.length());
if (grant_column) if (grant_column)
grant_column->rights&= ~(check->rights | rights); grant_column->rights&= ~(column->rights | rights);
} }
/* scan trough all columns to get new column grant */ /* scan trough all columns to get new column grant */
column_priv=0; column_priv= 0;
for (uint idx=0 ; idx < grant_table->hash_columns.records ; idx++) for (uint idx=0 ; idx < grant_table->hash_columns.records ; idx++)
{ {
grant_column= (GRANT_COLUMN*) hash_element(&grant_table->hash_columns, grant_column= (GRANT_COLUMN*) hash_element(&grant_table->hash_columns,
@@ -2259,7 +2285,7 @@ int mysql_grant (THD *thd, const char *db, List <LEX_USER> &list,
if (!revoke_grant) if (!revoke_grant)
create_new_users= test_if_create_new_users(thd); create_new_users= test_if_create_new_users(thd);
// go through users in user_list /* go through users in user_list */
pthread_mutex_lock(&LOCK_grant); pthread_mutex_lock(&LOCK_grant);
VOID(pthread_mutex_lock(&acl_cache->lock)); VOID(pthread_mutex_lock(&acl_cache->lock));
grant_version++; grant_version++;
@@ -2280,7 +2306,7 @@ int mysql_grant (THD *thd, const char *db, List <LEX_USER> &list,
continue; continue;
} }
if ((replace_user_table(thd, if ((replace_user_table(thd,
tables[0].table, tables[0].table,
*Str, *Str,
(!db ? rights : 0), revoke_grant, (!db ? rights : 0), revoke_grant,
create_new_users))) create_new_users)))
@@ -2410,7 +2436,16 @@ end:
} }
/* Reload grant array if possible */ /*
Reload grant array if possible
SYNOPSIS
grant_reload()
thd Thread handler
NOTES
Locked tables are checked by acl_init and doesn't have to be checked here
*/
void grant_reload(THD *thd) void grant_reload(THD *thd)
{ {
@@ -2419,8 +2454,6 @@ void grant_reload(THD *thd)
MEM_ROOT old_mem; MEM_ROOT old_mem;
DBUG_ENTER("grant_reload"); DBUG_ENTER("grant_reload");
// Locked tables are checked by acl_init and doesn't have to be checked here
pthread_mutex_lock(&LOCK_grant); pthread_mutex_lock(&LOCK_grant);
grant_version++; grant_version++;
old_hash_tables=hash_tables; old_hash_tables=hash_tables;
@@ -2496,13 +2529,13 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
pthread_mutex_unlock(&LOCK_grant); pthread_mutex_unlock(&LOCK_grant);
return 0; return 0;
err: err:
pthread_mutex_unlock(&LOCK_grant); pthread_mutex_unlock(&LOCK_grant);
if (!no_errors) // Not a silent skip of table if (!no_errors) // Not a silent skip of table
{ {
const char *command=""; const char *command="";
if (want_access & SELECT_ACL) if (want_access & SELECT_ACL)
command ="select"; command ="select";
else if (want_access & INSERT_ACL) else if (want_access & INSERT_ACL)
command = "insert"; command = "insert";
else if (want_access & UPDATE_ACL) else if (want_access & UPDATE_ACL)
@@ -2543,7 +2576,7 @@ bool check_grant_column(THD *thd,TABLE *table, const char *name,
pthread_mutex_lock(&LOCK_grant); pthread_mutex_lock(&LOCK_grant);
// reload table if someone has modified any grants /* reload table if someone has modified any grants */
if (table->grant.version != grant_version) if (table->grant.version != grant_version)
{ {
@@ -2603,7 +2636,7 @@ bool check_grant_all_columns(THD *thd, ulong want_access, TABLE *table)
pthread_mutex_lock(&LOCK_grant); pthread_mutex_lock(&LOCK_grant);
// reload table if someone has modified any grants /* reload table if someone has modified any grants */
if (table->grant.version != grant_version) if (table->grant.version != grant_version)
{ {
@@ -2613,7 +2646,7 @@ bool check_grant_all_columns(THD *thd, ulong want_access, TABLE *table)
table->real_name,0); /* purecov: inspected */ table->real_name,0); /* purecov: inspected */
table->grant.version=grant_version; /* purecov: inspected */ table->grant.version=grant_version; /* purecov: inspected */
} }
// The following should always be true /* The following should always be true */
if (!(grant_table=table->grant.grant_table)) if (!(grant_table=table->grant.grant_table))
goto err; /* purecov: inspected */ goto err; /* purecov: inspected */
@@ -2628,7 +2661,7 @@ bool check_grant_all_columns(THD *thd, ulong want_access, TABLE *table)
return 0; return 0;
/* We must use my_printf_error() here! */ /* We must use my_printf_error() here! */
err: err:
pthread_mutex_unlock(&LOCK_grant); pthread_mutex_unlock(&LOCK_grant);
const char *command=""; const char *command="";
@@ -2648,11 +2681,11 @@ bool check_grant_all_columns(THD *thd, ulong want_access, TABLE *table)
} }
/**************************************************************************** /*
Check if a user has the right to access a database Check if a user has the right to access a database
Access is accepted if he has a grant for any table in the database Access is accepted if he has a grant for any table in the database
Return 1 if access is denied Return 1 if access is denied
****************************************************************************/ */
bool check_grant_db(THD *thd,const char *db) bool check_grant_db(THD *thd,const char *db)
{ {
@@ -2692,7 +2725,7 @@ ulong get_table_grant(THD *thd, TABLE_LIST *table)
pthread_mutex_lock(&LOCK_grant); pthread_mutex_lock(&LOCK_grant);
grant_table = table_hash_search(thd->host,thd->ip,db,user, grant_table = table_hash_search(thd->host,thd->ip,db,user,
table->real_name,0); table->real_name, 0);
table->grant.grant_table=grant_table; // Remember for column test table->grant.grant_table=grant_table; // Remember for column test
table->grant.version=grant_version; table->grant.version=grant_version;
if (grant_table) if (grant_table)
@@ -2710,7 +2743,7 @@ ulong get_column_grant(THD *thd, TABLE_LIST *table, Field *field)
ulong priv; ulong priv;
pthread_mutex_lock(&LOCK_grant); pthread_mutex_lock(&LOCK_grant);
// reload table if someone has modified any grants /* reload table if someone has modified any grants */
if (table->grant.version != grant_version) if (table->grant.version != grant_version)
{ {
table->grant.grant_table= table->grant.grant_table=
@@ -2735,11 +2768,20 @@ ulong get_column_grant(THD *thd, TABLE_LIST *table, Field *field)
return priv; return priv;
} }
/* Help function for mysql_show_grants */
/***************************************************************************** static void add_user_option(String *grant, ulong value, const char *name)
SHOW GRANTS : send to client grant-like strings depicting user@host {
privileges if (value)
*****************************************************************************/ {
char buff[22], *p; // just as in int2str
grant->append(' ');
grant->append(name, strlen(name));
grant->append(' ');
p=int10_to_str(value, buff, 10);
grant->append(buff,p-buff);
}
}
static const char *command_array[]= static const char *command_array[]=
{ {
@@ -2748,13 +2790,21 @@ static const char *command_array[]=
"SUPER", "CREATE TEMPORARY TABLES", "LOCK TABLES", "EXECUTE", "SUPER", "CREATE TEMPORARY TABLES", "LOCK TABLES", "EXECUTE",
"REPLICATION SLAVE", "REPLICATION CLIENT", "REPLICATION SLAVE", "REPLICATION CLIENT",
}; };
static uint command_lengths[]= static uint command_lengths[]=
{ {
6,6,6,6,6,4,6,8,7,4,5,10,5,5,14,5,23,11,7,17,18 6,6,6,6,6,4,6,8,7,4,5,10,5,5,14,5,23,11,7,17,18
}; };
int mysql_show_grants(THD *thd,LEX_USER *lex_user) /*
SHOW GRANTS; Send grants for a user to the client
IMPLEMENTATION
Send to client grant-like strings depicting user@host privileges
*/
int mysql_show_grants(THD *thd,LEX_USER *lex_user)
{ {
ulong want_access; ulong want_access;
uint counter,index; uint counter,index;
@@ -2793,7 +2843,7 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
!my_strcasecmp(lex_user->host.str,host)) !my_strcasecmp(lex_user->host.str,host))
break; break;
} }
if (counter == acl_users.elements) if (counter == acl_users.elements)
{ {
my_printf_error(ER_NONEXISTING_GRANT,ER(ER_NONEXISTING_GRANT), my_printf_error(ER_NONEXISTING_GRANT,ER(ER_NONEXISTING_GRANT),
MYF(0),lex_user->user.str,lex_user->host.str); MYF(0),lex_user->user.str,lex_user->host.str);
@@ -2824,13 +2874,13 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
global.append("ALL PRIVILEGES",14); global.append("ALL PRIVILEGES",14);
else if (!(want_access & ~GRANT_ACL)) else if (!(want_access & ~GRANT_ACL))
global.append("USAGE",5); global.append("USAGE",5);
else else
{ {
bool found=0; bool found=0;
ulong j,test_access= want_access & ~GRANT_ACL; ulong j,test_access= want_access & ~GRANT_ACL;
for (counter=0, j = SELECT_ACL;j <= GLOBAL_ACLS;counter++,j <<= 1) for (counter=0, j = SELECT_ACL;j <= GLOBAL_ACLS;counter++,j <<= 1)
{ {
if (test_access & j) if (test_access & j)
{ {
if (found) if (found)
global.append(", ",2); global.append(", ",2);
@@ -2840,7 +2890,7 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
} }
} }
global.append (" ON *.* TO '",12); global.append (" ON *.* TO '",12);
global.append(lex_user->user.str,lex_user->user.length); global.append(lex_user->user.str,lex_user->user.length);
global.append ("'@'",3); global.append ("'@'",3);
global.append(lex_user->host.str,lex_user->host.length); global.append(lex_user->host.str,lex_user->host.length);
global.append ('\''); global.append ('\'');
@@ -2863,25 +2913,25 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
global.append(" REQUIRE ",9); global.append(" REQUIRE ",9);
if (acl_user->x509_issuer) if (acl_user->x509_issuer)
{ {
ssl_options++; ssl_options++;
global.append("ISSUER \'",8); global.append("ISSUER \'",8);
global.append(acl_user->x509_issuer,strlen(acl_user->x509_issuer)); global.append(acl_user->x509_issuer,strlen(acl_user->x509_issuer));
global.append('\''); global.append('\'');
} }
if (acl_user->x509_subject) if (acl_user->x509_subject)
{ {
if (ssl_options++) if (ssl_options++)
global.append(' '); global.append(' ');
global.append("SUBJECT \'",9); global.append("SUBJECT \'",9);
global.append(acl_user->x509_subject,strlen(acl_user->x509_subject)); global.append(acl_user->x509_subject,strlen(acl_user->x509_subject));
global.append('\''); global.append('\'');
} }
if (acl_user->ssl_cipher) if (acl_user->ssl_cipher)
{ {
if (ssl_options++) if (ssl_options++)
global.append(' '); global.append(' ');
global.append("CIPHER '",8); global.append("CIPHER '",8);
global.append(acl_user->ssl_cipher,strlen(acl_user->ssl_cipher)); global.append(acl_user->ssl_cipher,strlen(acl_user->ssl_cipher));
global.append('\''); global.append('\'');
} }
} }
@@ -2889,30 +2939,15 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
(acl_user->user_resource.questions | acl_user->user_resource.updates | (acl_user->user_resource.questions | acl_user->user_resource.updates |
acl_user->user_resource.connections)) acl_user->user_resource.connections))
{ {
global.append(" WITH",5); global.append(" WITH",5);
if (want_access & GRANT_ACL) if (want_access & GRANT_ACL)
global.append(" GRANT OPTION",13); global.append(" GRANT OPTION",13);
if (acl_user->user_resource.questions) add_user_option(&global, acl_user->user_resource.questions,
{ "MAX_QUERIES_PER_HOUR");
char buff[22], *p; // just as in int2str add_user_option(&global, acl_user->user_resource.updates,
global.append(" MAX_QUERIES_PER_HOUR ",22); "MAX_UPDATES_PER_HOUR");
p=int10_to_str(acl_user->user_resource.questions,buff,10); add_user_option(&global, acl_user->user_resource.connections,
global.append(buff,p-buff); "MAX_CONNECTIONS_PER_HOUR");
}
if (acl_user->user_resource.updates)
{
char buff[22], *p; // just as in int2str
global.append(" MAX_UPDATES_PER_HOUR ",22);
p=int10_to_str(acl_user->user_resource.updates,buff,10);
global.append(buff,p-buff);
}
if (acl_user->user_resource.connections)
{
char buff[22], *p; // just as in int2str
global.append(" MAX_CONNECTIONS_PER_HOUR ",26);
p=int10_to_str(acl_user->user_resource.connections,buff,10);
global.append(buff,p-buff);
}
} }
thd->packet.length(0); thd->packet.length(0);
net_store_data(&thd->packet,global.ptr(),global.length()); net_store_data(&thd->packet,global.ptr(),global.length());
@@ -2938,7 +2973,7 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
!my_strcasecmp(lex_user->host.str,host)) !my_strcasecmp(lex_user->host.str,host))
{ {
want_access=acl_db->access; want_access=acl_db->access;
if (want_access) if (want_access)
{ {
String db(buff,sizeof(buff)); String db(buff,sizeof(buff));
db.length(0); db.length(0);
@@ -2947,7 +2982,7 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
if (test_all_bits(want_access,(DB_ACLS & ~GRANT_ACL))) if (test_all_bits(want_access,(DB_ACLS & ~GRANT_ACL)))
db.append("ALL PRIVILEGES",14); db.append("ALL PRIVILEGES",14);
else if (!(want_access & ~GRANT_ACL)) else if (!(want_access & ~GRANT_ACL))
db.append("USAGE",5); db.append("USAGE",5);
else else
{ {
int found=0, cnt; int found=0, cnt;
@@ -2963,13 +2998,13 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
} }
} }
} }
db.append (" ON `",5); db.append(" ON `",5);
db.append(acl_db->db); db.append(acl_db->db);
db.append ("`.* TO '",8); db.append("`.* TO '",8);
db.append(lex_user->user.str,lex_user->user.length); db.append(lex_user->user.str,lex_user->user.length);
db.append ("'@'",3); db.append("'@'",3);
db.append(lex_user->host.str, lex_user->host.length); db.append(lex_user->host.str, lex_user->host.length);
db.append ('\''); db.append('\'');
if (want_access & GRANT_ACL) if (want_access & GRANT_ACL)
db.append(" WITH GRANT OPTION",18); db.append(" WITH GRANT OPTION",18);
thd->packet.length(0); thd->packet.length(0);
@@ -2988,7 +3023,7 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
for (index=0 ; index < hash_tables.records ; index++) for (index=0 ; index < hash_tables.records ; index++)
{ {
const char *user,*host; const char *user,*host;
GRANT_TABLE *grant_table= (GRANT_TABLE*) hash_element(&hash_tables,index); GRANT_TABLE *grant_table= (GRANT_TABLE*) hash_element(&hash_tables,index);
if (!(user=grant_table->user)) if (!(user=grant_table->user))
user=""; user="";
@@ -2998,44 +3033,54 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
if (!strcmp(lex_user->user.str,user) && if (!strcmp(lex_user->user.str,user) &&
!my_strcasecmp(lex_user->host.str,host)) !my_strcasecmp(lex_user->host.str,host))
{ {
want_access=grant_table->privs; ulong table_access= grant_table->privs;
if ((want_access | grant_table->cols) != 0) if ((table_access | grant_table->cols) != 0)
{ {
String global(buff,sizeof(buff)); String global(buff,sizeof(buff));
global.length(0); global.length(0);
global.append("GRANT ",6); global.append("GRANT ",6);
if (test_all_bits(grant_table->privs,(TABLE_ACLS & ~GRANT_ACL))) if (test_all_bits(table_access, (TABLE_ACLS & ~GRANT_ACL)))
global.append("ALL PRIVILEGES",14); global.append("ALL PRIVILEGES",14);
else else
{ {
int found=0; int found= 0;
ulong j,test_access= (want_access | grant_table->cols) & ~GRANT_ACL; ulong j,test_access= (table_access | grant_table->cols) & ~GRANT_ACL;
for (counter=0, j = SELECT_ACL;j <= TABLE_ACLS; counter++,j <<= 1) for (counter= 0, j= SELECT_ACL; j <= TABLE_ACLS; counter++, j<<= 1)
{ {
if (test_access & j) if (test_access & j)
{ {
if (found) if (found)
global.append(", ",2); global.append(", ",2);
found = 1; found= 1;
global.append(command_array[counter],command_lengths[counter]); global.append(command_array[counter],command_lengths[counter]);
if (grant_table->cols) if (grant_table->cols)
{ {
uint found_col=0; uint found_col= 0;
for (uint col_index=0 ; for (uint col_index=0 ;
col_index < grant_table->hash_columns.records ; col_index < grant_table->hash_columns.records ;
col_index++) col_index++)
{ {
GRANT_COLUMN *grant_column = (GRANT_COLUMN*) GRANT_COLUMN *grant_column = (GRANT_COLUMN*)
hash_element(&grant_table->hash_columns,col_index); hash_element(&grant_table->hash_columns,col_index);
if (grant_column->rights & j) if (grant_column->rights & j)
{ {
if (!found_col) if (!found_col)
{ {
found_col= 1;
/*
If we have a duplicated table level privilege, we
must write the access privilege name again.
*/
if (table_access & j)
{
global.append(", ", 2);
global.append(command_array[counter],
command_lengths[counter]);
}
global.append(" (",2); global.append(" (",2);
found_col=1;
} }
else else
global.append(", ",2); global.append(", ",2);
@@ -3054,12 +3099,12 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
global.append("`.`",3); global.append("`.`",3);
global.append(grant_table->tname); global.append(grant_table->tname);
global.append("` TO '",6); global.append("` TO '",6);
global.append(lex_user->user.str,lex_user->user.length); global.append(lex_user->user.str,lex_user->user.length);
global.append("'@'",3); global.append("'@'",3);
global.append(lex_user->host.str,lex_user->host.length); global.append(lex_user->host.str,lex_user->host.length);
global.append('\''); global.append('\'');
if (want_access & GRANT_ACL) if (table_access & GRANT_ACL)
global.append(" WITH GRANT OPTION",18); global.append(" WITH GRANT OPTION",18);
thd->packet.length(0); thd->packet.length(0);
net_store_data(&thd->packet,global.ptr(),global.length()); net_store_data(&thd->packet,global.ptr(),global.length());
if (my_net_write(&thd->net,(char*) thd->packet.ptr(), if (my_net_write(&thd->net,(char*) thd->packet.ptr(),
@@ -3072,7 +3117,7 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
} }
} }
end: end:
VOID(pthread_mutex_unlock(&acl_cache->lock)); VOID(pthread_mutex_unlock(&acl_cache->lock));
pthread_mutex_unlock(&LOCK_grant); pthread_mutex_unlock(&LOCK_grant);

View File

@@ -76,8 +76,8 @@
#define get_rights_for_db(A) (((A) & 63) | (((A) & DB_CHUNK1) >> 4) | (((A) & DB_CHUNK2) >> 6)) #define get_rights_for_db(A) (((A) & 63) | (((A) & DB_CHUNK1) >> 4) | (((A) & DB_CHUNK2) >> 6))
#define fix_rights_for_table(A) (((A) & 63) | (((A) & ~63) << 4)) #define fix_rights_for_table(A) (((A) & 63) | (((A) & ~63) << 4))
#define get_rights_for_table(A) (((A) & 63) | (((A) & ~63) >> 4)) #define get_rights_for_table(A) (((A) & 63) | (((A) & ~63) >> 4))
#define fix_rights_for_column(A) (((A) & COL_ACLS) | ((A & ~COL_ACLS) << 7)) #define fix_rights_for_column(A) (((A) & 7) | (((A) & ~7) << 8))
#define get_rights_for_column(A) (((A) & COL_ACLS) | ((A & ~COL_ACLS) >> 7)) #define get_rights_for_column(A) (((A) & 7) | ((A) >> 8))
/* prototypes */ /* prototypes */

View File

@@ -309,6 +309,7 @@ struct system_variables
ulong tmp_table_size; ulong tmp_table_size;
ulong tx_isolation; ulong tx_isolation;
ulong table_type; ulong table_type;
ulong default_week_format;
my_bool log_warnings; my_bool log_warnings;
my_bool low_priority_updates; my_bool low_priority_updates;

View File

@@ -584,6 +584,11 @@ check_connections(THD *thd)
if (thd->client_capabilities & CLIENT_SSL) if (thd->client_capabilities & CLIENT_SSL)
{ {
/* Do the SSL layering. */ /* Do the SSL layering. */
if (!ssl_acceptor_fd)
{
inc_host_errors(&thd->remote.sin_addr);
return(ER_HANDSHAKE_ERROR);
}
DBUG_PRINT("info", ("IO layer change in progress...")); DBUG_PRINT("info", ("IO layer change in progress..."));
if (sslaccept(ssl_acceptor_fd, net->vio, thd->variables.net_wait_timeout)) if (sslaccept(ssl_acceptor_fd, net->vio, thd->variables.net_wait_timeout))
{ {

View File

@@ -51,7 +51,7 @@ int check_binlog_magic(IO_CACHE* log, const char** errmsg)
} }
static int fake_rotate_event(NET* net, String* packet, char* log_file_name, static int fake_rotate_event(NET* net, String* packet, char* log_file_name,
const char**errmsg) ulonglong position, const char**errmsg)
{ {
char header[LOG_EVENT_HEADER_LEN], buf[ROTATE_HEADER_LEN]; char header[LOG_EVENT_HEADER_LEN], buf[ROTATE_HEADER_LEN];
memset(header, 0, 4); // when does not matter memset(header, 0, 4); // when does not matter
@@ -68,9 +68,7 @@ static int fake_rotate_event(NET* net, String* packet, char* log_file_name,
int4store(header + LOG_POS_OFFSET, 0); int4store(header + LOG_POS_OFFSET, 0);
packet->append(header, sizeof(header)); packet->append(header, sizeof(header));
/* We need to split the next statement because of problem with cxx */ int8store(buf+R_POS_OFFSET,position);
int4store(buf,4); // tell slave to skip magic number
int4store(buf+4,0);
packet->append(buf, ROTATE_HEADER_LEN); packet->append(buf, ROTATE_HEADER_LEN);
packet->append(p,ident_len); packet->append(p,ident_len);
if (my_net_write(net, (char*)packet->ptr(), packet->length())) if (my_net_write(net, (char*)packet->ptr(), packet->length()))
@@ -382,17 +380,30 @@ impossible position";
*/ */
packet->set("\0", 1); packet->set("\0", 1);
// if we are at the start of the log /*
if (pos == BIN_LOG_HEADER_SIZE) Before 4.0.14 we called fake_rotate_event below only if
(pos == BIN_LOG_HEADER_SIZE), because if this is false then the slave
already knows the binlog's name.
Now we always call fake_rotate_event; if the slave already knew the log's
name (ex: CHANGE MASTER TO MASTER_LOG_FILE=...) this is useless but does not
harm much. It is nice for 3.23 (>=.58) slaves which test Rotate events
to see if the master is 4.0 (then they choose to stop because they can't
replicate 4.0); by always calling fake_rotate_event we are sure that 3.23.58
and newer will detect the problem as soon as replication starts (BUG#198).
Always calling fake_rotate_event makes sending of normal
(=from-binlog) Rotate events a priori unneeded, but it is not so simple: the
2 Rotate events are not equivalent, the normal one is before the Stop event,
the fake one is after. If we don't send the normal one, then the Stop event
will be interpreted (by existing 4.0 slaves) as "the master stopped", which
is wrong. So for safety, given that we want minimum modification of 4.0, we
send the normal and fake Rotates.
*/
if (fake_rotate_event(net, packet, log_file_name, pos, &errmsg))
{ {
// tell the client log name with a fake rotate_event my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG;
if (fake_rotate_event(net, packet, log_file_name, &errmsg)) goto err;
{
my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG;
goto err;
}
packet->set("\0", 1);
} }
packet->set("\0", 1);
while (!net->error && net->vio != 0 && !thd->killed) while (!net->error && net->vio != 0 && !thd->killed)
{ {
@@ -585,10 +596,12 @@ Increase max_allowed_packet on master";
end_io_cache(&log); end_io_cache(&log);
(void) my_close(file, MYF(MY_WME)); (void) my_close(file, MYF(MY_WME));
// fake Rotate_log event just in case it did not make it to the log /*
// otherwise the slave make get confused about the offset Even if the previous log contained a Rotate_log_event, we still fake
one.
*/
if ((file=open_binlog(&log, log_file_name, &errmsg)) < 0 || if ((file=open_binlog(&log, log_file_name, &errmsg)) < 0 ||
fake_rotate_event(net, packet, log_file_name, &errmsg)) fake_rotate_event(net, packet, log_file_name, BIN_LOG_HEADER_SIZE, &errmsg))
{ {
my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG; my_errno= ER_MASTER_FATAL_ERROR_READING_BINLOG;
goto err; goto err;
@@ -828,7 +841,7 @@ int change_master(THD* thd, MASTER_INFO* mi)
// TODO: see if needs re-write // TODO: see if needs re-write
if (init_master_info(mi, master_info_file, relay_log_info_file, 0)) if (init_master_info(mi, master_info_file, relay_log_info_file, 0))
{ {
send_error(&thd->net, 0, "Could not initialize master info"); send_error(&thd->net, ER_MASTER_INFO);
unlock_slave_threads(mi); unlock_slave_threads(mi);
DBUG_RETURN(1); DBUG_RETURN(1);
} }

View File

@@ -453,6 +453,9 @@ mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &fields,COND *conds,
goto err; goto err;
thd->proc_info="preparing"; thd->proc_info="preparing";
select_distinct= select_distinct && (join.const_tables != join.tables);
if (result->initialize_tables(&join)) if (result->initialize_tables(&join))
goto err; goto err;
if (join.const_table_map != join.found_const_table_map && if (join.const_table_map != join.found_const_table_map &&
@@ -1634,6 +1637,9 @@ add_key_part(DYNAMIC_ARRAY *keyuse_array,KEY_FIELD *key_field)
key_field->field->table->reginfo.not_exists_optimize=1; key_field->field->table->reginfo.not_exists_optimize=1;
} }
#define FT_KEYPART (MAX_REF_PARTS+10)
static void static void
add_ft_keys(DYNAMIC_ARRAY *keyuse_array, add_ft_keys(DYNAMIC_ARRAY *keyuse_array,
JOIN_TAB *stat,COND *cond,table_map usable_tables) JOIN_TAB *stat,COND *cond,table_map usable_tables)
@@ -1692,23 +1698,20 @@ add_ft_keys(DYNAMIC_ARRAY *keyuse_array,
} }
} }
if (!cond_func || cond_func->key == NO_SUCH_KEY) if ((!cond_func || cond_func->key == NO_SUCH_KEY) ||
return; (!(usable_tables & cond_func->table->map)))
if (!(usable_tables & cond_func->table->map))
return; return;
KEYUSE keyuse; KEYUSE keyuse;
keyuse.table= cond_func->table; keyuse.table= cond_func->table;
keyuse.val = cond_func; keyuse.val = cond_func;
keyuse.key = cond_func->key; keyuse.key = cond_func->key;
#define FT_KEYPART (MAX_REF_PARTS+10) keyuse.keypart= FT_KEYPART;
keyuse.keypart=FT_KEYPART;
keyuse.used_tables=cond_func->key_item()->used_tables(); keyuse.used_tables=cond_func->key_item()->used_tables();
VOID(insert_dynamic(keyuse_array,(gptr) &keyuse)); VOID(insert_dynamic(keyuse_array,(gptr) &keyuse));
} }
static int static int
sort_keyuse(KEYUSE *a,KEYUSE *b) sort_keyuse(KEYUSE *a,KEYUSE *b)
{ {

View File

@@ -2016,7 +2016,11 @@ simple_expr:
| USER '(' ')' | USER '(' ')'
{ $$= new Item_func_user(); current_thd->safe_to_cache_query=0; } { $$= new Item_func_user(); current_thd->safe_to_cache_query=0; }
| WEEK_SYM '(' expr ')' | WEEK_SYM '(' expr ')'
{ $$= new Item_func_week($3,new Item_int((char*) "0",0,1)); } {
LEX *lex=Lex;
$$= new Item_func_week($3,new Item_int((char*) "0",
lex->thd->variables.default_week_format,1));
}
| WEEK_SYM '(' expr ',' expr ')' | WEEK_SYM '(' expr ',' expr ')'
{ $$= new Item_func_week($3,$5); } { $$= new Item_func_week($3,$5); }
| YEAR_SYM '(' expr ')' | YEAR_SYM '(' expr ')'