summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/ha_heap.cc15
-rw-r--r--sql/ha_heap.h5
-rw-r--r--sql/handler.cc4
-rw-r--r--sql/handler.h2
-rw-r--r--sql/lock.cc22
-rw-r--r--sql/mini_client.cc7
-rw-r--r--sql/mysql_priv.h7
-rw-r--r--sql/mysqld.cc62
-rw-r--r--sql/opt_range.cc12
-rw-r--r--sql/sql_base.cc35
-rw-r--r--sql/sql_parse.cc23
-rw-r--r--sql/sql_select.cc66
-rw-r--r--sql/sql_show.cc65
-rw-r--r--sql/table.h1
14 files changed, 230 insertions, 96 deletions
diff --git a/sql/ha_heap.cc b/sql/ha_heap.cc
index 989497cee6e..591ca0bc813 100644
--- a/sql/ha_heap.cc
+++ b/sql/ha_heap.cc
@@ -251,6 +251,21 @@ int ha_heap::rename_table(const char * from, const char * to)
}
+ha_rows ha_heap::records_in_range(int inx,
+ const byte *start_key,uint start_key_len,
+ enum ha_rkey_function start_search_flag,
+ const byte *end_key,uint end_key_len,
+ enum ha_rkey_function end_search_flag)
+{
+ KEY *pos=table->key_info+inx;
+ if (start_key_len != end_key_len ||
+ start_key_len != pos->key_length ||
+ start_search_flag != HA_READ_KEY_EXACT ||
+ end_search_flag != HA_READ_KEY_EXACT)
+ return HA_POS_ERROR; // Can't only use exact keys
+ return 10; // Good guess
+}
+
/* We can just delete the heap on creation */
int ha_heap::create(const char *name, TABLE *form, HA_CREATE_INFO *create_info)
diff --git a/sql/ha_heap.h b/sql/ha_heap.h
index acbc0975f1e..b56ee84822f 100644
--- a/sql/ha_heap.h
+++ b/sql/ha_heap.h
@@ -65,7 +65,10 @@ class ha_heap: public handler
int reset(void);
int external_lock(THD *thd, int lock_type);
int delete_all_rows(void);
-
+ ha_rows records_in_range(int inx, const byte *start_key,uint start_key_len,
+ enum ha_rkey_function start_search_flag,
+ const byte *end_key,uint end_key_len,
+ enum ha_rkey_function end_search_flag);
int delete_table(const char *from);
int rename_table(const char * from, const char * to);
int create(const char *name, TABLE *form, HA_CREATE_INFO *create_info);
diff --git a/sql/handler.cc b/sql/handler.cc
index 592861e176b..437b11be5bb 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -317,8 +317,8 @@ int handler::ha_open(const char *name, int mode, int test_if_locked)
}
if (!error)
{
-
- if (!(ref=(byte*) my_malloc(ALIGN_SIZE(ref_length)*2,MYF(0))))
+ if (!(ref=(byte*) alloc_root(&table->mem_root,
+ ALIGN_SIZE(ref_length)*2)))
{
close();
error=HA_ERR_OUT_OF_MEM;
diff --git a/sql/handler.h b/sql/handler.h
index 67fd99c71d7..08bf355b60e 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -200,7 +200,7 @@ public:
create_time(0), check_time(0), update_time(0), mean_rec_length(0),
ft_handler(0)
{}
- virtual ~handler(void) { my_free((char*) ref,MYF(MY_ALLOW_ZERO_PTR)); }
+ virtual ~handler(void) {}
int ha_open(const char *name, int mode, int test_if_locked);
void update_timestamp(byte *record);
void update_auto_increment();
diff --git a/sql/lock.cc b/sql/lock.cc
index a2e4daa4590..eba1851bae0 100644
--- a/sql/lock.cc
+++ b/sql/lock.cc
@@ -407,15 +407,17 @@ int lock_table_name(THD *thd, TABLE_LIST *table_list)
TABLE *table;
char key[MAX_DBKEY_LENGTH];
uint key_length;
- key_length=(uint) (strmov(strmov(key,table_list->db)+1,table_list->name)-key)+
- 1;
+ DBUG_ENTER("lock_table_name");
+
+ key_length=(uint) (strmov(strmov(key,table_list->db)+1,table_list->name)
+ -key)+ 1;
/* Only insert the table if we haven't insert it already */
for (table=(TABLE*) hash_search(&open_cache,(byte*) key,key_length) ;
table ;
table = (TABLE*) hash_next(&open_cache,(byte*) key,key_length))
if (table->in_use == thd)
- return 0;
+ DBUG_RETURN(0);
/* Create a table entry with the right key and with an old refresh version */
/* Note that we must use my_malloc() here as this is freed by the table
@@ -423,17 +425,18 @@ int lock_table_name(THD *thd, TABLE_LIST *table_list)
if (!(table= (TABLE*) my_malloc(sizeof(*table)+key_length,
MYF(MY_WME | MY_ZEROFILL))))
- return -1;
+ DBUG_RETURN(-1);
memcpy((table->table_cache_key= (char*) (table+1)), key, key_length);
table->key_length=key_length;
table->in_use=thd;
+ table->locked_by_name=1;
table_list->table=table;
if (hash_insert(&open_cache, (byte*) table))
- return -1;
+ DBUG_RETURN(-1);
if (remove_table_from_cache(thd, table_list->db, table_list->name))
- return 1; // Table is in use
- return 0;
+ DBUG_RETURN(1); // Table is in use
+ DBUG_RETURN(0);
}
void unlock_table_name(THD *thd, TABLE_LIST *table_list)
@@ -446,7 +449,7 @@ static bool locked_named_table(THD *thd, TABLE_LIST *table_list)
{
for ( ; table_list ; table_list=table_list->next)
{
- if (table_list->table && table_is_used(table_list->table))
+ if (table_list->table && table_is_used(table_list->table,0))
return 1;
}
return 0; // All tables are locked
@@ -456,6 +459,7 @@ static bool locked_named_table(THD *thd, TABLE_LIST *table_list)
bool wait_for_locked_table_names(THD *thd, TABLE_LIST *table_list)
{
bool result=0;
+ DBUG_ENTER("wait_for_locked_table_names");
while (locked_named_table(thd,table_list))
{
@@ -467,5 +471,5 @@ bool wait_for_locked_table_names(THD *thd, TABLE_LIST *table_list)
wait_for_refresh(thd);
pthread_mutex_lock(&LOCK_open);
}
- return result;
+ DBUG_RETURN(result);
}
diff --git a/sql/mini_client.cc b/sql/mini_client.cc
index b9e66911475..5cd0fe2c680 100644
--- a/sql/mini_client.cc
+++ b/sql/mini_client.cc
@@ -225,13 +225,14 @@ static void mc_free_old_query(MYSQL *mysql)
* Base version coded by Steve Bernacki, Jr. <steve@navinet.net>
*****************************************************************************/
-static int mc_sock_connect(File s, const struct sockaddr *name, uint namelen, uint to)
+static int mc_sock_connect(my_socket s, const struct sockaddr *name,
+ uint namelen, uint to)
{
#if defined(__WIN__)
return connect(s, (struct sockaddr*) name, namelen);
#else
int flags, res, s_err;
- socklen_t s_err_size = sizeof(uint);
+ size_socket s_err_size = sizeof(uint);
fd_set sfds;
struct timeval tv;
@@ -451,7 +452,7 @@ mc_mysql_connect(MYSQL *mysql,const char *host, const char *user,
uint port, const char *unix_socket,uint client_flag)
{
char buff[100],*end,*host_info;
- int sock;
+ my_socket sock;
ulong ip_addr;
struct sockaddr_in sock_addr;
uint pkt_length;
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index fa61102fb57..7e372a7ffd1 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -127,7 +127,7 @@ void sql_element_free(void *ptr);
#define TEST_NO_THREADS 32 /* For debugging under Linux */
#define TEST_READCHECK 64 /* Force use of readcheck */
#define TEST_NO_EXTRA 128
-#define TEST_KILL_ON_DEBUG 256 /* Kill server */
+#define TEST_CORE_ON_SIGNAL 256 /* Give core if signal */
/* options for select set by the yacc parser */
#define SELECT_DISTINCT 1
@@ -319,10 +319,11 @@ TABLE *open_table(THD *thd,const char *db,const char *table,const char *alias,
TABLE *find_locked_table(THD *thd, const char *db,const char *table_name);
bool reopen_table(TABLE *table,bool locked=0);
bool reopen_tables(THD *thd,bool get_locks,bool in_refresh);
-void close_old_data_files(THD *thd, TABLE *table, bool abort_locks);
+void close_old_data_files(THD *thd, TABLE *table, bool abort_locks,
+ bool send_refresh);
bool close_data_tables(THD *thd,const char *db, const char *table_name);
bool wait_for_tables(THD *thd);
-bool table_is_used(TABLE *table);
+bool table_is_used(TABLE *table, bool wait_for_name_lock);
bool drop_locked_tables(THD *thd,const char *db, const char *table_name);
void abort_locked_tables(THD *thd,const char *db, const char *table_name);
Field *find_field_in_tables(THD *thd,Item_field *item,TABLE_LIST *tables);
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index f8ce60b9681..8ea12f68da8 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -1003,6 +1003,20 @@ static void init_signals(void)
}
#else
+#ifdef HAVE_LINUXTHREADS
+
+/* Produce a core for the thread */
+
+static sig_handler write_core(int sig)
+{
+ fprintf(stderr,"Got signal %s in thread %d\n",sys_siglist[sig],getpid());
+ signal(sig, SIG_DFL);
+ if (fork() != 0) exit(1); // Abort main program
+ // Core will be written at exit
+}
+#endif
+
+
static void init_signals(void)
{
sigset_t set;
@@ -1012,6 +1026,16 @@ static void init_signals(void)
sigset(THR_KILL_SIGNAL,end_thread_signal);
sigset(THR_SERVER_ALARM,print_signal_warning); // Should never be called!
+#ifdef HAVE_LINUXTHREADS
+ if (test_flags & TEST_CORE_ON_SIGNAL)
+ {
+ struct sigaction sa; sa.sa_flags = 0;
+ sigemptyset(&sa.sa_mask);
+ sigprocmask(SIG_SETMASK,&sa.sa_mask,NULL);
+ sa.sa_handler=write_core;
+ sigaction(SIGSEGV, &sa, NULL);
+ }
+#endif
(void) sigemptyset(&set);
#ifdef THREAD_SPECIFIC_SIGPIPE
sigset(SIGPIPE,abort_thread);
@@ -2134,7 +2158,7 @@ enum options {OPT_ISAM_LOG=256,OPT_SKIP_NEW,OPT_SKIP_GRANT,
OPT_MASTER_PORT, OPT_MASTER_INFO_FILE, OPT_MASTER_CONNECT_RETRY,
OPT_SQL_BIN_UPDATE_SAME, OPT_REPLICATE_DO_DB,
OPT_REPLICATE_IGNORE_DB, OPT_LOG_SLAVE_UPDATES,
- OPT_BINLOG_DO_DB, OPT_BINLOG_IGNORE_DB};
+ OPT_BINLOG_DO_DB, OPT_BINLOG_IGNORE_DB, OPT_WANT_CORE};
static struct option long_options[] =
{
@@ -2156,6 +2180,7 @@ static struct option long_options[] =
#ifdef __WIN__
{"console", no_argument, 0, OPT_CONSOLE},
#endif
+ {"core-file", no_argument, 0, OPT_WANT_CORE},
{"chroot", required_argument,0, 'r'},
{"character-sets-dir",required_argument,0, OPT_CHARSETS_DIR},
{"datadir", required_argument, 0, 'h'},
@@ -2188,8 +2213,10 @@ static struct option long_options[] =
{"master-connect-retry", required_argument, 0, (int) OPT_MASTER_CONNECT_RETRY},
{"master-info-file", required_argument, 0, (int) OPT_MASTER_INFO_FILE},
{"new", no_argument, 0, 'n'},
- {"old-protocol", no_argument, 0, 'o'},
+ {"old-protocol", no_argument, 0, 'o'},
+#ifndef DBUG_OFF
{"one-thread", no_argument, 0, OPT_ONE_THREAD},
+#endif
{"pid-file", required_argument, 0, (int) OPT_PID_FILE},
{"port", required_argument, 0, 'P'},
{"replicate-do-db", required_argument, 0, OPT_REPLICATE_DO_DB},
@@ -2407,6 +2434,12 @@ static void print_version(void)
server_version,SYSTEM_TYPE,MACHINE_TYPE);
}
+static void use_help(void)
+{
+ print_version();
+ printf("Use %s --help for a list of available options\n",my_progname);
+}
+
static void usage(void)
{
print_version();
@@ -2426,6 +2459,7 @@ static void usage(void)
--character-sets-dir=...\n\
Directory where character sets are\n\
--chroot=path Chroot mysqld daemon during startup\n\
+ --core-file Write core on errors\n\
-h, --datadir=path Path to the database root");
#ifndef DBUG_OFF
printf("\
@@ -2454,11 +2488,17 @@ static void usage(void)
--log-isam[=file] Log all isam changes to file\n\
--log-long-format Log some extra information to update log\n\
--low-priority-updates INSERT/DELETE/UPDATE has lower priority than selects\n\
+ --log-slow-queries=[file]\n\
+ Log slow queries to this log file\n\
--pid-file=path Pid file used by safe_mysqld\n\
-P, --port=... Port number to use for connection\n\
-n, --new Use very new possible 'unsafe' functions\n\
- -o, --old-protocol Use the old (3.20) protocol\n\
- --one-thread Only use one thread (for debugging under Linux)\n\
+ -o, --old-protocol Use the old (3.20) protocol\n");
+#ifndef DBUG_OFF
+ puts("\
+ --one-thread Only use one thread (for debugging under Linux)\n");
+#endif
+ puts("\
-O, --set-variable var=option\n\
Give a variable an value. --help lists variables\n\
-Sg, --skip-grant-tables\n\
@@ -2621,7 +2661,7 @@ static void get_options(int argc,char **argv)
case 'O':
if (set_changeable_var(optarg, changeable_vars))
{
- usage();
+ use_help();
exit(1);
}
break;
@@ -2666,7 +2706,8 @@ static void get_options(int argc,char **argv)
opt_noacl=1;
else
{
- usage();
+ fprintf(stderr,"%s: Unrecognized option: %s\n",my_progname,optarg);
+ use_help();
exit(1);
}
break;
@@ -2718,8 +2759,6 @@ static void get_options(int argc,char **argv)
binlog_do_db.push_back(db);
break;
}
-
-
case (int) OPT_SQL_BIN_UPDATE_SAME:
opt_sql_bin_update = 1;
break;
@@ -2774,6 +2813,9 @@ static void get_options(int argc,char **argv)
case (int) OPT_ONE_THREAD:
test_flags |= TEST_NO_THREADS;
break;
+ case (int) OPT_WANT_CORE:
+ test_flags |= TEST_CORE_ON_SIGNAL;
+ break;
case (int) OPT_BIND_ADDRESS:
if (optarg && isdigit(optarg[0]))
{
@@ -2910,7 +2952,7 @@ static void get_options(int argc,char **argv)
default:
fprintf(stderr,"%s: Unrecognized option: %c\n",my_progname,c);
- usage();
+ use_help();
exit(1);
}
}
@@ -2920,7 +2962,7 @@ static void get_options(int argc,char **argv)
if (argc != optind)
{
fprintf(stderr,"%s: Too many parameters\n",my_progname);
- usage();
+ use_help();
exit(1);
}
fix_paths();
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 4f1abf9b685..25ee26dbdbd 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -14,6 +14,16 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+/*
+ TODO:
+ Fix that MAYBE_KEY are stored in the tree so that we can detect use
+ of full hash keys for queries like:
+
+ select s.id, kws.keyword_id from sites as s,kws where s.id=kws.site_id and kws.keyword_id in (204,205);
+
+*/
+
+
#ifdef __GNUC__
#pragma implementation // gcc: Class implementation
@@ -557,7 +567,7 @@ SEL_ARG *SEL_ARG::clone_tree()
** Returns:
** -1 if impossible select
** 0 if can't use quick_select
-** 1 if found usably range
+** 1 if found usable range
** Updates the following in the select parameter:
** needed_reg ; Bits for keys with may be used if all prev regs are read
** quick ; Parameter to use when reading records.
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 6bf44f7d7d6..de689baaddb 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -582,9 +582,8 @@ bool close_cached_tables(THD *thd, bool if_wait_for_refresh,
thd->mysys_var->current_cond= &COND_refresh;
thd->proc_info="Flushing tables";
pthread_mutex_unlock(&thd->mysys_var->mutex);
- VOID(pthread_cond_broadcast(&COND_refresh)); // If one flush is locked
- close_old_data_files(thd,thd->open_tables,1);
+ close_old_data_files(thd,thd->open_tables,1,1);
bool found=1;
/* Wait until all threads has closed all the tables we had locked */
DBUG_PRINT("info", ("Waiting for others threads to close their open tables"));
@@ -921,7 +920,7 @@ TABLE *open_table(THD *thd,const char *db,const char *table_name,
** There is a refresh in progress for this table
** Wait until the table is freed or the thread is killed.
*/
- close_old_data_files(thd,thd->open_tables,0);
+ close_old_data_files(thd,thd->open_tables,0,0);
if (table->in_use != thd)
wait_for_refresh(thd);
else
@@ -1216,9 +1215,11 @@ bool reopen_tables(THD *thd,bool get_locks,bool in_refresh)
abort_locks is set if called from flush_tables.
*/
-void close_old_data_files(THD *thd, TABLE *table, bool abort_locks)
+void close_old_data_files(THD *thd, TABLE *table, bool abort_locks,
+ bool send_refresh)
{
- bool found=0;
+ DBUG_ENTER("close_old_data_files");
+ bool found=send_refresh;
for (; table ; table=table->next)
{
if (table->version != refresh_version)
@@ -1241,6 +1242,7 @@ void close_old_data_files(THD *thd, TABLE *table, bool abort_locks)
}
if (found)
VOID(pthread_cond_broadcast(&COND_refresh)); // Signal to refresh
+ DBUG_VOID_RETURN;
}
@@ -1250,17 +1252,19 @@ void close_old_data_files(THD *thd, TABLE *table, bool abort_locks)
if the table is closed
*/
-bool table_is_used(TABLE *table)
+bool table_is_used(TABLE *table, bool wait_for_name_lock)
{
do
{
char *key= table->table_cache_key;
uint key_length=table->key_length;
- for (TABLE *search=(TABLE*) hash_search(&open_cache,(byte*) key,key_length) ;
+ for (TABLE *search=(TABLE*) hash_search(&open_cache,
+ (byte*) key,key_length) ;
search ;
search = (TABLE*) hash_next(&open_cache,(byte*) key,key_length))
{
if (search->locked_by_flush ||
+ search->locked_by_name && wait_for_name_lock ||
search->db_stat && search->version < refresh_version)
return 1; // Table is used
}
@@ -1278,19 +1282,14 @@ bool wait_for_tables(THD *thd)
thd->proc_info="Waiting for tables";
pthread_mutex_lock(&LOCK_open);
- thd->some_tables_deleted=0;
- close_old_data_files(thd,thd->open_tables,0);
- if (dropping_tables)
- {
- (void) pthread_cond_broadcast(&COND_refresh); // Signal to refresh/delete
- (void) pthread_cond_wait(&COND_refresh,&LOCK_open);
- }
-
- while (table_is_used(thd->open_tables) && ! thd->killed)
+ while (!thd->killed)
{
- (void) pthread_cond_wait(&COND_refresh,&LOCK_open);
+ thd->some_tables_deleted=0;
+ close_old_data_files(thd,thd->open_tables,0,dropping_tables != 0);
+ if (!table_is_used(thd->open_tables,1))
+ break;
+ (void) pthread_cond_wait(&COND_refresh,&LOCK_open);
}
-
if (thd->killed)
result= 1; // aborted
else
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 8b7e16709c0..3fb96857007 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -1137,16 +1137,21 @@ mysql_execute_command(void)
goto error;
for (table=tables ; table ; table=table->next->next)
{
- if (check_access(thd, ALTER_ACL, table->db, &table->grant.privilege) ||
+ if (check_access(thd, ALTER_ACL | DROP_ACL, table->db,
+ &table->grant.privilege) ||
check_access(thd, INSERT_ACL | CREATE_ACL, table->next->db,
&table->next->grant.privilege))
goto error;
if (grant_option)
{
- if (check_grant(thd,ALTER_ACL,table) ||
+ TABLE_LIST old_list,new_list;
+ old_list=table[0];
+ new_list=table->next[0];
+ old_list.next=new_list.next=0;
+ if (check_grant(thd,ALTER_ACL,&old_list) ||
(!test_all_bits(table->next->grant.privilege,
INSERT_ACL | CREATE_ACL) &&
- check_grant(thd,INSERT_ACL | CREATE_ACL, table->next)))
+ check_grant(thd,INSERT_ACL | CREATE_ACL, &new_list)))
goto error;
}
}
@@ -1170,9 +1175,8 @@ mysql_execute_command(void)
#endif
case SQLCOM_REPAIR:
{
- if (!tables->db)
- tables->db=thd->db;
- if (check_table_access(thd,SELECT_ACL | INSERT_ACL, tables))
+ if (check_db_used(thd,tables) ||
+ check_table_access(thd,SELECT_ACL | INSERT_ACL, tables))
goto error; /* purecov: inspected */
res = mysql_repair_table(thd, tables, &lex->check_opt);
break;
@@ -1695,6 +1699,10 @@ error:
** Get the user (global) and database privileges for all used tables
** Returns true (error) if we can't get the privileges and we don't use
** table/column grants.
+** The idea of EXTRA_ACL is that one will be granted access to the table if
+** one has the asked privilege on any column combination of the table; For
+** example to be able to check a table one needs to have SELECT privilege on
+** any column of the table.
****************************************************************************/
bool
@@ -1760,7 +1768,8 @@ check_table_access(THD *thd,uint want_access,TABLE_LIST *tables)
TABLE_LIST *org_tables=tables;
for (; tables ; tables=tables->next)
{
- if ((thd->master_access & want_access) == want_access && thd->db)
+ if ((thd->master_access & want_access) == (want_access & ~EXTRA_ACL) &&
+ thd->db)
tables->grant.privilege= want_access;
else if (tables->db && tables->db == thd->db)
{
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 6578e3b717a..4ee0343274a 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -29,7 +29,7 @@
#include <assert.h>
const char *join_type_str[]={ "UNKNOWN","system","const","eq_ref","ref",
- "MAYBE_REF","ALL","range","index" };
+ "MAYBE_REF","ALL","range","index","fulltext" };
static bool make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
DYNAMIC_ARRAY *keyuse,List<Item_func_match> &ftfuncs);
@@ -800,6 +800,14 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
if ((s->on_expr=tables->on_expr))
{
// table->maybe_null=table->outer_join=1; // Mark for send fields
+ if (!table->file->records)
+ { // Empty table
+ s->key_dependent=s->dependent=0;
+ s->type=JT_SYSTEM;
+ const_table_map|=table->map;
+ set_position(join,const_count++,s,(KEYUSE*) 0);
+ continue;
+ }
s->key_dependent=s->dependent=
s->on_expr->used_tables() & ~(table->map);
s->dependent|=stat_vector[i-1]->dependent | table_vector[i-1]->map;
@@ -1272,15 +1280,54 @@ static void
add_ft_keys(DYNAMIC_ARRAY *keyuse_array,
JOIN_TAB *stat,COND *cond,table_map usable_tables)
{
- /* for now, handling only the simples WHERE MATCH (...) case */
- /* a bit more complex WHERE MATCH (...) > const,
- AND's and (perhaps) OR's are on the way SerG */
+ Item_func_match *cond_func=NULL;
+
+ if (cond->type() == Item::FUNC_ITEM)
+ {
+ Item_func *func=(Item_func *)cond,
+ *arg0=(Item_func *)(func->arguments()[0]),
+ *arg1=(Item_func *)(func->arguments()[1]);
+
+ if (func->functype() == Item_func::FT_FUNC)
+ cond_func=(Item_func_match *)cond;
+ else if (arg0->type() == Item::FUNC_ITEM &&
+ arg0->functype() == Item_func::FT_FUNC &&
+ (func->functype() == Item_func::GE_FUNC ||
+ func->functype() == Item_func::GT_FUNC) &&
+ arg1->const_item() && arg1->val()>=0)
+ cond_func=(Item_func_match *)arg0;
+ else if (arg1->type() == Item::FUNC_ITEM &&
+ arg1->functype() == Item_func::FT_FUNC &&
+ (func->functype() == Item_func::LE_FUNC ||
+ func->functype() == Item_func::LT_FUNC) &&
+ arg0->const_item() && arg0->val()>=0)
+ cond_func=(Item_func_match *)arg1;
+ }
+ else if (cond->type() == Item::COND_ITEM)
+ {
+ List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
- if (cond->type() != Item::FUNC_ITEM ||
- ((Item_func*) cond)->functype() != Item_func::FT_FUNC)
- return;
+ if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
+ {
+ Item *item;
+ /* I'm too lazy to implement proper recursive descent here,
+ and anyway, nobody will use such a stupid queries
+ that will require it :-)
+ May be later...
+ */
+ while ((item=li++))
+ if (item->type() == Item::FUNC_ITEM &&
+ ((Item_func *)item)->functype() == Item_func::FT_FUNC)
+ {
+ cond_func=(Item_func_match *)item;
+ break;
+ }
+ }
+ }
+
+ if(!cond_func)
+ return;
- Item_func_match *cond_func= (Item_func_match *) cond;
KEYUSE keyuse;
keyuse.table= cond_func->table;
@@ -1928,8 +1975,7 @@ get_best_combination(JOIN *join)
if (ftkey)
{
j->ref.items[0]=((Item_func*)(keyuse->val))->key_item();
- if (!keyuse->used_tables &&
- !(join->select_options & SELECT_DESCRIBE))
+ if (!keyuse->used_tables)
{
// AFAIK key_buff is zeroed...
// We don't need to free ft_tmp as the buffer will be freed atom.
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 66141a8591c..b862ee60893 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -1,15 +1,15 @@
/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
+
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
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
-
+
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
-
+
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
@@ -488,7 +488,7 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list)
if (send_fields(thd,field_list,1))
DBUG_RETURN(1);
-
+
String *packet = &thd->packet;
for(;table; table = table->next)
{
@@ -510,7 +510,7 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list)
// into fewer, so we cannot use net_store_data() anymore,
// and do it ourselves
char* p = (char*)packet->ptr() + store_len_offset;
- *p++ = (char) 253; // The client the length is stored using 3-bytes
+ *p++ = (char) 253; // The client the length is stored using 3-bytes
int3store(p, create_len);
// now we are in business :-)
@@ -649,10 +649,10 @@ mysqld_dump_create_info(THD *thd, TABLE *table, int fd)
DBUG_PRINT("enter",("table: %s",table->real_name));
String* packet = &thd->packet;
packet->length(0);
-
+
if(store_create_info(thd,table,packet))
DBUG_RETURN(-1);
-
+
if(fd < 0)
{
if(my_net_write(&thd->net, (char*)packet->ptr(), packet->length()))
@@ -661,14 +661,14 @@ mysqld_dump_create_info(THD *thd, TABLE *table, int fd)
}
else
{
- if(my_write(fd, (const byte*) packet->ptr(), packet->length(),
+ if(my_write(fd, (const byte*) packet->ptr(), packet->length(),
MYF(MY_WME)))
DBUG_RETURN(-1);
}
DBUG_RETURN(0);
}
-
+
static int
store_create_info(THD *thd, TABLE *table, String* packet)
{
@@ -676,37 +676,37 @@ store_create_info(THD *thd, TABLE *table, String* packet)
DBUG_PRINT("enter",("table: %s",table->real_name));
restore_record(table,2); // Get empty record
-
+
List<Item> field_list;
char tmp[MAX_FIELD_WIDTH];
String type(tmp, sizeof(tmp));
packet->append("create table ", 13);
packet->append(table->real_name);
packet->append('(');
-
+
Field **ptr,*field;
for (ptr=table->field ; (field= *ptr); ptr++)
{
if(ptr != table->field)
packet->append(',');
-
+
uint flags = field->flags;
packet->append(field->field_name);
packet->append(' ');
// check for surprises from the previous call to Field::sql_type()
if(type.ptr() != tmp)
type.set(tmp, sizeof(tmp));
-
+
field->sql_type(type);
packet->append(type.ptr(),type.length());
-
+
bool null_default_value = (field->type() == FIELD_TYPE_TIMESTAMP ||
field->unireg_check == Field::NEXT_NUMBER);
bool has_default = (field->type() != FIELD_TYPE_BLOB);
-
+
if((flags & NOT_NULL_FLAG) && !null_default_value)
packet->append(" not null", 9);
-
+
if(has_default)
{
@@ -724,51 +724,54 @@ store_create_info(THD *thd, TABLE *table, String* packet)
else
packet->append(tmp,0);
}
-
+
if (field->unireg_check == Field::NEXT_NUMBER)
packet->append(" auto_increment", 15 );
-
+
}
KEY *key_info=table->key_info;
table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK | HA_STATUS_TIME);
uint primary_key = table->primary_key;
-
+
for (uint i=0 ; i < table->keys ; i++,key_info++)
{
packet->append(',');
-
+
KEY_PART_INFO *key_part= key_info->key_part;
if(i == primary_key)
packet->append("primary", 7);
else if(key_info->flags & HA_NOSAME)
packet->append("unique", 6);
+ else if(key_info->flags & HA_FULLTEXT)
+ packet->append("fulltext", 8);
packet->append(" key ", 5);
if(i != primary_key)
packet->append(key_info->name);
-
+
packet->append('(');
-
+
for (uint j=0 ; j < key_info->key_parts ; j++,key_part++)
{
if(j)
packet->append(',');
-
+
if(key_part->field)
packet->append(key_part->field->field_name);
KEY *key=table->key_info+i;
-
+
if (!key_part->field ||
- key_part->length !=
- table->field[key_part->fieldnr-1]->key_length())
+ (key_part->length !=
+ table->field[key_part->fieldnr-1]->key_length() &&
+ !(key_info->flags & HA_FULLTEXT)))
{
char buff[64];
buff[0] = '(';
char* end=int10_to_str((long) key_part->length, buff + 1,10);
*end++ = ')';
- packet->append(buff,(uint) (end-buff));
+ packet->append(buff,(uint) (end-buff));
}
}
@@ -776,13 +779,13 @@ store_create_info(THD *thd, TABLE *table, String* packet)
}
packet->append(')');
-
+
handler *file = table->file;
packet->append(" type=", 6);
packet->append(file->table_type());
char buff[128];
char* p;
-
+
if(table->min_rows)
{
packet->append(" min_rows=");
@@ -796,7 +799,7 @@ store_create_info(THD *thd, TABLE *table, String* packet)
p = longlong10_to_str(table->max_rows, buff, 10);
packet->append(buff, (uint) (p - buff));
}
-
+
if (table->db_create_options & HA_OPTION_PACK_KEYS)
packet->append(" pack_keys=1", 12);
if (table->db_create_options & HA_OPTION_NO_PACK_KEYS)
@@ -806,7 +809,7 @@ store_create_info(THD *thd, TABLE *table, String* packet)
if (table->db_create_options & HA_OPTION_DELAY_KEY_WRITE)
packet->append(" delay_key_write=1",18);
-
+
DBUG_RETURN(0);
}
diff --git a/sql/table.h b/sql/table.h
index 7fe3e5de601..198e0d6e801 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -91,6 +91,7 @@ struct st_table {
my_bool crypted;
my_bool db_low_byte_first; /* Portable row format */
my_bool locked_by_flush;
+ my_bool locked_by_name;
Field *next_number_field, /* Set if next_number is activated */
*found_next_number_field, /* Set on open */
*rowid_field;