Below is the list of changes that have just been committed into a local
5.0 repository of jonas. When jonas does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html
ChangeSet
1.1792 05/04/13 07:43:03 joreland@stripped +14 -0
Merge mysql.com:/home/jonas/src/mysql-5.0
into mysql.com:/home/jonas/src/mysql-5.0-ndb
sql/sql_select.cc
1.311 05/04/13 07:43:01 joreland@stripped +0 -0
Auto merged
sql/sql_parse.cc
1.421 05/04/13 07:43:01 joreland@stripped +0 -0
Auto merged
sql/sql_class.h
1.230 05/04/13 07:42:59 joreland@stripped +0 -0
Auto merged
sql/mysqld.cc
1.444 05/04/13 07:42:59 joreland@stripped +0 -0
Auto merged
sql/item.cc
1.108 05/04/13 07:42:59 joreland@stripped +0 -0
Auto merged
sql/ha_ndbcluster.cc
1.170 05/04/13 07:42:59 joreland@stripped +0 -0
Auto merged
ndb/test/ndbapi/testOIBasic.cpp
1.37 05/04/13 07:42:59 joreland@stripped +0 -0
Auto merged
ndb/src/ndbapi/NdbTransaction.cpp
1.43 05/04/13 07:42:59 joreland@stripped +0 -0
Auto merged
ndb/src/ndbapi/NdbScanOperation.cpp
1.66 05/04/13 07:42:58 joreland@stripped +0 -0
Auto merged
ndb/src/kernel/blocks/dbacc/DbaccMain.cpp
1.47 05/04/13 07:42:58 joreland@stripped +0 -0
Auto merged
ndb/include/ndbapi/NdbTransaction.hpp
1.41 05/04/13 07:42:58 joreland@stripped +0 -0
Auto merged
ndb/include/ndbapi/NdbScanOperation.hpp
1.32 05/04/13 07:42:58 joreland@stripped +0 -0
Auto merged
mysql-test/mysql-test-run.sh
1.262 05/04/13 07:42:58 joreland@stripped +0 -0
Auto merged
BitKeeper/etc/logging_ok
1.306 05/04/13 07:42:37 joreland@stripped +0 -0
auto-union
# This is a BitKeeper patch. What follows are the unified diffs for the
# set of deltas contained in the patch. The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User: joreland
# Host: eel.hemma.oreland.se
# Root: /home/jonas/src/mysql-5.0-ndb/RESYNC
--- 1.443/sql/mysqld.cc Mon Apr 11 14:31:11 2005
+++ 1.444/sql/mysqld.cc Wed Apr 13 07:42:59 2005
@@ -30,9 +30,6 @@
#include "ha_innodb.h"
#endif
#include "ha_myisam.h"
-#ifdef HAVE_ISAM
-#include "ha_isam.h"
-#endif
#ifdef HAVE_NDBCLUSTER_DB
#include "ha_ndbcluster.h"
#endif
@@ -47,11 +44,6 @@
#else
#define OPT_BDB_DEFAULT 0
#endif
-#ifdef HAVE_ISAM_DB
-#define OPT_ISAM_DEFAULT 1
-#else
-#define OPT_ISAM_DEFAULT 0
-#endif
#ifdef HAVE_NDBCLUSTER_DB
#define OPT_NDBCLUSTER_DEFAULT 0
#if defined(NOT_ENOUGH_TESTED) \
@@ -64,7 +56,6 @@
#define OPT_NDBCLUSTER_DEFAULT 0
#endif
-#include <nisam.h>
#include <thr_alarm.h>
#include <ft_global.h>
#include <errmsg.h>
@@ -1519,6 +1510,7 @@
thd=thread_cache.get();
thd->real_id=pthread_self();
(void) thd->store_globals();
+ thd->thr_create_time= time(NULL);
threads.append(thd);
pthread_mutex_unlock(&LOCK_thread_count);
DBUG_VOID_RETURN;
@@ -4342,7 +4334,7 @@
"Don't try to recover Berkeley DB tables on start.", 0, 0, 0, GET_NO_ARG,
NO_ARG, 0, 0, 0, 0, 0, 0},
{"bdb-no-sync", OPT_BDB_NOSYNC,
- "Disable synchronously flushing logs. This option is deprecated, use
--skip-sync-bdb-logs or sync-bdb-logs=0 instead",
+ "This option is deprecated, use --skip-sync-bdb-logs instead",
// (gptr*) &opt_sync_bdb_logs, (gptr*) &opt_sync_bdb_logs, 0, GET_BOOL,
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"bdb-shared-data", OPT_BDB_SHARED,
@@ -4551,9 +4543,8 @@
(gptr*) &global_system_variables.innodb_support_xa,
0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0},
#endif /* End HAVE_INNOBASE_DB */
- {"isam", OPT_ISAM, "Enable ISAM (if this version of MySQL supports it). \
-Disable with --skip-isam.",
- (gptr*) &opt_isam, (gptr*) &opt_isam, 0, GET_BOOL, NO_ARG, OPT_ISAM_DEFAULT,
0, 0,
+ {"isam", OPT_ISAM, "Obsolete. ISAM storage engine is no longer supported.",
+ (gptr*) &opt_isam, (gptr*) &opt_isam, 0, GET_BOOL, NO_ARG, 0, 0, 0,
0, 0, 0},
{"language", 'L',
"Client error messages in given language. May be given as a full path.",
@@ -5180,7 +5171,7 @@
(gptr*) &dflt_key_cache_var.param_buff_size,
(gptr*) 0,
0, (GET_ULL | GET_ASK_ADDR),
- REQUIRED_ARG, KEY_CACHE_SIZE, MALLOC_OVERHEAD, UINT_MAX32, MALLOC_OVERHEAD,
+ REQUIRED_ARG, KEY_CACHE_SIZE, MALLOC_OVERHEAD, ~(ulong) 0, MALLOC_OVERHEAD,
IO_SIZE, 0},
{"key_cache_age_threshold", OPT_KEY_CACHE_AGE_THRESHOLD,
"This characterizes the number of hits a hot block has to be untouched until it is
considered aged enough to be downgraded to a warm block. This specifies the percentage
ratio of that number of hits to the total number of blocks in key cache",
@@ -5469,36 +5460,35 @@
1, 0},
#ifdef HAVE_BERKELEY_DB
{"sync-bdb-logs", OPT_BDB_SYNC,
- "Synchronously flush logs. Enabled by default",
+ "Synchronously flush Berkeley DB logs. Enabled by default",
(gptr*) &opt_sync_bdb_logs, (gptr*) &opt_sync_bdb_logs, 0, GET_BOOL,
NO_ARG, 1, 0, 0, 0, 0, 0},
#endif /* HAVE_BERKELEY_DB */
{"sync-binlog", OPT_SYNC_BINLOG,
- "Sync the binlog to disk after every #th event. \
-#=0 (the default) does no sync. Syncing slows MySQL down",
- (gptr*) &sync_binlog_period,
- (gptr*) &sync_binlog_period, 0, GET_ULONG, REQUIRED_ARG, 0, 0, ~0L, 0, 1,
- 0},
+ "Synchronously flush binary log to disk after every #th event. "
+ "Use 0 (default) to disable synchronous flushing.",
+ (gptr*) &sync_binlog_period, (gptr*) &sync_binlog_period, 0, GET_ULONG,
+ REQUIRED_ARG, 0, 0, ~0L, 0, 1, 0},
+ {"sync-frm", OPT_SYNC_FRM, "Sync .frm to disk on create. Enabled by default.",
+ (gptr*) &opt_sync_frm, (gptr*) &opt_sync_frm, 0, GET_BOOL, NO_ARG, 1, 0,
+ 0, 0, 0, 0},
#ifdef DOES_NOTHING_YET
{"sync-replication", OPT_SYNC_REPLICATION,
- "Enable synchronous replication",
+ "Enable synchronous replication.",
(gptr*) &global_system_variables.sync_replication,
(gptr*) &global_system_variables.sync_replication,
0, GET_ULONG, REQUIRED_ARG, 0, 0, 1, 0, 1, 0},
{"sync-replication-slave-id", OPT_SYNC_REPLICATION_SLAVE_ID,
- "Synchronous replication is wished for this slave",
+ "Synchronous replication is wished for this slave.",
(gptr*) &global_system_variables.sync_replication_slave_id,
(gptr*) &global_system_variables.sync_replication_slave_id,
0, GET_ULONG, REQUIRED_ARG, 0, 0, ~0L, 0, 1, 0},
{"sync-replication-timeout", OPT_SYNC_REPLICATION_TIMEOUT,
- "Synchronous replication timeout",
+ "Synchronous replication timeout.",
(gptr*) &global_system_variables.sync_replication_timeout,
(gptr*) &global_system_variables.sync_replication_timeout,
0, GET_ULONG, REQUIRED_ARG, 10, 0, ~0L, 0, 1, 0},
#endif
- {"sync-frm", OPT_SYNC_FRM, "Sync .frm to disk on create. Enabled by default",
- (gptr*) &opt_sync_frm, (gptr*) &opt_sync_frm, 0, GET_BOOL, NO_ARG, 1, 0,
- 0, 0, 0, 0},
{"table_cache", OPT_TABLE_CACHE,
"The number of open tables for all threads.", (gptr*) &table_cache_size,
(gptr*) &table_cache_size, 0, GET_ULONG, REQUIRED_ARG, 64, 1, 512*1024L,
@@ -5962,11 +5952,7 @@
#else
have_innodb=SHOW_OPTION_NO;
#endif
-#ifdef HAVE_ISAM
- have_isam=SHOW_OPTION_YES;
-#else
have_isam=SHOW_OPTION_NO;
-#endif
#ifdef HAVE_EXAMPLE_DB
have_example_db= SHOW_OPTION_YES;
#else
@@ -6116,16 +6102,6 @@
sf_malloc_mem_limit = atoi(argument);
#endif
break;
-#ifdef EMBEDDED_LIBRARY
- case OPT_MAX_ALLOWED_PACKET:
- max_allowed_packet= atoi(argument);
- global_system_variables.max_allowed_packet= max_allowed_packet;
- break;
- case OPT_NET_BUFFER_LENGTH:
- net_buffer_length= atoi(argument);
- global_system_variables.net_buffer_length= net_buffer_length;
- break;
-#endif
#include <sslopt-case.h>
case 'V':
print_version();
@@ -6375,9 +6351,6 @@
opt_error_log= 0; // Force logs to stdout
break;
case (int) OPT_FLUSH:
-#ifdef HAVE_ISAM
- nisam_flush=1;
-#endif
myisam_flush=1;
flush_time=0; // No auto flush
break;
@@ -6484,14 +6457,6 @@
have_berkeley_db= SHOW_OPTION_DISABLED;
#endif
break;
- case OPT_ISAM:
-#ifdef HAVE_ISAM
- if (opt_isam)
- have_isam= SHOW_OPTION_YES;
- else
- have_isam= SHOW_OPTION_DISABLED;
-#endif
- break;
case OPT_NDBCLUSTER:
#ifdef HAVE_NDBCLUSTER_DB
if (opt_ndbcluster)
@@ -6713,6 +6678,9 @@
#ifndef EMBEDDED_LIBRARY
if (mysqld_chroot)
set_root(mysqld_chroot);
+#else
+ max_allowed_packet= global_system_variables.max_allowed_packet;
+ net_buffer_length= global_system_variables.net_buffer_length;
#endif
fix_paths();
--- 1.229/sql/sql_class.h Tue Apr 5 10:01:06 2005
+++ 1.230/sql/sql_class.h Wed Apr 13 07:42:59 2005
@@ -327,6 +327,7 @@
bool is_active(const char* log_file_name);
int update_log_index(LOG_INFO* linfo, bool need_update_threads);
void rotate_and_purge(uint flags);
+ bool flush_and_sync();
int purge_logs(const char *to_log, bool included,
bool need_mutex, bool need_update_threads,
ulonglong *decrease_log_space);
@@ -1264,18 +1265,18 @@
pthread_mutex_unlock(&LOCK_delete);
}
void close_active_vio();
-#endif
+#endif
void awake(THD::killed_state state_to_set);
/*
For enter_cond() / exit_cond() to work the mutex must be got before
- enter_cond() (in 4.1 an assertion will soon ensure this); this mutex is
- then released by exit_cond(). Use must be:
- lock mutex; enter_cond(); your code; exit_cond().
+ enter_cond(); this mutex is then released by exit_cond().
+ Usage must be: lock mutex; enter_cond(); your code; exit_cond().
*/
inline const char* enter_cond(pthread_cond_t *cond, pthread_mutex_t* mutex,
const char* msg)
{
const char* old_msg = proc_info;
+ safe_mutex_assert_owner(mutex);
mysys_var->current_mutex = mutex;
mysys_var->current_cond = cond;
proc_info = msg;
--- 1.420/sql/sql_parse.cc Mon Apr 11 14:31:11 2005
+++ 1.421/sql/sql_parse.cc Wed Apr 13 07:43:01 2005
@@ -1103,7 +1103,8 @@
thd->proc_info=0;
thd->set_time();
thd->init_for_queries();
- while (!net->error && net->vio != 0 && !(thd->killed ==
THD::KILL_CONNECTION))
+ while (!net->error && net->vio != 0 &&
+ !(thd->killed == THD::KILL_CONNECTION))
{
net->no_send_error= 0;
if (do_command(thd))
@@ -1912,12 +1913,13 @@
#endif
ulong uptime = (ulong) (thd->start_time - start_time);
sprintf((char*) buff,
- "Uptime: %ld Threads: %d Questions: %lu Slow queries: %lu Opens: %ld Flush
tables: %ld Open tables: %u Queries per second avg: %.3f",
+ "Uptime: %lu Threads: %d Questions: %lu Slow queries: %lu Opens: %lu Flush
tables: %lu Open tables: %u Queries per second avg: %.3f",
uptime,
(int) thread_count, (ulong) thd->query_id,
(ulong) thd->status_var.long_query_count,
thd->status_var.opened_tables, refresh_version, cached_tables(),
- uptime ? (float)thd->query_id/(float)uptime : 0);
+ (uptime ? (ulonglong2double(thd->query_id) / (double) uptime) :
+ (double) 0));
#ifdef SAFEMALLOC
if (sf_malloc_cur_memory) // Using SAFEMALLOC
sprintf(strend(buff), " Memory in use: %ldK Max memory used: %ldK",
@@ -4317,7 +4319,7 @@
case SQLCOM_XA_START:
if (thd->transaction.xa_state == XA_IDLE && thd->lex->xa_opt ==
XA_RESUME)
{
- if (! thd->transaction.xid.eq(&thd->lex->ident))
+ if (! thd->transaction.xid.eq(thd->lex->xid))
{
my_error(ER_XAER_NOTA, MYF(0));
break;
@@ -4326,7 +4328,7 @@
send_ok(thd);
break;
}
- if (thd->lex->ident.length > MAXGTRIDSIZE || thd->lex->xa_opt !=
XA_NONE)
+ if (thd->lex->xa_opt != XA_NONE)
{ // JOIN is not supported yet. TODO
my_error(ER_XAER_INVAL, MYF(0));
break;
@@ -4344,7 +4346,7 @@
}
DBUG_ASSERT(thd->transaction.xid.is_null());
thd->transaction.xa_state=XA_ACTIVE;
- thd->transaction.xid.set(&thd->lex->ident);
+ thd->transaction.xid.set(thd->lex->xid);
thd->options= ((thd->options & (ulong) ~(OPTION_STATUS_NO_TRANS_UPDATE)) |
OPTION_BEGIN);
thd->server_status|= SERVER_STATUS_IN_TRANS;
@@ -4363,7 +4365,7 @@
xa_state_names[thd->transaction.xa_state]);
break;
}
- if (!thd->transaction.xid.eq(&thd->lex->ident))
+ if (!thd->transaction.xid.eq(thd->lex->xid))
{
my_error(ER_XAER_NOTA, MYF(0));
break;
@@ -4378,7 +4380,7 @@
xa_state_names[thd->transaction.xa_state]);
break;
}
- if (!thd->transaction.xid.eq(&thd->lex->ident))
+ if (!thd->transaction.xid.eq(thd->lex->xid))
{
my_error(ER_XAER_NOTA, MYF(0));
break;
@@ -4393,9 +4395,9 @@
send_ok(thd);
break;
case SQLCOM_XA_COMMIT:
- if (!thd->transaction.xid.eq(&thd->lex->ident))
+ if (!thd->transaction.xid.eq(thd->lex->xid))
{
- if (!(res= !ha_commit_or_rollback_by_xid(&thd->lex->ident, 1)))
+ if (!(res= !ha_commit_or_rollback_by_xid(thd->lex->xid, 1)))
my_error(ER_XAER_NOTA, MYF(0));
else
send_ok(thd);
@@ -4428,9 +4430,9 @@
thd->transaction.xa_state=XA_NOTR;
break;
case SQLCOM_XA_ROLLBACK:
- if (!thd->transaction.xid.eq(&thd->lex->ident))
+ if (!thd->transaction.xid.eq(thd->lex->xid))
{
- if (!(res= !ha_commit_or_rollback_by_xid(&thd->lex->ident, 0)))
+ if (!(res= !ha_commit_or_rollback_by_xid(thd->lex->xid, 0)))
my_error(ER_XAER_NOTA, MYF(0));
else
send_ok(thd);
--- 1.310/sql/sql_select.cc Mon Apr 11 14:31:12 2005
+++ 1.311/sql/sql_select.cc Wed Apr 13 07:43:01 2005
@@ -111,6 +111,7 @@
static bool open_tmp_table(TABLE *table);
static bool create_myisam_tmp_table(TABLE *table,TMP_TABLE_PARAM *param,
ulong options);
+static Next_select_func setup_end_select_func(JOIN *join);
static int do_select(JOIN *join,List<Item> *fields,TABLE *tmp_table,
Procedure *proc);
static int sub_select_cache(JOIN *join,JOIN_TAB *join_tab,bool end_of_records);
@@ -1638,6 +1639,8 @@
{
thd->proc_info="Sending data";
DBUG_PRINT("info", ("%s", thd->proc_info));
+ result->send_fields(*curr_fields_list,
+ Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF);
error= do_select(curr_join, curr_fields_list, NULL, procedure);
thd->limit_found_rows= curr_join->send_records;
thd->examined_row_count= curr_join->examined_rows;
@@ -1776,12 +1779,8 @@
thd->server_status&= ~SERVER_STATUS_CURSOR_EXISTS;
/* Prepare JOIN for reading rows. */
-
- Next_select_func end_select= join->sort_and_group || join->procedure &&
- join->procedure->flags & PROC_GROUP ?
- end_send_group : end_send;
-
- join->join_tab[join->tables-1].next_select= end_select;
+ join->tmp_table= 0;
+ join->join_tab[join->tables-1].next_select= setup_end_select_func(join);
join->send_records= 0;
join->fetch_limit= join->unit->offset_limit_cnt;
@@ -1802,6 +1801,11 @@
*/
DBUG_ASSERT(join_tab->table->null_row == 0);
+ /*
+ There is always at least one record in the table, as otherwise we
+ wouldn't have opened the cursor. Therefore a failure is the only
+ reason read_first_record can return not 0.
+ */
DBUG_RETURN(join_tab->read_first_record(join_tab));
}
@@ -2231,6 +2235,8 @@
if (s->dependent & table->map)
s->dependent |= table->reginfo.join_tab->dependent;
}
+ if (s->dependent)
+ s->table->maybe_null= 1;
}
/* Catch illegal cross references for outer joins */
for (i= 0, s= stat ; i < table_count ; i++, s++)
@@ -2480,6 +2486,11 @@
uint level;
uint optimize;
bool eq_func;
+ /*
+ If true, the condition this struct represents will not be satisfied
+ when val IS NULL.
+ */
+ bool null_rejecting;
} KEY_FIELD;
/* Values in optimize */
@@ -2496,6 +2507,12 @@
that are internally transformed to something like:
SELECT * FROM t1 WHERE t1.key=outer_ref_field or t1.key IS NULL
+
+ KEY_FIELD::null_rejecting is processed as follows:
+ result has null_rejecting=true if it is set for both ORed references.
+ for example:
+ (t2.key = t1.field OR t2.key = t1.field) -> null_rejecting=true
+ (t2.key = t1.field OR t2.key <=> t1.field) -> null_rejecting=false
*/
static KEY_FIELD *
@@ -2529,6 +2546,8 @@
KEY_OPTIMIZE_EXISTS) |
((old->optimize | new_fields->optimize) &
KEY_OPTIMIZE_REF_OR_NULL));
+ old->null_rejecting= old->null_rejecting &&
+ new_fields->null_rejecting;
}
}
else if (old->eq_func && new_fields->eq_func &&
@@ -2540,6 +2559,8 @@
KEY_OPTIMIZE_EXISTS) |
((old->optimize | new_fields->optimize) &
KEY_OPTIMIZE_REF_OR_NULL));
+ old->null_rejecting= old->null_rejecting &&
+ new_fields->null_rejecting;
}
else if (old->eq_func && new_fields->eq_func &&
(old->val->is_null() || new_fields->val->is_null()))
@@ -2550,6 +2571,8 @@
/* Remember the NOT NULL value */
if (old->val->is_null())
old->val= new_fields->val;
+ /* The referred expression can be NULL: */
+ old->null_rejecting= false;
}
else
{
@@ -2605,7 +2628,7 @@
*/
static void
-add_key_field(KEY_FIELD **key_fields, uint and_level, COND *cond,
+add_key_field(KEY_FIELD **key_fields,uint and_level, Item_func *cond,
Field *field, bool eq_func, Item **value, uint num_values,
table_map usable_tables)
{
@@ -2707,10 +2730,17 @@
(*key_fields)->val= *value;
(*key_fields)->level= and_level;
(*key_fields)->optimize= exists_optimize;
+ /*
+ If the condition has form "tbl.keypart = othertbl.field" and
+ othertbl.field can be NULL, there will be no matches if othertbl.field
+ has NULL value.
+ */
+ (*key_fields)->null_rejecting= (cond->functype() == Item_func::EQ_FUNC)
&&
+ ((*value)->type() == Item::FIELD_ITEM) &&
+ ((Item_field*)*value)->field->maybe_null();
(*key_fields)++;
}
-
/*
Add possible keys to array of possible keys originated from a simple predicate
@@ -2735,7 +2765,7 @@
static void
add_key_equal_fields(KEY_FIELD **key_fields, uint and_level,
- COND *cond, Item_field *field_item,
+ Item_func *cond, Item_field *field_item,
bool eq_func, Item **val,
uint num_values, table_map usable_tables)
{
@@ -2763,7 +2793,7 @@
}
static void
-add_key_fields(JOIN_TAB *stat,KEY_FIELD **key_fields,uint *and_level,
+add_key_fields(KEY_FIELD **key_fields,uint *and_level,
COND *cond, table_map usable_tables)
{
if (cond->type() == Item_func::COND_ITEM)
@@ -2775,20 +2805,20 @@
{
Item *item;
while ((item=li++))
- add_key_fields(stat,key_fields,and_level,item,usable_tables);
+ add_key_fields(key_fields,and_level,item,usable_tables);
for (; org_key_fields != *key_fields ; org_key_fields++)
org_key_fields->level= *and_level;
}
else
{
(*and_level)++;
- add_key_fields(stat,key_fields,and_level,li++,usable_tables);
+ add_key_fields(key_fields,and_level,li++,usable_tables);
Item *item;
while ((item=li++))
{
KEY_FIELD *start_key_fields= *key_fields;
(*and_level)++;
- add_key_fields(stat,key_fields,and_level,item,usable_tables);
+ add_key_fields(key_fields,and_level,item,usable_tables);
*key_fields=merge_key_fields(org_key_fields,start_key_fields,
*key_fields,++(*and_level));
}
@@ -2876,7 +2906,7 @@
*/
while ((item= it++))
{
- add_key_field(key_fields, *and_level, cond, item->field,
+ add_key_field(key_fields, *and_level, cond_func, item->field,
TRUE, &const_item, 1, usable_tables);
}
}
@@ -2896,7 +2926,7 @@
{
if (!field->eq(item->field))
{
- add_key_field(key_fields, *and_level, cond, field,
+ add_key_field(key_fields, *and_level, cond_func, field,
TRUE, (Item **) &item, 1, usable_tables);
}
}
@@ -2948,6 +2978,7 @@
keyuse.keypart_map= (key_part_map) 1 << part;
keyuse.used_tables=key_field->val->used_tables();
keyuse.optimize= key_field->optimize & KEY_OPTIMIZE_REF_OR_NULL;
+ keyuse.null_rejecting= key_field->null_rejecting;
VOID(insert_dynamic(keyuse_array,(gptr) &keyuse));
}
}
@@ -3041,8 +3072,22 @@
/*
Update keyuse array with all possible keys we can use to fetch rows
- join_tab is a array in tablenr_order
- stat is a reference array in 'prefered' order.
+
+ SYNOPSIS
+ update_ref_and_keys()
+ thd
+ keyuse OUT Put here ordered array of KEYUSE structures
+ join_tab Array in tablenr_order
+ tables Number of tables in join
+ cond WHERE condition (note that the function analyzes
+ join_tab[i]->on_expr too)
+ normal_tables tables not inner w.r.t some outer join (ones for which
+ we can make ref access based the WHERE clause)
+ select_lex current SELECT
+
+ RETURN
+ 0 - OK
+ 1 - Out of memory.
*/
static bool
@@ -3067,7 +3112,7 @@
return TRUE;
if (cond)
{
- add_key_fields(join_tab,&end,&and_level,cond,normal_tables);
+ add_key_fields(&end,&and_level,cond,normal_tables);
for (; field != end ; field++)
{
add_key_part(keyuse,field);
@@ -3090,7 +3135,7 @@
*/
if (*join_tab[i].on_expr_ref)
{
- add_key_fields(join_tab,&end,&and_level,*join_tab[i].on_expr_ref,
+ add_key_fields(&end,&and_level,*join_tab[i].on_expr_ref,
join_tab[i].table->map);
}
else
@@ -3101,7 +3146,7 @@
{
NESTED_JOIN *nested_join= embedding->nested_join;
if (nested_join->join_list.head() == tab)
- add_key_fields(join_tab, &end, &and_level, embedding->on_expr,
+ add_key_fields(&end, &and_level, embedding->on_expr,
nested_join->used_tables);
}
}
@@ -4875,6 +4920,7 @@
}
j->ref.key_buff2=j->ref.key_buff+ALIGN_SIZE(length);
j->ref.key_err=1;
+ j->ref.null_rejecting= 0;
keyuse=org_keyuse;
store_key **ref_key= j->ref.key_copy;
@@ -4899,6 +4945,8 @@
uint maybe_null= test(keyinfo->key_part[i].null_bit);
j->ref.items[i]=keyuse->val; // Save for cond removal
+ if (keyuse->null_rejecting)
+ j->ref.null_rejecting |= 1 << i;
keyuse_uses_no_tables= keyuse_uses_no_tables && !keyuse->used_tables;
if (!keyuse->used_tables &&
!(join->select_options & SELECT_DESCRIBE))
@@ -5057,6 +5105,91 @@
}
+inline void add_cond_and_fix(Item **e1, Item *e2)
+{
+ if (*e1)
+ {
+ Item *res;
+ if ((res= new Item_cond_and(*e1, e2)))
+ {
+ *e1= res;
+ res->quick_fix_field();
+ }
+ }
+ else
+ *e1= e2;
+}
+
+
+/*
+ Add to join_tab->select_cond[i] "table.field IS NOT NULL" conditions we've
+ inferred from ref/eq_ref access performed.
+
+ SYNOPSIS
+ add_not_null_conds()
+ join Join to process
+
+ NOTES
+ This function is a part of "Early NULL-values filtering for ref access"
+ optimization.
+
+ Example of this optimization:
+ For query SELECT * FROM t1,t2 WHERE t2.key=t1.field
+ and plan " any-access(t1), ref(t2.key=t1.field) "
+ add "t1.field IS NOT NULL" to t1's table condition.
+ Description of the optimization:
+
+ We look through equalities choosen to perform ref/eq_ref access,
+ pick equalities that have form "tbl.part_of_key = othertbl.field"
+ (where othertbl is a non-const table and othertbl.field may be NULL)
+ and add them to conditions on correspoding tables (othertbl in this
+ example).
+
+ This optimization doesn't affect the choices that ref, range, or join
+ optimizer make. This was intentional because this was added after 4.1
+ was GA.
+
+ Implementation overview
+ 1. update_ref_and_keys() accumulates info about null-rejecting
+ predicates in in KEY_FIELD::null_rejecting
+ 1.1 add_key_part saves these to KEYUSE.
+ 2. create_ref_for_key copies them to TABLE_REF.
+ 3. add_not_null_conds adds "x IS NOT NULL" to join_tab->select_cond of
+ appropiate JOIN_TAB members.
+*/
+
+static void add_not_null_conds(JOIN *join)
+{
+ DBUG_ENTER("add_not_null_conds");
+ for (uint i=join->const_tables ; i < join->tables ; i++)
+ {
+ JOIN_TAB *tab=join->join_tab+i;
+ if ((tab->type == JT_REF || tab->type == JT_REF_OR_NULL) &&
+ !tab->table->maybe_null)
+ {
+ for (uint keypart= 0; keypart < tab->ref.key_parts; keypart++)
+ {
+ if (tab->ref.null_rejecting & (1 << keypart))
+ {
+ Item *item= tab->ref.items[keypart];
+ DBUG_ASSERT(item->type() == Item::FIELD_ITEM);
+ Item_field *not_null_item= (Item_field*)item;
+ JOIN_TAB *referred_tab= not_null_item->field->table->reginfo.join_tab;
+ Item_func_isnotnull *notnull;
+ if (!(notnull= new Item_func_isnotnull(not_null_item)))
+ DBUG_VOID_RETURN;
+
+ notnull->quick_fix_field();
+ DBUG_EXECUTE("where",print_where(notnull,
+ referred_tab->table->alias););
+ add_cond_and_fix(&referred_tab->select_cond, notnull);
+ }
+ }
+ }
+ }
+ DBUG_VOID_RETURN;
+}
+
/*
Build a predicate guarded by match variables for embedding outer joins
@@ -5194,6 +5327,7 @@
DBUG_ENTER("make_join_select");
if (select)
{
+ add_not_null_conds(join);
table_map used_tables;
if (cond) /* Because of QUICK_GROUP_MIN_MAX_SELECT */
{ /* there may be a select without a cond. */
@@ -5327,6 +5461,7 @@
tab->select_cond= sel->cond= NULL;
sel->head=tab->table;
+ DBUG_EXECUTE("where",print_where(tmp,tab->table->alias););
if (tab->quick)
{
/* Use quick key read if it's a constant and it's not used
@@ -8022,6 +8157,7 @@
*/
(*argp)->maybe_null=1;
}
+ new_field->query_id= thd->query_id;
}
}
}
@@ -8068,6 +8204,7 @@
group_null_items++;
new_field->flags|= GROUP_FLAG;
}
+ new_field->query_id= thd->query_id;
*(reg_field++) =new_field;
}
if (!--hidden_field_count)
@@ -8733,36 +8870,24 @@
}
-/****************************************************************************
- Make a join of all tables and write it on socket or to table
- Return: 0 if ok
- 1 if error is sent
- -1 if error should be sent
-****************************************************************************/
+/*
+ SYNOPSIS
+ setup_end_select_func()
+ join join to setup the function for.
-static int
-do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure)
-{
- int error= 0;
- JOIN_TAB *join_tab;
- Next_select_func end_select;
- DBUG_ENTER("do_select");
+ DESCRIPTION
+ Rows produced by a join sweep may end up in a temporary table or be sent
+ to a client. Setup the function of the nested loop join algorithm which
+ handles final fully constructed and matched records.
- join->procedure=procedure;
- /*
- Tell the client how many fields there are in a row
- */
- if (!table)
- join->result->send_fields(*fields,
- Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF);
- else
- {
- VOID(table->file->extra(HA_EXTRA_WRITE_CACHE));
- empty_record(table);
- }
- join->tmp_table= table; /* Save for easy recursion */
- join->fields= fields;
+ RETURN
+ end_select function to use. This function can't fail.
+*/
+static Next_select_func setup_end_select_func(JOIN *join)
+{
+ TABLE *table= join->tmp_table;
+ Next_select_func end_select;
/* Set up select_end */
if (table)
{
@@ -8772,8 +8897,6 @@
{
DBUG_PRINT("info",("Using end_update"));
end_select=end_update;
- if (!table->file->inited)
- table->file->ha_index_init(0);
}
else
{
@@ -8807,7 +8930,38 @@
else
end_select= end_send;
}
- join->join_tab[join->tables-1].next_select=end_select;
+ return end_select;
+}
+
+
+/****************************************************************************
+ Make a join of all tables and write it on socket or to table
+ Return: 0 if ok
+ 1 if error is sent
+ -1 if error should be sent
+****************************************************************************/
+
+static int
+do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure)
+{
+ int error= 0;
+ JOIN_TAB *join_tab;
+ DBUG_ENTER("do_select");
+
+ join->procedure=procedure;
+ join->tmp_table= table; /* Save for easy recursion */
+ join->fields= fields;
+
+ if (table)
+ {
+ VOID(table->file->extra(HA_EXTRA_WRITE_CACHE));
+ empty_record(table);
+ if (table->group && join->tmp_table_param.sum_func_count &&
+ table->s->keys && !table->file->inited)
+ table->file->ha_index_init(0);
+ }
+ /* Set up select_end */
+ join->join_tab[join->tables-1].next_select= setup_end_select_func(join);
join_tab=join->join_tab+join->const_tables;
join->send_records=0;
@@ -8819,6 +8973,7 @@
*/
if (!join->conds || join->conds->val_int())
{
+ Next_select_func end_select= join->join_tab[join->tables-1].next_select;
if (!(error=(*end_select)(join,join_tab,0)) || error == -3)
error=(*end_select)(join,join_tab,1);
}
--- 1.305/BitKeeper/etc/logging_ok Mon Apr 11 14:30:58 2005
+++ 1.306/BitKeeper/etc/logging_ok Wed Apr 13 07:42:37 2005
@@ -9,6 +9,7 @@
WAX@stripped
acurtis@stripped
acurtis@stripped
+acurtis@stripped
administrador@stripped
ahlentz@stripped
akishkin@stripped
@@ -59,6 +60,7 @@
gluh@stripped
gluh@gluh.(none)
gluh@stripped
+gluh@stripped
gordon@stripped
greg@stripped
greg@stripped
--- 1.40/ndb/include/ndbapi/NdbTransaction.hpp Wed Mar 9 12:05:07 2005
+++ 1.41/ndb/include/ndbapi/NdbTransaction.hpp Wed Apr 13 07:42:58 2005
@@ -658,6 +658,7 @@
// Release all cursor operations in connection
void releaseOps(NdbOperation*);
void releaseScanOperations(NdbIndexScanOperation*);
+ void releaseExecutedScanOperation(NdbIndexScanOperation*);
// Set the transaction identity of the transaction
void setTransactionId(Uint64 aTransactionId);
--- 1.31/ndb/include/ndbapi/NdbScanOperation.hpp Mon Apr 11 12:33:17 2005
+++ 1.32/ndb/include/ndbapi/NdbScanOperation.hpp Wed Apr 13 07:42:58 2005
@@ -37,6 +37,29 @@
public:
/**
+ * Scan flags. OR-ed together and passed as second argument to
+ * readTuples.
+ */
+ enum ScanFlag {
+ SF_TupScan = (1 << 16), // scan TUP - only LM_CommittedRead
+ SF_OrderBy = (1 << 24), // index scan in order
+ SF_Descending = (2 << 24), // index scan in descending order
+ SF_ReadRangeNo = (4 << 24) // enable @ref get_range_no
+ };
+
+ /**
+ * readTuples
+ *
+ * @param lock_mode Lock mode
+ * @param scan_flags see @ref ScanFlag
+ * @param parallel No of fragments to scan in parallel (0=max)
+ */
+ virtual
+ int readTuples(LockMode lock_mode = LM_Read,
+ Uint32 scan_flags = 0, Uint32 parallel = 0);
+
+#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
+ /**
* readTuples
*
* @param lock_mode Lock mode
@@ -44,10 +67,11 @@
* @param parallel No of fragments to scan in parallell
* @note specifying 0 for batch and parallall means max performance
*/
+#ifdef ndb_readtuples_impossible_overload
int readTuples(LockMode lock_mode = LM_Read,
Uint32 batch = 0, Uint32 parallel = 0);
+#endif
-#ifndef DOXYGEN_SHOULD_SKIP_DEPRECATED
inline int readTuples(int parallell){
return readTuples(LM_Read, 0, parallell);
}
--- 1.42/ndb/src/ndbapi/NdbTransaction.cpp Mon Apr 11 12:33:17 2005
+++ 1.43/ndb/src/ndbapi/NdbTransaction.cpp Wed Apr 13 07:42:59 2005
@@ -1521,6 +1521,7 @@
if(checkState_TransId(&commitConf->transId1)){
theCommitStatus = Committed;
theCompletionStatus = CompletedSuccess;
+ theGlobalCheckpointId = commitConf->gci;
return 0;
} else {
#ifdef NDB_NO_DROPPED_SIGNAL
--- 1.65/ndb/src/ndbapi/NdbScanOperation.cpp Mon Apr 11 12:33:17 2005
+++ 1.66/ndb/src/ndbapi/NdbScanOperation.cpp Wed Apr 13 07:42:58 2005
@@ -113,7 +113,7 @@
int
NdbScanOperation::readTuples(NdbScanOperation::LockMode lm,
- Uint32 batch,
+ Uint32 scan_flags,
Uint32 parallel)
{
m_ordered = m_descending = false;
@@ -159,7 +159,7 @@
m_keyInfo = lockExcl ? 1 : 0;
- bool range = false;
+ bool rangeScan = false;
if (m_accessTable->m_indexType == NdbDictionary::Index::OrderedIndex)
{
if (m_currentTable == m_accessTable){
@@ -172,8 +172,12 @@
// Modify operation state
theStatus = GetValue;
theOperationType = OpenRangeScanRequest;
- range = true;
+ rangeScan = true;
}
+
+ bool tupScan = (scan_flags & SF_TupScan);
+ if (tupScan && rangeScan)
+ tupScan = false;
theParallelism = parallel;
@@ -202,7 +206,8 @@
ScanTabReq::setLockMode(reqInfo, lockExcl);
ScanTabReq::setHoldLockFlag(reqInfo, lockHoldMode);
ScanTabReq::setReadCommittedFlag(reqInfo, readCommitted);
- ScanTabReq::setRangeScanFlag(reqInfo, range);
+ ScanTabReq::setRangeScanFlag(reqInfo, rangeScan);
+ ScanTabReq::setTupScanFlag(reqInfo, tupScan);
req->requestInfo = reqInfo;
Uint64 transId = theNdbCon->getTransactionId();
@@ -1191,12 +1196,14 @@
int
NdbIndexScanOperation::readTuples(LockMode lm,
- Uint32 batch,
- Uint32 parallel,
- bool order_by,
- bool order_desc,
- bool read_range_no){
- int res = NdbScanOperation::readTuples(lm, batch, 0);
+ Uint32 scan_flags,
+ Uint32 parallel)
+{
+ const bool order_by = scan_flags & SF_OrderBy;
+ const bool order_desc = scan_flags & SF_Descending;
+ const bool read_range_no = scan_flags & SF_ReadRangeNo;
+
+ int res = NdbScanOperation::readTuples(lm, scan_flags, 0);
if(!res && read_range_no)
{
m_read_range_no = 1;
--- 1.36/ndb/test/ndbapi/testOIBasic.cpp Thu Apr 7 11:13:40 2005
+++ 1.37/ndb/test/ndbapi/testOIBasic.cpp Wed Apr 13 07:42:59 2005
@@ -479,16 +479,17 @@
for (unsigned j = 0; j < size; j++) {
bytes[j] = urandom(256);
}
+ int not_used;
// check wellformed
const char* sbytes = (const char*)bytes;
- if ((*cs->cset->well_formed_len)(cs, sbytes, sbytes + size, 1) != size) {
+ if ((*cs->cset->well_formed_len)(cs, sbytes, sbytes + size, 1, ¬_used)
!= size) {
miss1++;
continue;
}
// check no proper prefix wellformed
ok = true;
for (unsigned j = 1; j < size; j++) {
- if ((*cs->cset->well_formed_len)(cs, sbytes, sbytes + j, 1) == j) {
+ if ((*cs->cset->well_formed_len)(cs, sbytes, sbytes + j, 1, ¬_used) ==
j) {
ok = false;
break;
}
@@ -673,7 +674,8 @@
CHARSET_INFO* cs = m_chs->m_cs;
const char* src = (const char*)addr;
unsigned len = m_bytelength;
- assert((*cs->cset->well_formed_len)(cs, src, src + len, 0xffff) == len);
+ int not_used;
+ assert((*cs->cset->well_formed_len)(cs, src, src + len, 0xffff,
¬_used) == len);
}
break;
case Col::Varchar:
@@ -682,8 +684,9 @@
const unsigned char* src = (const unsigned char*)addr;
const char* ssrc = (const char*)src;
unsigned len = src[0];
+ int not_used;
assert(len <= m_bytelength);
- assert((*cs->cset->well_formed_len)(cs, ssrc + 1, ssrc + 1 + len, 0xffff) ==
len);
+ assert((*cs->cset->well_formed_len)(cs, ssrc + 1, ssrc + 1 + len, 0xffff,
¬_used) == len);
}
break;
case Col::Longvarchar:
@@ -692,8 +695,9 @@
const unsigned char* src = (const unsigned char*)addr;
const char* ssrc = (const char*)src;
unsigned len = src[0] + (src[1] << 8);
+ int not_used;
assert(len <= m_bytelength);
- assert((*cs->cset->well_formed_len)(cs, ssrc + 2, ssrc + 2 + len, 0xffff) ==
len);
+ assert((*cs->cset->well_formed_len)(cs, ssrc + 2, ssrc + 2 + len, 0xffff,
¬_used) == len);
}
break;
default:
--- 1.169/sql/ha_ndbcluster.cc Mon Apr 11 14:31:11 2005
+++ 1.170/sql/ha_ndbcluster.cc Wed Apr 13 07:42:59 2005
@@ -178,7 +178,6 @@
{ 4244, HA_ERR_TABLE_EXIST, 1 },
{ 709, HA_ERR_NO_SUCH_TABLE, 0 },
- { 284, HA_ERR_NO_SUCH_TABLE, 1 },
{ 266, HA_ERR_LOCK_WAIT_TIMEOUT, 1 },
{ 274, HA_ERR_LOCK_WAIT_TIMEOUT, 1 },
@@ -193,6 +192,8 @@
{ 827, HA_ERR_RECORD_FILE_FULL, 1 },
{ 832, HA_ERR_RECORD_FILE_FULL, 1 },
+ { 284, HA_ERR_TABLE_DEF_CHANGED, 0 },
+
{ 0, 1, 0 },
{ -1, -1, 1 }
@@ -448,13 +449,31 @@
int ha_ndbcluster::ndb_err(NdbTransaction *trans)
{
int res;
- const NdbError err= trans->getNdbError();
+ NdbError err= trans->getNdbError();
DBUG_ENTER("ndb_err");
ERR_PRINT(err);
switch (err.classification) {
case NdbError::SchemaError:
invalidateDictionaryCache();
+
+ if (err.code==284)
+ {
+ /*
+ Check if the table is _really_ gone or if the table has
+ been alterend and thus changed table id
+ */
+ NDBDICT *dict= get_ndb()->getDictionary();
+ DBUG_PRINT("info", ("Check if table %s is really gone", m_tabname));
+ if (!(dict->getTable(m_tabname)))
+ {
+ err= dict->getNdbError();
+ DBUG_PRINT("info", ("Table not found, error: %d", err.code));
+ if (err.code != 709)
+ DBUG_RETURN(1);
+ }
+ DBUG_PRINT("info", ("Table exists but must have changed"));
+ }
break;
default:
break;
@@ -1919,8 +1938,12 @@
if (has_auto_increment)
{
+ THD *thd= table->in_use;
+
m_skip_auto_increment= FALSE;
update_auto_increment();
+ /* Ensure that handler is always called for auto_increment values */
+ thd->next_insert_id= 0;
m_skip_auto_increment= !auto_increment_column_changed;
}
@@ -2662,7 +2685,7 @@
m_ops_pending= 0;
}
- cursor->close(m_force_send);
+ cursor->close(m_force_send, true);
m_active_cursor= m_multi_cursor= NULL;
DBUG_RETURN(0);
}
@@ -2970,7 +2993,11 @@
DBUG_PRINT("enter", ("rows: %d", (int)rows));
m_rows_inserted= 0;
- m_rows_to_insert= rows;
+ if (rows == 0)
+ /* We don't know how many will be inserted, guess */
+ m_rows_to_insert= m_autoincrement_prefetch;
+ else
+ m_rows_to_insert= rows;
/*
Calculate how many rows that should be inserted
@@ -4080,6 +4107,10 @@
DBUG_ENTER("get_auto_increment");
DBUG_PRINT("enter", ("m_tabname: %s", m_tabname));
Ndb *ndb= get_ndb();
+
+ if (m_rows_inserted > m_rows_to_insert)
+ /* We guessed too low */
+ m_rows_to_insert+= m_autoincrement_prefetch;
cache_size=
(m_rows_to_insert - m_rows_inserted < m_autoincrement_prefetch) ?
m_rows_to_insert - m_rows_inserted
@@ -5663,7 +5694,7 @@
close_scan:
if (res == 1)
{
- m_multi_cursor->close();
+ m_multi_cursor->close(false, true);
m_active_cursor= m_multi_cursor= 0;
DBUG_MULTI_RANGE(8);
continue;
@@ -5803,6 +5834,7 @@
{
thd->cleanup();
delete thd;
+ delete ndb;
DBUG_RETURN(NULL);
}
@@ -5921,6 +5953,7 @@
thd->cleanup();
delete thd;
+ delete ndb;
DBUG_PRINT("exit", ("ndb_util_thread"));
my_thread_end();
pthread_exit(0);
| Thread |
|---|
| • bk commit into 5.0 tree (joreland:1.1792) | jonas.oreland | 13 Apr |