summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/ha_heap.cc2
-rw-r--r--sql/ha_heap.h9
-rw-r--r--sql/ha_myisam.h2
-rw-r--r--sql/ha_myisammrg.cc18
-rw-r--r--sql/ha_myisammrg.h16
-rw-r--r--sql/handler.h3
-rw-r--r--sql/lex.h5
-rw-r--r--sql/mysql_priv.h6
-rw-r--r--sql/sql_acl.cc1
-rw-r--r--sql/sql_lex.h27
-rw-r--r--sql/sql_parse.cc50
-rw-r--r--sql/sql_select.cc33
-rw-r--r--sql/sql_table.cc4
-rw-r--r--sql/sql_yacc.yy13
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; }