diff options
Diffstat (limited to 'sql')
-rw-r--r-- | sql/ha_heap.cc | 2 | ||||
-rw-r--r-- | sql/ha_heap.h | 9 | ||||
-rw-r--r-- | sql/ha_myisam.h | 2 | ||||
-rw-r--r-- | sql/ha_myisammrg.cc | 18 | ||||
-rw-r--r-- | sql/ha_myisammrg.h | 16 | ||||
-rw-r--r-- | sql/handler.h | 3 | ||||
-rw-r--r-- | sql/lex.h | 5 | ||||
-rw-r--r-- | sql/mysql_priv.h | 6 | ||||
-rw-r--r-- | sql/sql_acl.cc | 1 | ||||
-rw-r--r-- | sql/sql_lex.h | 27 | ||||
-rw-r--r-- | sql/sql_parse.cc | 50 | ||||
-rw-r--r-- | sql/sql_select.cc | 33 | ||||
-rw-r--r-- | sql/sql_table.cc | 4 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 13 |
14 files changed, 122 insertions, 67 deletions
diff --git a/sql/ha_heap.cc b/sql/ha_heap.cc index 591ca0bc813..5bdbf75749e 100644 --- a/sql/ha_heap.cc +++ b/sql/ha_heap.cc @@ -261,7 +261,7 @@ ha_rows ha_heap::records_in_range(int 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) + end_search_flag != HA_READ_AFTER_KEY) return HA_POS_ERROR; // Can't only use exact keys return 10; // Good guess } diff --git a/sql/ha_heap.h b/sql/ha_heap.h index b56ee84822f..b3651a3957b 100644 --- a/sql/ha_heap.h +++ b/sql/ha_heap.h @@ -33,14 +33,15 @@ class ha_heap: public handler const char *table_type() const { return "HEAP"; } const char **bas_ext() const; ulong option_flag() const - { return (HA_READ_RND_SAME+HA_NO_INDEX+HA_BINARY_KEYS+HA_WRONG_ASCII_ORDER+ - HA_KEYPOS_TO_RNDPOS+HA_NO_BLOBS+HA_REC_NOT_IN_SEQ); } + { return (HA_READ_RND_SAME | HA_NO_INDEX | HA_ONLY_WHOLE_INDEX | + HA_WRONG_ASCII_ORDER | HA_KEYPOS_TO_RNDPOS | HA_NO_BLOBS | + HA_REC_NOT_IN_SEQ); } uint max_record_length() const { return HA_MAX_REC_LENGTH; } uint max_keys() const { return MAX_KEY; } uint max_key_parts() const { return MAX_REF_PARTS; } uint max_key_length() const { return HA_MAX_REC_LENGTH; } - virtual double scan_time() { return (double) (records+deleted) / 100.0; } - virtual double read_time(ha_rows rows) { return (double) rows / 100.0; } + virtual double scan_time() { return (double) (records+deleted) / 20.0+10; } + virtual double read_time(ha_rows rows) { return (double) rows / 20.0+1; } virtual bool fast_key_read() { return 1;} int open(const char *name, int mode, int test_if_locked); diff --git a/sql/ha_myisam.h b/sql/ha_myisam.h index c8f097e792f..e9ae9670b2f 100644 --- a/sql/ha_myisam.h +++ b/sql/ha_myisam.h @@ -45,7 +45,7 @@ class ha_myisam: public handler const char **bas_ext() const; ulong option_flag() const { return int_option_flag; } uint max_record_length() const { return HA_MAX_REC_LENGTH; } - uint max_keys() const { return 1; } + uint max_keys() const { return MI_MAX_KEY; } uint max_key_parts() const { return MAX_REF_PARTS; } uint max_key_length() const { return MAX_KEY_LENGTH; } diff --git a/sql/ha_myisammrg.cc b/sql/ha_myisammrg.cc index 4e6a1f19583..45822444527 100644 --- a/sql/ha_myisammrg.cc +++ b/sql/ha_myisammrg.cc @@ -180,11 +180,7 @@ void ha_myisammrg::info(uint flag) mean_rec_length=info.reclength; block_size=0; update_time=0; -#if SIZEOF_OFF_T > 4 ref_length=6; // Should be big enough -#else - ref_length=4; -#endif } @@ -228,6 +224,16 @@ THR_LOCK_DATA **ha_myisammrg::store_lock(THD *thd, int ha_myisammrg::create(const char *name, register TABLE *form, HA_CREATE_INFO *create_info) { - char buff[FN_REFLEN]; - return myrg_create(fn_format(buff,name,"","",2+4+16),0); + char buff[FN_REFLEN],**table_names,**pos; + TABLE_LIST *tables= (TABLE_LIST*) create_info->merge_list.first; + DBUG_ENTER("ha_myisammrg::create"); + + if (!(table_names= (char**) sql_alloc((create_info->merge_list.elements+1)* + sizeof(char*)))) + DBUG_RETURN(1); + for (pos=table_names ; tables ; tables=tables->next) + *pos++= tables->real_name; + *pos=0; + DBUG_RETURN(myrg_create(fn_format(buff,name,"","",2+4+16), + (const char **) table_names, (my_bool) 0)); } diff --git a/sql/ha_myisammrg.h b/sql/ha_myisammrg.h index 864b2f1760c..376c4edf18f 100644 --- a/sql/ha_myisammrg.h +++ b/sql/ha_myisammrg.h @@ -32,15 +32,19 @@ class ha_myisammrg: public handler ~ha_myisammrg() {} const char *table_type() const { return "MRG_MyISAM"; } const char **bas_ext() const; - ulong option_flag() const { return HA_REC_NOT_IN_SEQ+HA_READ_NEXT+ - HA_READ_PREV+HA_READ_RND_SAME+HA_HAVE_KEY_READ_ONLY+ - HA_KEYPOS_TO_RNDPOS+HA_READ_ORDER+ - HA_LASTKEY_ORDER+HA_READ_NOT_EXACT_KEY+ - HA_LONGLONG_KEYS+HA_NULL_KEY+HA_BLOB_KEY; } + ulong option_flag() const + { return (HA_REC_NOT_IN_SEQ | HA_READ_NEXT | + HA_READ_PREV | HA_READ_RND_SAME | + HA_HAVE_KEY_READ_ONLY | + HA_KEYPOS_TO_RNDPOS | HA_READ_ORDER | + HA_LASTKEY_ORDER | HA_READ_NOT_EXACT_KEY | + HA_LONGLONG_KEYS | HA_NULL_KEY | HA_BLOB_KEY); } uint max_record_length() const { return HA_MAX_REC_LENGTH; } - uint max_keys() const { return 1; } + uint max_keys() const { return MI_MAX_KEY; } uint max_key_parts() const { return MAX_REF_PARTS; } uint max_key_length() const { return MAX_KEY_LENGTH; } + virtual double scan_time() + { return ulonglong2double(data_file_length) / IO_SIZE + file->tables; } int open(const char *name, int mode, int test_if_locked); int close(void); diff --git a/sql/handler.h b/sql/handler.h index 70b05f0c7f7..3bf35cc8804 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -47,7 +47,7 @@ if database is updated after read) */ #define HA_REC_NOT_IN_SEQ 64 /* ha_info don't return recnumber; It returns a position to ha_r_rnd */ -#define HA_BINARY_KEYS 128 /* Keys must be exact */ +#define HA_ONLY_WHOLE_INDEX 128 /* Can't use part key searches */ #define HA_RSAME_NO_INDEX 256 /* RSAME can't restore index */ #define HA_WRONG_ASCII_ORDER 512 /* Can't use sorting through key */ #define HA_HAVE_KEY_READ_ONLY 1024 /* Can read only keys (no record) */ @@ -127,6 +127,7 @@ typedef struct st_ha_create_information ulong raid_chunksize; bool if_not_exists; ulong used_fields; + SQL_LIST merge_list; } HA_CREATE_INFO; diff --git a/sql/lex.h b/sql/lex.h index 2be54a56b1a..de4bd69fa87 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -297,11 +297,12 @@ static SYMBOL symbols[] = { { "TRAILING", SYM(TRAILING),0,0}, { "TO", SYM(TO_SYM),0,0}, { "TYPE", SYM(TYPE_SYM),0,0}, - { "USE", SYM(USE_SYM),0,0}, - { "USING", SYM(USING),0,0}, + { "UNION", SYM(UNION_SYM),0,0}, { "UNIQUE", SYM(UNIQUE_SYM),0,0}, { "UNLOCK", SYM(UNLOCK_SYM),0,0}, { "UNSIGNED", SYM(UNSIGNED),0,0}, + { "USE", SYM(USE_SYM),0,0}, + { "USING", SYM(USING),0,0}, { "UPDATE", SYM(UPDATE_SYM),0,0}, { "USAGE", SYM(USAGE),0,0}, { "VALUES", SYM(VALUES),0,0}, diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 3b5c87fcab2..18930468541 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -78,7 +78,11 @@ void sql_element_free(void *ptr); // The following is used to decide if MySQL should use table scanning // instead of reading with keys. The number says how many evaluation of the // WHERE clause is comparable to reading one extra row from a table. -#define TIME_FOR_COMPARE 5 // 5 compares == one read +#define TIME_FOR_COMPARE 5 // 5 compares == one read +// Number of rows in a reference table when refereed through a not unique key. +// This value is only used when we don't know anything about the key +// distribution. +#define MATCHING_ROWS_IN_OTHER_TABLE 10 /* Don't pack string keys shorter than this (if PACK_KEYS=1 isn't used) */ #define KEY_DEFAULT_PACK_LENGTH 8 diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 6e1bfb23abe..5089c8d75ee 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -1905,6 +1905,7 @@ int grant_init (void) { t_table->file->index_end(); mysql_unlock_tables(thd, lock); + thd->version--; // Force close to free memory close_thread_tables(thd); delete thd; DBUG_RETURN(0); // Empty table is ok! diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 083bc8a83b5..9a22d4dab04 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -94,16 +94,9 @@ typedef struct st_lex { LEX_YYSTYPE yylval; uchar *ptr,*tok_start,*tok_end,*end_of_query; ha_rows select_limit,offset_limit; - bool create_refs,drop_primary,drop_if_exists,local_file, - in_comment,ignore_space,verbose; - enum_sql_command sql_command; - enum lex_states next_state; - ulong options; - uint in_sum_expr,grant,grant_tot_col,which_columns, sort_default; char *length,*dec,*change,*name; String *wild; sql_exchange *exchange; - thr_lock_type lock_option; List<List_item> expr_list; List<List_item> when_list; @@ -124,17 +117,25 @@ typedef struct st_lex { create_field *last_field; Item *where,*having,*default_value; - enum enum_duplicates duplicates; - ulong thread_id,type; - HA_CREATE_INFO create_info; CONVERT *convert_set; - LEX_USER *grant_user; + LEX_USER *grant_user; char *db,*db1,*table1,*db2,*table2; /* For outer join using .. */ gptr yacc_yyss,yacc_yyvs; THD *thd; udf_func udf; - HA_CHECK_OPT check_opt; // check/repair options - LEX_MASTER_INFO mi; // used by CHANGE MASTER + HA_CHECK_OPT check_opt; // check/repair options + HA_CREATE_INFO create_info; + LEX_MASTER_INFO mi; // used by CHANGE MASTER + ulong thread_id,type; + ulong options; + enum_sql_command sql_command; + enum lex_states next_state; + enum enum_duplicates duplicates; + uint in_sum_expr,grant,grant_tot_col,which_columns, sort_default; + thr_lock_type lock_option; + bool create_refs,drop_primary,drop_if_exists,local_file; + bool in_comment,ignore_space,verbose; + } LEX; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index a2ef4354521..97eb7c80b50 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -38,8 +38,9 @@ extern "C" pthread_mutex_t THR_LOCK_keycache; extern "C" int gethostname(char *name, int namelen); #endif -static bool check_table_access(THD *thd,uint want_access,TABLE_LIST *tables); +static bool check_table_access(THD *thd,uint want_access, TABLE_LIST *tables); static bool check_db_used(THD *thd,TABLE_LIST *tables); +static bool check_merge_table_access(THD *thd, char *db, TABLE_LIST *tables); static bool check_dup(THD *thd,const char *db,const char *name, TABLE_LIST *tables); static void mysql_init_query(THD *thd); @@ -504,9 +505,9 @@ int mysql_table_dump(THD* thd, char* db, char* tbl_name, int fd) if(!(table=open_ltable(thd, table_list, TL_READ_NO_INSERT))) DBUG_RETURN(1); - if(check_access(thd, SELECT_ACL, db, &table_list->grant.privilege)) + if (check_access(thd, SELECT_ACL, db, &table_list->grant.privilege)) goto err; - if(grant_option && check_grant(thd, SELECT_ACL, table_list)) + if (grant_option && check_grant(thd, SELECT_ACL, table_list)) goto err; thd->free_list = 0; @@ -988,10 +989,12 @@ mysql_execute_command(void) break; case SQLCOM_CREATE_TABLE: -#ifdef DEMO_VERSION - send_error(&thd->net,ER_NOT_ALLOWED_COMMAND); -#else - if (check_access(thd,CREATE_ACL,tables->db,&tables->grant.privilege)) + if (!tables->db) + tables->db=thd->db; + if (check_access(thd,CREATE_ACL,tables->db,&tables->grant.privilege) || + check_merge_table_access(thd, tables->db, + (TABLE_LIST *) + lex->create_info.merge_list.first)) goto error; /* purecov: inspected */ if (grant_option) { @@ -1072,7 +1075,6 @@ mysql_execute_command(void) if (grant_option && check_grant(thd,INDEX_ACL,tables)) goto error; res = mysql_create_index(thd, tables, lex->key_list); -#endif break; case SQLCOM_SLAVE_START: @@ -1082,7 +1084,6 @@ mysql_execute_command(void) stop_slave(thd); break; - case SQLCOM_ALTER_TABLE: #if defined(DONT_ALLOW_SHOW_COMMANDS) send_error(&thd->net,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */ @@ -1096,11 +1097,16 @@ mysql_execute_command(void) res=0; break; } + if (!tables->db) + tables->db=thd->db; if (!lex->db) lex->db=tables->db; if (check_access(thd,ALTER_ACL,tables->db,&tables->grant.privilege) || - check_access(thd,INSERT_ACL | CREATE_ACL,lex->db,&priv)) - goto error; /* purecov: inspected */ + check_access(thd,INSERT_ACL | CREATE_ACL,lex->db,&priv) || + check_merge_table_access(thd, tables->db, + (TABLE_LIST *) + lex->create_info.merge_list.first)) + goto error; /* purecov: inspected */ if (!tables->db) tables->db=thd->db; if (grant_option) @@ -1354,7 +1360,7 @@ mysql_execute_command(void) res = mysql_drop_index(thd, tables, lex->drop_list); break; case SQLCOM_SHOW_DATABASES: -#if defined(DONT_ALLOW_SHOW_COMMANDS) || defined(DEMO_VERSION) +#if defined(DONT_ALLOW_SHOW_COMMANDS) send_error(&thd->net,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */ DBUG_VOID_RETURN; #else @@ -1810,6 +1816,22 @@ static bool check_db_used(THD *thd,TABLE_LIST *tables) } +static bool check_merge_table_access(THD *thd, char *db, TABLE_LIST *table_list) +{ + int error=0; + if (table_list) + { + /* Force all tables to use the current database */ + TABLE_LIST *tmp; + for (tmp=table_list; tmp ; tmp=tmp->next) + tmp->db=db; + error=check_table_access(thd, SELECT_ACL | UPDATE_ACL | DELETE_ACL, + table_list); + } + return error; +} + + /**************************************************************************** Check stack size; Send error if there isn't enough stack to continue ****************************************************************************/ @@ -2462,7 +2484,7 @@ static int start_slave(THD* thd , bool net_report) if(!thd) thd = current_thd; NET* net = &thd->net; const char* err = 0; - if(check_access(thd, PROCESS_ACL, any_db)) + if (check_access(thd, PROCESS_ACL, any_db)) return 1; pthread_mutex_lock(&LOCK_slave); if(!slave_running) @@ -2497,7 +2519,7 @@ static int stop_slave(THD* thd, bool net_report ) NET* net = &thd->net; const char* err = 0; - if(check_access(thd, PROCESS_ACL, any_db)) + if (check_access(thd, PROCESS_ACL, any_db)) return 1; pthread_mutex_lock(&LOCK_slave); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index d9d3d90f0d8..54569e241e0 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -942,7 +942,7 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds, } /* Approximate found rows and time to read them */ s->found_records=s->records=s->table->file->records; - s->read_time=(ha_rows) ((s->table->file->data_file_length)/IO_SIZE)+1; + s->read_time=(ha_rows) s->table->file->scan_time(); /* Set a max range of how many seeks we can expect when using keys */ s->worst_seeks= (double) (s->read_time*2); @@ -1419,18 +1419,18 @@ update_ref_and_keys(DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,uint tables, for (i=0 ; i < keyuse->elements-1 ; i++,use++) { if (!use->used_tables) - use->table->const_key_parts[use->key]|= + use->table->const_key_parts[use->key] |= (key_part_map) 1 << use->keypart; if (use->keypart != FT_KEYPART) { - if (use->key == prev->key && use->table == prev->table) - { - if (prev->keypart+1 < use->keypart || - prev->keypart == use->keypart && found_eq_constant) - continue; /* remove */ - } - else if (use->keypart != 0) // First found must be 0 - continue; + if (use->key == prev->key && use->table == prev->table) + { + if (prev->keypart+1 < use->keypart || + prev->keypart == use->keypart && found_eq_constant) + continue; /* remove */ + } + else if (use->keypart != 0) // First found must be 0 + continue; } *save_pos= *use; @@ -1532,7 +1532,7 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count, double best_records=DBL_MAX; /* Test how we can use keys */ - rec= s->records/10; /* Assume 10 records/key */ + rec= s->records/MATCHING_ROWS_IN_OTHER_TABLE; /* Assumed records/key */ for (keyuse=s->keyuse ; keyuse->table == table ;) { key_map found_part=0; @@ -1571,7 +1571,7 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count, if (map == 1) // Only one table { TABLE *tmp_table=join->all_tables[tablenr]; - if (rec > tmp_table->file->records) + if (rec > tmp_table->file->records && rec > 100) rec=max(tmp_table->file->records,100); } } @@ -1615,12 +1615,12 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count, } else { - if (!found_ref) // If not const key - { + if (!found_ref) + { // We found a const key if (table->quick_keys & ((key_map) 1 << key)) records= (double) table->quick_rows[key]; else - records= (double) s->records; // quick_range couldn't use key! + records= (double) s->records/rec; // quick_range couldn't use key! } else { @@ -1654,7 +1654,8 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count, ** than a not unique key ** Set tmp to (previous record count) * (records / combination) */ - if (found_part & 1) + if ((found_part & 1) && + !(table->file->option_flag() & HA_ONLY_WHOLE_INDEX)) { uint max_key_part=max_part_bit(found_part); /* Check if quick_range could determinate how many rows we diff --git a/sql/sql_table.cc b/sql/sql_table.cc index a3da4daa9f4..5a983c8cf06 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -176,7 +176,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, DBUG_ENTER("mysql_create_table"); /* - ** Check for dupplicate fields and check type of table to create + ** Check for duplicate fields and check type of table to create */ if (!fields.elements) @@ -302,7 +302,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name, bool primary_key=0,unique_key=0; Key *key; uint tmp; - tmp=max(file->max_keys(), MAX_KEY); + tmp=min(file->max_keys(), MAX_KEY); if (key_count > tmp) { diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index d4fec1289ba..e6952741b60 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -262,6 +262,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %token UDF_RETURNS_SYM %token UDF_SONAME_SYM %token UDF_SYM +%token UNION_SYM %token UNIQUE_SYM %token USAGE %token USE_SYM @@ -712,6 +713,18 @@ create_table_option: | RAID_TYPE EQ raid_types { Lex->create_info.raid_type= $3; Lex->create_info.used_fields|= HA_CREATE_USED_RAID;} | RAID_CHUNKS EQ ULONG_NUM { Lex->create_info.raid_chunks= $3; Lex->create_info.used_fields|= HA_CREATE_USED_RAID;} | RAID_CHUNKSIZE EQ ULONG_NUM { Lex->create_info.raid_chunksize= $3*RAID_BLOCK_SIZE; Lex->create_info.used_fields|= HA_CREATE_USED_RAID;} + | UNION_SYM EQ '(' table_list ')' + { + /* Move the union list to the merge_list */ + LEX *lex=Lex; + TABLE_LIST *table_list= (TABLE_LIST*) lex->table_list.first; + lex->create_info.merge_list= lex->table_list; + lex->create_info.merge_list.elements--; + lex->create_info.merge_list.first= (byte*) (table_list->next); + lex->table_list.elements=1; + lex->table_list.next= (byte**) &(table_list->next); + table_list->next=0; + } table_types: ISAM_SYM { $$= DB_TYPE_ISAM; } |