diff options
Diffstat (limited to 'sql')
-rw-r--r-- | sql/ha_heap.cc | 15 | ||||
-rw-r--r-- | sql/ha_heap.h | 5 | ||||
-rw-r--r-- | sql/handler.cc | 4 | ||||
-rw-r--r-- | sql/handler.h | 2 | ||||
-rw-r--r-- | sql/lock.cc | 22 | ||||
-rw-r--r-- | sql/mini_client.cc | 7 | ||||
-rw-r--r-- | sql/mysql_priv.h | 7 | ||||
-rw-r--r-- | sql/mysqld.cc | 62 | ||||
-rw-r--r-- | sql/opt_range.cc | 12 | ||||
-rw-r--r-- | sql/sql_base.cc | 35 | ||||
-rw-r--r-- | sql/sql_parse.cc | 23 | ||||
-rw-r--r-- | sql/sql_select.cc | 66 | ||||
-rw-r--r-- | sql/sql_show.cc | 65 | ||||
-rw-r--r-- | sql/table.h | 1 |
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; |