summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorunknown <kent@kent-amd64.(none)>2007-07-21 01:53:19 +0200
committerunknown <kent@kent-amd64.(none)>2007-07-21 01:53:19 +0200
commit47507276aa628ab51878ca36f0af47541ac04755 (patch)
tree0b56ddbf67df3ed64d453b4f68cc0e931ca79549 /sql
parent366c21fef8981a6ca3ac909eb14b75b99a0a5278 (diff)
parentd758b1e629a78e1cf58c8a04da51e3c33630368c (diff)
downloadmariadb-git-47507276aa628ab51878ca36f0af47541ac04755.tar.gz
Merge kboortz@bk-internal.mysql.com:/home/bk/mysql-5.0
into mysql.com:/home/kent/bk/tmp3/mysql-5.0-build libmysql/libmysql.c: Auto merged scripts/make_binary_distribution.sh: Auto merged sql/field.cc: Auto merged
Diffstat (limited to 'sql')
-rw-r--r--sql/field.cc3
-rw-r--r--sql/field_conv.cc17
-rw-r--r--sql/ha_heap.cc20
-rw-r--r--sql/ha_heap.h9
-rw-r--r--sql/ha_myisam.cc2
-rw-r--r--sql/item_cmpfunc.cc110
-rw-r--r--sql/item_cmpfunc.h2
-rw-r--r--sql/item_sum.cc1
-rw-r--r--sql/item_timefunc.cc5
-rw-r--r--sql/opt_range.cc40
-rw-r--r--sql/set_var.cc6
-rw-r--r--sql/share/charsets/ascii.xml2
-rw-r--r--sql/sql_class.h1
-rw-r--r--sql/sql_select.cc10
-rw-r--r--sql/sql_table.cc2
-rw-r--r--sql/unireg.cc2
16 files changed, 187 insertions, 45 deletions
diff --git a/sql/field.cc b/sql/field.cc
index 58832db04cd..78b2515c55f 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -5271,7 +5271,8 @@ int Field_newdate::store(const char *from,uint len,CHARSET_INFO *cs)
else
{
tmp= l_time.day + l_time.month*32 + l_time.year*16*32;
- if (!error && (ret != MYSQL_TIMESTAMP_DATE))
+ if (!error && (ret != MYSQL_TIMESTAMP_DATE) &&
+ thd->count_cuted_fields != CHECK_FIELD_IGNORE)
error= 3; // Datetime was cut (note)
}
diff --git a/sql/field_conv.cc b/sql/field_conv.cc
index a286255ec23..2705d4f617b 100644
--- a/sql/field_conv.cc
+++ b/sql/field_conv.cc
@@ -790,11 +790,18 @@ int field_conv(Field *to,Field *from)
blob->value.copy();
return blob->store(blob->value.ptr(),blob->value.length(),from->charset());
}
- if ((from->result_type() == STRING_RESULT &&
- (to->result_type() == STRING_RESULT ||
- (from->real_type() != FIELD_TYPE_ENUM &&
- from->real_type() != FIELD_TYPE_SET))) ||
- to->type() == FIELD_TYPE_DECIMAL)
+ if (from->real_type() == FIELD_TYPE_ENUM &&
+ to->real_type() == FIELD_TYPE_ENUM &&
+ from->val_int() == 0)
+ {
+ ((Field_enum *)(to))->store_type(0);
+ return 0;
+ }
+ else if ((from->result_type() == STRING_RESULT &&
+ (to->result_type() == STRING_RESULT ||
+ (from->real_type() != FIELD_TYPE_ENUM &&
+ from->real_type() != FIELD_TYPE_SET))) ||
+ to->type() == FIELD_TYPE_DECIMAL)
{
char buff[MAX_FIELD_WIDTH];
String result(buff,sizeof(buff),from->charset());
diff --git a/sql/ha_heap.cc b/sql/ha_heap.cc
index 8838aa99c1a..bf807407df1 100644
--- a/sql/ha_heap.cc
+++ b/sql/ha_heap.cc
@@ -115,6 +115,26 @@ int ha_heap::close(void)
/*
+ Create a copy of this table
+
+ DESCRIPTION
+ Do same as default implementation but use file->s->name instead of
+ table->s->path. This is needed by Windows where the clone() call sees
+ '/'-delimited path in table->s->path, while ha_peap::open() was called
+ with '\'-delimited path.
+*/
+
+handler *ha_heap::clone(MEM_ROOT *mem_root)
+{
+ handler *new_handler= get_new_handler(table, mem_root, table->s->db_type);
+ if (new_handler && !new_handler->ha_open(file->s->name, table->db_stat,
+ HA_OPEN_IGNORE_IF_LOCKED))
+ return new_handler;
+ return NULL; /* purecov: inspected */
+}
+
+
+/*
Compute which keys to use for scanning
SYNOPSIS
diff --git a/sql/ha_heap.h b/sql/ha_heap.h
index 18389c1298d..23583d0a6a7 100644
--- a/sql/ha_heap.h
+++ b/sql/ha_heap.h
@@ -32,6 +32,7 @@ class ha_heap: public handler
public:
ha_heap(TABLE *table);
~ha_heap() {}
+ handler *clone(MEM_ROOT *mem_root);
const char *table_type() const
{
return (table->in_use->variables.sql_mode & MODE_MYSQL323) ?
@@ -54,8 +55,8 @@ public:
ulong index_flags(uint inx, uint part, bool all_parts) const
{
return ((table->key_info[inx].algorithm == HA_KEY_ALG_BTREE) ?
- HA_READ_NEXT | HA_READ_PREV | HA_READ_ORDER | HA_READ_RANGE :
- HA_ONLY_WHOLE_INDEX);
+ HA_READ_NEXT | HA_READ_PREV | HA_READ_ORDER | HA_READ_RANGE :
+ HA_ONLY_WHOLE_INDEX | HA_KEY_SCAN_NOT_ROR);
}
const key_map *keys_to_use_for_scanning() { return &btree_keys; }
uint max_supported_keys() const { return MAX_KEY; }
@@ -101,9 +102,7 @@ public:
enum thr_lock_type lock_type);
int cmp_ref(const byte *ref1, const byte *ref2)
{
- HEAP_PTR ptr1=*(HEAP_PTR*)ref1;
- HEAP_PTR ptr2=*(HEAP_PTR*)ref2;
- return ptr1 < ptr2? -1 : (ptr1 > ptr2? 1 : 0);
+ return memcmp(ref1, ref2, sizeof(HEAP_PTR));
}
private:
void update_key_stats();
diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc
index 18c9e6feb34..92fa9e405e1 100644
--- a/sql/ha_myisam.cc
+++ b/sql/ha_myisam.cc
@@ -1809,6 +1809,8 @@ int ha_myisam::create(const char *name, register TABLE *table_arg,
if (ha_create_info->options & HA_LEX_CREATE_TMP_TABLE)
create_flags|= HA_CREATE_TMP_TABLE;
+ if (ha_create_info->options & HA_CREATE_KEEP_FILES)
+ create_flags|= HA_CREATE_KEEP_FILES;
if (options & HA_OPTION_PACK_RECORD)
create_flags|= HA_PACK_RECORD;
if (options & HA_OPTION_CHECKSUM)
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index ed0c09f0b32..86eb10d50b0 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -666,6 +666,67 @@ Arg_comparator::can_compare_as_dates(Item *a, Item *b, ulonglong *const_value)
}
+/*
+ Retrieves correct TIME value from the given item.
+
+ SYNOPSIS
+ get_time_value()
+ thd thread handle
+ item_arg [in/out] item to retrieve TIME value from
+ cache_arg [in/out] pointer to place to store the cache item to
+ warn_item [in] unused
+ is_null [out] TRUE <=> the item_arg is null
+
+ DESCRIPTION
+ Retrieves the correct TIME value from given item for comparison by the
+ compare_datetime() function.
+ If item's result can be compared as longlong then its int value is used
+ and a value returned by get_time function is used otherwise.
+ If an item is a constant one then its value is cached and it isn't
+ get parsed again. An Item_cache_int object is used for for cached values.
+ It seamlessly substitutes the original item. The cache item is marked as
+ non-constant to prevent re-caching it again.
+
+ RETURN
+ obtained value
+*/
+
+ulonglong
+get_time_value(THD *thd, Item ***item_arg, Item **cache_arg,
+ Item *warn_item, bool *is_null)
+{
+ ulonglong value;
+ Item *item= **item_arg;
+ MYSQL_TIME ltime;
+
+ if (item->result_as_longlong())
+ {
+ value= item->val_int();
+ *is_null= item->null_value;
+ }
+ else
+ {
+ *is_null= item->get_time(&ltime);
+ value= !*is_null ? TIME_to_ulonglong_datetime(&ltime) : 0;
+ }
+ /*
+ Do not cache GET_USER_VAR() function as its const_item() may return TRUE
+ for the current thread but it still may change during the execution.
+ */
+ if (item->const_item() && cache_arg && (item->type() != Item::FUNC_ITEM ||
+ ((Item_func*)item)->functype() != Item_func::GUSERVAR_FUNC))
+ {
+ Item_cache_int *cache= new Item_cache_int();
+ /* Mark the cache as non-const to prevent re-caching. */
+ cache->set_used_tables(1);
+ cache->store(item, value);
+ *cache_arg= cache;
+ *item_arg= cache_arg;
+ }
+ return value;
+}
+
+
int Arg_comparator::set_cmp_func(Item_bool_func2 *owner_arg,
Item **a1, Item **a2,
Item_result type)
@@ -704,8 +765,23 @@ int Arg_comparator::set_cmp_func(Item_bool_func2 *owner_arg,
}
is_nulls_eq= test(owner && owner->functype() == Item_func::EQUAL_FUNC);
func= &Arg_comparator::compare_datetime;
+ get_value_func= &get_datetime_value;
+ return 0;
+ }
+ else if (type == STRING_RESULT && (*a)->field_type() == MYSQL_TYPE_TIME &&
+ (*b)->field_type() == MYSQL_TYPE_TIME)
+ {
+ /* Compare TIME values as integers. */
+ thd= current_thd;
+ owner= owner_arg;
+ a_cache= 0;
+ b_cache= 0;
+ is_nulls_eq= test(owner && owner->functype() == Item_func::EQUAL_FUNC);
+ func= &Arg_comparator::compare_datetime;
+ get_value_func= &get_time_value;
return 0;
}
+
return set_compare_func(owner_arg, type);
}
@@ -723,8 +799,10 @@ void Arg_comparator::set_datetime_cmp_func(Item **a1, Item **b1)
b_cache= 0;
is_nulls_eq= FALSE;
func= &Arg_comparator::compare_datetime;
+ get_value_func= &get_datetime_value;
}
+
/*
Retrieves correct DATETIME value from given item.
@@ -838,8 +916,8 @@ int Arg_comparator::compare_datetime()
bool is_null= FALSE;
ulonglong a_value, b_value;
- /* Get DATE/DATETIME value of the 'a' item. */
- a_value= get_datetime_value(thd, &a, &a_cache, *b, &is_null);
+ /* Get DATE/DATETIME/TIME value of the 'a' item. */
+ a_value= (*get_value_func)(thd, &a, &a_cache, *b, &is_null);
if (!is_nulls_eq && is_null)
{
if (owner)
@@ -847,8 +925,8 @@ int Arg_comparator::compare_datetime()
return -1;
}
- /* Get DATE/DATETIME value of the 'b' item. */
- b_value= get_datetime_value(thd, &b, &b_cache, *a, &is_null);
+ /* Get DATE/DATETIME/TIME value of the 'b' item. */
+ b_value= (*get_value_func)(thd, &b, &b_cache, *a, &is_null);
if (is_null)
{
if (owner)
@@ -1716,6 +1794,7 @@ void Item_func_between::fix_length_and_dec()
THD *thd= current_thd;
int i;
bool datetime_found= FALSE;
+ int time_items_found= 0;
compare_as_dates= TRUE;
/*
@@ -1735,17 +1814,19 @@ void Item_func_between::fix_length_and_dec()
At least one of items should be a DATE/DATETIME item and other items
should return the STRING result.
*/
- for (i= 0; i < 3; i++)
+ if (cmp_type == STRING_RESULT)
{
- if (args[i]->is_datetime())
+ for (i= 0; i < 3; i++)
{
- datetime_found= TRUE;
- continue;
+ if (args[i]->is_datetime())
+ {
+ datetime_found= TRUE;
+ continue;
+ }
+ if (args[i]->field_type() == MYSQL_TYPE_TIME &&
+ args[i]->result_as_longlong())
+ time_items_found++;
}
- if (args[i]->result_type() == STRING_RESULT)
- continue;
- compare_as_dates= FALSE;
- break;
}
if (!datetime_found)
compare_as_dates= FALSE;
@@ -1755,6 +1836,11 @@ void Item_func_between::fix_length_and_dec()
ge_cmp.set_datetime_cmp_func(args, args + 1);
le_cmp.set_datetime_cmp_func(args, args + 2);
}
+ else if (time_items_found == 3)
+ {
+ /* Compare TIME items as integers. */
+ cmp_type= INT_RESULT;
+ }
else if (args[0]->real_item()->type() == FIELD_ITEM &&
thd->lex->sql_command != SQLCOM_CREATE_VIEW &&
thd->lex->sql_command != SQLCOM_SHOW_CREATE)
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index 79091b9c87d..9afc0507817 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -42,6 +42,8 @@ class Arg_comparator: public Sql_alloc
bool is_nulls_eq; // TRUE <=> compare for the EQUAL_FUNC
enum enum_date_cmp_type { CMP_DATE_DFLT= 0, CMP_DATE_WITH_DATE,
CMP_DATE_WITH_STR, CMP_STR_WITH_DATE };
+ ulonglong (*get_value_func)(THD *thd, Item ***item_arg, Item **cache_arg,
+ Item *warn_item, bool *is_null);
public:
DTCollation cmp_collation;
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index 133f00039b0..fe9f58d84e1 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -3068,6 +3068,7 @@ Item_func_group_concat::Item_func_group_concat(THD *thd,
original(item)
{
quick_group= item->quick_group;
+ result.set_charset(collation.collation);
}
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index 9795ec5f413..873e2833a1e 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -2662,11 +2662,8 @@ longlong Item_date_typecast::val_int()
{
DBUG_ASSERT(fixed == 1);
MYSQL_TIME ltime;
- if (args[0]->get_date(&ltime, TIME_FUZZY_DATE))
- {
- null_value= 1;
+ if ((null_value= args[0]->get_date(&ltime, TIME_FUZZY_DATE)))
return 0;
- }
return (longlong) (ltime.year * 10000L + ltime.month * 100 + ltime.day);
}
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index c3aa1f52556..247f0eada49 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -1131,8 +1131,16 @@ int QUICK_RANGE_SELECT::init_ror_merged_scan(bool reuse_handler)
THD *thd= current_thd;
if (!(file= head->file->clone(thd->mem_root)))
{
+ /*
+ Manually set the error flag. Note: there seems to be quite a few
+ places where a failure could cause the server to "hang" the client by
+ sending no response to a query. ATM those are not real errors because
+ the storage engine calls in question happen to never fail with the
+ existing storage engines.
+ */
+ thd->net.report_error= 1; /* purecov: inspected */
/* Caller will free the memory */
- goto failure;
+ goto failure; /* purecov: inspected */
}
if (file->external_lock(thd, F_RDLCK))
goto failure;
@@ -5816,6 +5824,11 @@ check_quick_select(PARAM *param,uint idx,SEL_ARG *tree)
param->is_ror_scan is cleared if the function detects that the key scan is
not a Rowid-Ordered Retrieval scan ( see comments for is_key_scan_ror
function for description of which key scans are ROR scans)
+
+ RETURN
+ #records E(#records) for given subtree
+ HA_POS_ERROR if subtree cannot be used for record retrieval
+
*/
static ha_rows
@@ -6007,27 +6020,24 @@ check_quick_keys(PARAM *param,uint idx,SEL_ARG *key_tree,
ROR (Rowid Ordered Retrieval) key scan is a key scan that produces
ordered sequence of rowids (ha_xxx::cmp_ref is the comparison function)
- An index scan is a ROR scan if it is done using a condition in form
+ This function is needed to handle a practically-important special case:
+ an index scan is a ROR scan if it is done using a condition in form
- "key1_1=c_1 AND ... AND key1_n=c_n" (1)
+ "key1_1=c_1 AND ... AND key1_n=c_n"
where the index is defined on (key1_1, ..., key1_N [,a_1, ..., a_n])
- and the table has a clustered Primary Key
-
- PRIMARY KEY(a_1, ..., a_n, b1, ..., b_k) with first key parts being
- identical to uncovered parts ot the key being scanned (2)
+ and the table has a clustered Primary Key defined as
- Scans on HASH indexes are not ROR scans,
- any range scan on clustered primary key is ROR scan (3)
-
- Check (1) is made in check_quick_keys()
- Check (3) is made check_quick_select()
- Check (2) is made by this function.
+ PRIMARY KEY(a_1, ..., a_n, b1, ..., b_k)
+
+ i.e. the first key parts of it are identical to uncovered parts ot the
+ key being scanned. This function assumes that the index flags do not
+ include HA_KEY_SCAN_NOT_ROR flag (that is checked elsewhere).
RETURN
- TRUE If the scan is ROR-scan
- FALSE otherwise
+ TRUE The scan is ROR-scan
+ FALSE Otherwise
*/
static bool is_key_scan_ror(PARAM *param, uint keynr, uint8 nparts)
diff --git a/sql/set_var.cc b/sql/set_var.cc
index 09cdc34f803..b30aa008366 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -592,6 +592,10 @@ sys_var_const_str sys_license("license", STRINGIFY_ARG(LICENSE));
/* Global read-only variable containing hostname */
sys_var_const_str sys_hostname("hostname", glob_hostname);
+sys_var_thd_bool sys_keep_files_on_create("keep_files_on_create",
+ &SV::keep_files_on_create);
+
+
/*
@@ -637,6 +641,7 @@ sys_var *sys_variables[]=
&sys_delayed_insert_limit,
&sys_delayed_insert_timeout,
&sys_delayed_queue_size,
+ &sys_keep_files_on_create,
&sys_error_count,
&sys_expire_logs_days,
&sys_flush,
@@ -849,6 +854,7 @@ struct show_var_st init_vars[]= {
{sys_delayed_insert_timeout.name, (char*) &sys_delayed_insert_timeout, SHOW_SYS},
{sys_delayed_queue_size.name,(char*) &sys_delayed_queue_size, SHOW_SYS},
{sys_div_precincrement.name,(char*) &sys_div_precincrement,SHOW_SYS},
+ {sys_keep_files_on_create.name,(char*) &sys_keep_files_on_create, SHOW_SYS},
{sys_engine_condition_pushdown.name,
(char*) &sys_engine_condition_pushdown, SHOW_SYS},
{sys_expire_logs_days.name, (char*) &sys_expire_logs_days, SHOW_SYS},
diff --git a/sql/share/charsets/ascii.xml b/sql/share/charsets/ascii.xml
index 97006c53680..068fb84eeae 100644
--- a/sql/share/charsets/ascii.xml
+++ b/sql/share/charsets/ascii.xml
@@ -97,7 +97,7 @@
0040 0041 0042 0043 0044 0045 0046 0047 0048 0049 004A 004B 004C 004D 004E 004F
0050 0051 0052 0053 0054 0055 0056 0057 0058 0059 005A 005B 005C 005D 005E 005F
0060 0061 0062 0063 0064 0065 0066 0067 0068 0069 006A 006B 006C 006D 006E 006F
-0070 0071 0072 0073 0074 0075 0076 0077 0078 0079 007A 007B 007C 007D 007E 0000
+0070 0071 0072 0073 0074 0075 0076 0077 0078 0079 007A 007B 007C 007D 007E 007F
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 0cfe8dc6668..445a3ce437c 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -566,6 +566,7 @@ struct system_variables
my_bool new_mode;
my_bool query_cache_wlock_invalidate;
my_bool engine_condition_pushdown;
+ my_bool keep_files_on_create;
#ifdef HAVE_INNOBASE_DB
my_bool innodb_table_locks;
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 6e0640d2cd4..d8bf8466f58 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -8486,9 +8486,15 @@ static void restore_prev_nj_state(JOIN_TAB *last)
{
TABLE_LIST *last_emb= last->table->pos_in_table_list->embedding;
JOIN *join= last->join;
- while (last_emb && !(--last_emb->nested_join->counter))
+ while (last_emb)
{
- join->cur_embedding_map &= last_emb->nested_join->nj_map;
+ if (!(--last_emb->nested_join->counter))
+ join->cur_embedding_map&= ~last_emb->nested_join->nj_map;
+ else if (last_emb->nested_join->join_list.elements-1 ==
+ last_emb->nested_join->counter)
+ join->cur_embedding_map|= last_emb->nested_join->nj_map;
+ else
+ break;
last_emb= last_emb->embedding;
}
}
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 87f23097a66..e02595836ca 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -2841,6 +2841,8 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, TABLE_LIST *src_table,
and temporary tables).
*/
*fn_ext(dst_path)= 0;
+ if (thd->variables.keep_files_on_create)
+ create_info->options|= HA_CREATE_KEEP_FILES;
err= ha_create_table(dst_path, create_info, 1);
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
diff --git a/sql/unireg.cc b/sql/unireg.cc
index c01e6a0f00c..d8e63bb78e1 100644
--- a/sql/unireg.cc
+++ b/sql/unireg.cc
@@ -285,6 +285,8 @@ int rea_create_table(THD *thd, my_string file_name,
if (mysql_create_frm(thd, file_name, db, table, create_info,
create_fields, keys, key_info, NULL))
DBUG_RETURN(1);
+ if (thd->variables.keep_files_on_create)
+ create_info->options|= HA_CREATE_KEEP_FILES;
if (!create_info->frm_only && ha_create_table(file_name,create_info,0))
{
my_delete(file_name,MYF(0));