Below is the list of changes that have just been committed into a local
5.1 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.1973 05/08/27 08:12:24 jonas@eel.(none) +57 -0
Merge eel.(none):/home/jonas/src/mysql-5.1-push
into eel.(none):/home/jonas/src/dd-rel
storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp
1.82 05/08/27 08:12:19 jonas@eel.(none) +0 -0
merge
storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp
1.95 05/08/27 08:12:19 jonas@eel.(none) +1 -1
merge
storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp
1.91 05/08/27 08:12:18 jonas@eel.(none) +21 -27
merge
storage/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp
1.62 05/08/27 08:12:18 jonas@eel.(none) +2 -7
merge
storage/ndb/src/kernel/blocks/dbacc/Dbacc.hpp
1.27 05/08/27 08:12:18 jonas@eel.(none) +0 -0
merge
storage/ndb/src/kernel/SimBlockList.cpp
1.15 05/08/27 08:12:18 jonas@eel.(none) +1 -4
merge
storage/ndb/include/kernel/kernel_types.h
1.9 05/08/27 08:12:18 jonas@eel.(none) +7 -7
merge
storage/ndb/include/kernel/BlockNumbers.h
1.8 05/08/27 08:12:18 jonas@eel.(none) +5 -4
merge
storage/ndb/include/kernel/AttributeDescriptor.hpp
1.13 05/08/27 08:12:18 jonas@eel.(none) +1 -2
merge
sql/share/errmsg.txt
1.35 05/08/27 08:12:18 jonas@eel.(none) +0 -0
merge
sql/ha_ndbcluster.cc
1.147 05/08/27 08:12:18 jonas@eel.(none) +9 -15
merge
storage/ndb/tools/ndb_condig.cpp
1.7 05/08/27 07:49:59 jonas@eel.(none) +0 -0
Auto merged
storage/ndb/src/ndbapi/TransporterFacade.cpp
1.37 05/08/27 07:49:59 jonas@eel.(none) +0 -0
Auto merged
storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp
1.96 05/08/27 07:49:59 jonas@eel.(none) +0 -0
Auto merged
storage/ndb/src/ndbapi/DictCache.cpp
1.15 05/08/27 07:49:59 jonas@eel.(none) +0 -0
Auto merged
storage/ndb/src/mgmapi/mgmapi.cpp
1.52 05/08/27 07:49:59 jonas@eel.(none) +0 -0
Auto merged
storage/ndb/src/kernel/vm/SimulatedBlock.hpp
1.19 05/08/27 07:49:59 jonas@eel.(none) +0 -0
Auto merged
storage/ndb/src/kernel/vm/SimulatedBlock.cpp
1.16 05/08/27 07:49:59 jonas@eel.(none) +0 -0
Auto merged
storage/ndb/src/kernel/blocks/suma/Suma.cpp
1.22 05/08/27 07:49:59 jonas@eel.(none) +0 -0
Auto merged
storage/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp
1.24 05/08/27 07:49:59 jonas@eel.(none) +0 -0
Auto merged
storage/ndb/src/kernel/blocks/dbtc/Dbtc.hpp
1.32 05/08/27 07:49:58 jonas@eel.(none) +0 -0
Auto merged
storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp
1.51 05/08/27 07:49:58 jonas@eel.(none) +0 -0
Auto merged
storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp
1.34 05/08/27 07:49:58 jonas@eel.(none) +0 -0
Auto merged
storage/ndb/src/kernel/blocks/dbdict/printSchemaFile.cpp
1.14 05/08/27 07:49:58 jonas@eel.(none) +0 -0
Auto merged
storage/ndb/src/kernel/blocks/dbdict/Dbdict.hpp
1.37 05/08/27 07:49:58 jonas@eel.(none) +0 -0
Auto merged
storage/ndb/src/kernel/blocks/dbacc/DbaccInit.cpp
1.23 05/08/27 07:49:57 jonas@eel.(none) +0 -0
Auto merged
storage/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp
1.33 05/08/27 07:49:57 jonas@eel.(none) +0 -0
Auto merged
storage/ndb/src/kernel/blocks/Makefile.am
1.11 05/08/27 07:49:57 jonas@eel.(none) +0 -0
Auto merged
storage/ndb/src/kernel/Makefile.am
1.13 05/08/27 07:49:57 jonas@eel.(none) +0 -0
Auto merged
storage/ndb/src/common/debugger/BlockNames.cpp
1.6 05/08/27 07:49:57 jonas@eel.(none) +0 -0
Auto merged
storage/ndb/include/ndbapi/NdbDictionary.hpp
1.48 05/08/27 07:49:57 jonas@eel.(none) +0 -0
Auto merged
storage/ndb/include/kernel/GlobalSignalNumbers.h
1.16 05/08/27 07:49:57 jonas@eel.(none) +0 -0
Auto merged
storage/myisam/myisampack.c
1.45 05/08/27 07:49:57 jonas@eel.(none) +0 -0
Auto merged
storage/innobase/trx/trx0trx.c
1.60 05/08/27 07:49:57 jonas@eel.(none) +0 -0
Auto merged
sql/sql_yacc.yy
1.372 05/08/27 07:49:57 jonas@eel.(none) +0 -0
Auto merged
sql/sql_table.cc
1.230 05/08/27 07:49:57 jonas@eel.(none) +0 -0
Auto merged
sql/sql_select.cc
1.328 05/08/27 07:49:56 jonas@eel.(none) +0 -0
Auto merged
sql/sql_parse.cc
1.433 05/08/27 07:49:56 jonas@eel.(none) +0 -0
Auto merged
sql/sql_lex.h
1.183 05/08/27 07:49:56 jonas@eel.(none) +0 -0
Auto merged
sql/sql_delete.cc
1.152 05/08/27 07:49:56 jonas@eel.(none) +0 -0
Auto merged
sql/sql_class.h
1.235 05/08/27 07:49:56 jonas@eel.(none) +0 -0
Auto merged
sql/sql_class.cc
1.179 05/08/27 07:49:56 jonas@eel.(none) +0 -0
Auto merged
sql/sql_cache.cc
1.82 05/08/27 07:49:55 jonas@eel.(none) +0 -0
Auto merged
sql/mysqld.cc
1.455 05/08/27 07:49:55 jonas@eel.(none) +0 -0
Auto merged
sql/mysql_priv.h
1.299 05/08/27 07:49:55 jonas@eel.(none) +0 -0
Auto merged
sql/lock.cc
1.73 05/08/27 07:49:55 jonas@eel.(none) +0 -0
Auto merged
sql/lex.h
1.143 05/08/27 07:49:55 jonas@eel.(none) +0 -0
Auto merged
sql/item.cc
1.121 05/08/27 07:49:55 jonas@eel.(none) +0 -0
Auto merged
sql/handler.h
1.143 05/08/27 07:49:55 jonas@eel.(none) +0 -0
Auto merged
sql/handler.cc
1.153 05/08/27 07:49:55 jonas@eel.(none) +0 -0
Auto merged
sql/ha_ndbcluster.h
1.79 05/08/27 07:49:55 jonas@eel.(none) +0 -0
Auto merged
sql/ha_innodb.cc
1.215 05/08/27 07:49:54 jonas@eel.(none) +0 -0
Auto merged
mysql-test/t/ndb_config.test
1.5 05/08/27 07:49:54 jonas@eel.(none) +0 -0
Auto merged
mysql-test/t/ndb_alter_table.test
1.24 05/08/27 07:49:54 jonas@eel.(none) +0 -0
Auto merged
mysql-test/r/ndb_alter_table.result
1.28 05/08/27 07:49:54 jonas@eel.(none) +0 -0
Auto merged
configure.in
1.270 05/08/27 07:49:54 jonas@eel.(none) +1 -3
Auto merged
BitKeeper/etc/ignore
1.210 05/08/27 07:49:38 jonas@eel.(none) +1 -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: jonas
# Host: eel.(none)
# Root: /home/jonas/src/dd-rel/RESYNC
--- 1.269/configure.in 2005-08-09 09:49:29 +02:00
+++ 1.270/configure.in 2005-08-27 07:49:54 +02:00
@@ -1,13 +1,13 @@
dnl -*- ksh -*-
dnl Process this file with autoconf to produce a configure script.
-AC_PREREQ(2.57)dnl Minimum Autoconf version required.
+AC_PREREQ(2.52)dnl Minimum Autoconf version required.
AC_INIT(sql/mysqld.cc)
AC_CANONICAL_SYSTEM
# The Docs Makefile.am parses this line!
# Don't forget to also update the NDB lines below.
-AM_INIT_AUTOMAKE(mysql, 5.1.1-alpha)
+AM_INIT_AUTOMAKE(mysql, 5.1.2-alpha)
AM_CONFIG_HEADER(config.h)
PROTOCOL_VERSION=10
@@ -18,7 +18,7 @@
# ndb version
NDB_VERSION_MAJOR=5
NDB_VERSION_MINOR=1
-NDB_VERSION_BUILD=1
+NDB_VERSION_BUILD=2
NDB_VERSION_STATUS="alpha"
# Set all version vars based on $VERSION. How do we do this more elegant ?
@@ -131,6 +131,7 @@
# Hack for OS X/Darwin and Metrowerks CodeWarrior
AC_ARG_WITH(darwin-mwcc,
[ --with-darwin-mwcc Use Metrowerks CodeWarrior wrappers on OS X/Darwin],[
+ if [ "with_darwin_mwcc" = yes ] ; then
builddir=`pwd`
ccwrapper="$builddir/support-files/MacOSX/mwcc-wrapper"
arwrapper="$builddir/support-files/MacOSX/mwar-wrapper"
@@ -142,7 +143,7 @@
export CC CXX LD AR RANLIB
AC_SUBST(AR)
AC_SUBST(RANLIB)
- with_darwin_mwcc=yes
+ fi
])
AM_CONDITIONAL(DARWIN_MWCC, test x$with_darwin_mwcc = xyes)
@@ -2446,7 +2447,7 @@
dnl This probably should be cleaned up more - for now the threaded
dnl client is just using plain-old libs.
-sql_client_dirs="libmysql strings regex client"
+sql_client_dirs="strings regex mysys sql/share libmysql client"
linked_client_targets="linked_libmysql_sources"
if test "$THREAD_SAFE_CLIENT" != "no"
@@ -2484,7 +2485,7 @@
AC_DEFINE([THREAD], [1],
[Define if you want to have threaded code. This may be undef on client code])
# Avoid _PROGRAMS names
- THREAD_LOBJECTS="thr_alarm.o thr_lock.o thr_mutex.o thr_rwlock.o my_pthread.o my_thr_init.o"
+ THREAD_LOBJECTS="thr_alarm.o thr_lock.o thr_mutex.o thr_rwlock.o my_pthread.o my_thr_init.o mf_keycache.o"
AC_SUBST(THREAD_LOBJECTS)
server_scripts="mysqld_safe mysql_install_db"
sql_server_dirs="strings mysys dbug extra regex"
@@ -2597,7 +2598,6 @@
# END of configuration for optional table handlers
#
sql_server_dirs="$sql_server_dirs storage/myisam storage/myisammrg storage/heap vio sql"
-
fi
# IMPORTANT - do not modify LIBS past this line - this hack is the only way
@@ -2757,7 +2757,6 @@
storage/ndb/src/kernel/blocks/backup/Makefile dnl
storage/ndb/src/kernel/blocks/dbutil/Makefile dnl
storage/ndb/src/kernel/blocks/suma/Makefile dnl
- storage/ndb/src/kernel/blocks/grep/Makefile dnl
storage/ndb/src/kernel/blocks/dbtux/Makefile dnl
storage/ndb/src/kernel/vm/Makefile dnl
storage/ndb/src/mgmapi/Makefile dnl
@@ -2771,11 +2770,9 @@
storage/ndb/test/ndbapi/Makefile dnl
storage/ndb/test/ndbapi/bank/Makefile dnl
storage/ndb/test/tools/Makefile dnl
- storage/ndb/test/run-test/Makefile dnl
- storage/ndb/include/ndb_version.h dnl
- storage/ndb/include/ndb_global.h dnl
+ storage/ndb/test/run-test/Makefile mysql-test/ndb/Makefile dnl
+ storage/ndb/include/ndb_version.h storage/ndb/include/ndb_global.h dnl
storage/ndb/include/ndb_types.h dnl
- mysql-test/ndb/Makefile dnl
)
fi
--- 1.44/storage/myisam/myisampack.c 2005-07-21 15:33:43 +02:00
+++ 1.45/storage/myisam/myisampack.c 2005-08-27 07:49:57 +02:00
@@ -695,14 +695,22 @@
else
error=my_rename(new_name,org_name,MYF(MY_WME));
if (!error)
+ {
VOID(my_copystat(temp_name,org_name,MYF(MY_COPYTIME)));
+ if (tmp_dir[0])
+ VOID(my_delete(new_name,MYF(MY_WME)));
+ }
}
}
else
{
if (tmp_dir[0])
+ {
error=my_copy(new_name,org_name,
MYF(MY_WME | MY_HOLD_ORIGINAL_MODES | MY_COPYTIME));
+ if (!error)
+ VOID(my_delete(new_name,MYF(MY_WME)));
+ }
else
error=my_redel(org_name,new_name,MYF(MY_WME | MY_COPYTIME));
}
--- 1.152/sql/handler.cc 2005-08-09 09:49:30 +02:00
+++ 1.153/sql/handler.cc 2005-08-27 07:49:55 +02:00
@@ -609,8 +609,8 @@
trans->ht[trans->nht++]=ht_arg;
DBUG_ASSERT(*ht == ht_arg);
trans->no_2pc|=(ht_arg->prepare==0);
- if (thd->transaction.xid.is_null())
- thd->transaction.xid.set(thd->query_id);
+ if (thd->transaction.xid_state.xid.is_null())
+ thd->transaction.xid_state.xid.set(thd->query_id);
DBUG_VOID_RETURN;
}
@@ -657,7 +657,7 @@
THD_TRANS *trans= all ? &thd->transaction.all : &thd->transaction.stmt;
bool is_real_trans= all || thd->transaction.all.nht == 0;
handlerton **ht= trans->ht;
- my_xid xid= thd->transaction.xid.get_my_xid();
+ my_xid xid= thd->transaction.xid_state.xid.get_my_xid();
DBUG_ENTER("ha_commit_trans");
if (thd->in_sub_stmt)
@@ -757,7 +757,7 @@
trans->nht=0;
trans->no_2pc=0;
if (is_real_trans)
- thd->transaction.xid.null();
+ thd->transaction.xid_state.xid.null();
if (all)
{
#ifdef HAVE_QUERY_CACHE
@@ -813,7 +813,7 @@
trans->nht=0;
trans->no_2pc=0;
if (is_real_trans)
- thd->transaction.xid.null();
+ thd->transaction.xid_state.xid.null();
if (all)
{
thd->variables.tx_isolation=thd->session_tx_isolation;
@@ -1007,6 +1007,7 @@
char buf[XIDDATASIZE*4+6]; // see xid_to_str
sql_print_information("ignore xid %s", xid_to_str(buf, list+i));
#endif
+ xid_cache_insert(list+i, XA_PREPARED);
found_foreign_xids++;
continue;
}
@@ -1070,10 +1071,8 @@
{
List<Item> field_list;
Protocol *protocol= thd->protocol;
- handlerton **ht= handlertons, **end_ht=ht+total_ha;
- bool error=TRUE;
- int len, got;
- XID *list=0;
+ int i=0;
+ XID_STATE *xs;
DBUG_ENTER("mysql_xa_recover");
field_list.push_back(new Item_int("formatID",0,11));
@@ -1083,48 +1082,30 @@
if (protocol->send_fields(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
- DBUG_RETURN(TRUE);
-
- for (len= MAX_XID_LIST_SIZE ; list==0 && len > MIN_XID_LIST_SIZE; len/=2)
- {
- list=(XID *)my_malloc(len*sizeof(XID), MYF(0));
- }
- if (!list)
- {
- my_error(ER_OUTOFMEMORY, MYF(0), len);
DBUG_RETURN(1);
- }
- for ( ; ht < end_ht ; ht++)
+ pthread_mutex_lock(&LOCK_xid_cache);
+ while ((xs= (XID_STATE*)hash_element(&xid_cache, i++)))
{
- if (!(*ht)->recover)
- continue;
- while ((got=(*(*ht)->recover)(list, len)) > 0 )
+ if (xs->xa_state==XA_PREPARED)
{
- XID *xid, *end;
- for (xid=list, end=list+got; xid < end; xid++)
+ protocol->prepare_for_resend();
+ protocol->store_longlong((longlong)xs->xid.formatID, FALSE);
+ protocol->store_longlong((longlong)xs->xid.gtrid_length, FALSE);
+ protocol->store_longlong((longlong)xs->xid.bqual_length, FALSE);
+ protocol->store(xs->xid.data, xs->xid.gtrid_length+xs->xid.bqual_length,
+ &my_charset_bin);
+ if (protocol->write())
{
- if (xid->get_my_xid())
- continue; // skip "our" xids
- protocol->prepare_for_resend();
- protocol->store_longlong((longlong)xid->formatID, FALSE);
- protocol->store_longlong((longlong)xid->gtrid_length, FALSE);
- protocol->store_longlong((longlong)xid->bqual_length, FALSE);
- protocol->store(xid->data, xid->gtrid_length+xid->bqual_length,
- &my_charset_bin);
- if (protocol->write())
- goto err;
+ pthread_mutex_unlock(&LOCK_xid_cache);
+ DBUG_RETURN(1);
}
- if (got < len)
- break;
}
}
- error=FALSE;
+ pthread_mutex_unlock(&LOCK_xid_cache);
send_eof(thd);
-err:
- my_free((gptr)list, MYF(0));
- DBUG_RETURN(error);
+ DBUG_RETURN(0);
}
/*
@@ -1827,7 +1808,7 @@
}
case HA_ERR_NULL_IN_SPATIAL:
textno= ER_UNKNOWN_ERROR;
- DBUG_VOID_RETURN;
+ break;
case HA_ERR_FOUND_DUPP_UNIQUE:
textno=ER_DUP_UNIQUE;
break;
@@ -1850,8 +1831,8 @@
textno=ER_CRASHED_ON_REPAIR;
break;
case HA_ERR_OUT_OF_MEM:
- my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), errflag);
- DBUG_VOID_RETURN;
+ textno=ER_OUT_OF_RESOURCES;
+ break;
case HA_ERR_WRONG_COMMAND:
textno=ER_ILLEGAL_HA;
break;
@@ -1862,10 +1843,8 @@
textno=ER_UNSUPPORTED_EXTENSION;
break;
case HA_ERR_RECORD_FILE_FULL:
- textno=ER_RECORD_FILE_FULL;
- break;
case HA_ERR_INDEX_FILE_FULL:
- textno= errno;
+ textno=ER_RECORD_FILE_FULL;
break;
case HA_ERR_LOCK_WAIT_TIMEOUT:
textno=ER_LOCK_WAIT_TIMEOUT;
--- 1.142/sql/handler.h 2005-07-25 10:30:26 +02:00
+++ 1.143/sql/handler.h 2005-08-27 07:49:55 +02:00
@@ -103,6 +103,10 @@
#define HA_ONLY_WHOLE_INDEX 16 /* Can't use part key searches */
#define HA_KEYREAD_ONLY 64 /* Support HA_EXTRA_KEYREAD */
+/* bits in alter_table_flags */
+#define HA_ONLINE_ADD_EMPTY_PARTITION 1
+#define HA_ONLINE_DROP_PARTITION 2
+
/* operations for disable/enable indexes */
#define HA_KEY_SWITCH_NONUNIQ 0
#define HA_KEY_SWITCH_ALL 1
@@ -236,11 +240,11 @@
char data[XIDDATASIZE]; // not \0-terminated !
bool eq(struct xid_t *xid)
- { return !memcmp(this, xid, sizeof(long)*3+gtrid_length+bqual_length); }
+ { return !memcmp(this, xid, length()); }
bool eq(long g, long b, const char *d)
{ return g == gtrid_length && b == bqual_length && !memcmp(d, data, g+b); }
void set(struct xid_t *xid)
- { memcpy(this, xid, sizeof(long)*3+xid->gtrid_length+xid->bqual_length); }
+ { memcpy(this, xid, xid->length()); }
void set(long f, const char *g, long gl, const char *b, long bl)
{
formatID= f;
@@ -279,6 +283,11 @@
!memcmp(data, MYSQL_XID_PREFIX, MYSQL_XID_PREFIX_LEN) ?
quick_get_my_xid() : 0;
}
+ uint length()
+ {
+ return sizeof(formatID)+sizeof(gtrid_length)+sizeof(bqual_length)+
+ gtrid_length+bqual_length;
+ }
};
typedef struct xid_t XID;
@@ -399,6 +408,16 @@
LIST_PARTITION
};
+enum partition_state {
+ PART_NORMAL= 0,
+ PART_IS_DROPPED= 1,
+ PART_TO_BE_DROPPED= 2,
+ PART_DROPPING= 3,
+ PART_IS_ADDED= 4,
+ PART_ADDING= 5,
+ PART_ADDED= 6
+};
+
#define UNDEF_NODEGROUP 65535
class Item;
@@ -415,13 +434,15 @@
char* data_file_name;
char* index_file_name;
enum db_type engine_type;
+ enum partition_state part_state;
uint16 nodegroup_id;
partition_element()
: part_max_rows(0), part_min_rows(0), partition_name(NULL),
tablespace_name(NULL), range_value(0), part_comment(NULL),
data_file_name(NULL), index_file_name(NULL),
- engine_type(DB_TYPE_UNKNOWN), nodegroup_id(UNDEF_NODEGROUP)
+ engine_type(DB_TYPE_UNKNOWN),part_state(PART_NORMAL),
+ nodegroup_id(UNDEF_NODEGROUP)
{
subpartitions.empty();
list_val_list.empty();
@@ -447,6 +468,7 @@
* Here comes a set of definitions needed for partitioned table handlers.
*/
List<partition_element> partitions;
+ List<partition_element> temp_partitions;
List<char> part_field_list;
List<char> subpart_field_list;
@@ -492,7 +514,6 @@
uint part_func_len;
uint subpart_func_len;
- uint no_full_parts;
uint no_parts;
uint no_subparts;
uint count_curr_parts;
@@ -529,7 +550,7 @@
part_result_type(INT_RESULT),
part_type(NOT_A_PARTITION), subpart_type(NOT_A_PARTITION),
part_info_len(0), part_func_len(0), subpart_func_len(0),
- no_full_parts(0), no_parts(0), no_subparts(0),
+ no_parts(0), no_subparts(0),
count_curr_parts(0), count_curr_subparts(0), part_error_code(0),
no_list_values(0), no_part_fields(0), no_subpart_fields(0),
no_full_part_fields(0), linear_hash_mask(0),
@@ -543,6 +564,7 @@
all_fields_in_SPF.clear_all();
some_fields_in_PF.clear_all();
partitions.empty();
+ temp_partitions.empty();
part_field_list.empty();
subpart_field_list.empty();
}
@@ -635,6 +657,13 @@
#ifdef HAVE_PARTITION_DB
+bool is_partition_in_list(char *part_name, List<char> list_part_names);
+bool is_partitions_in_table(partition_info *new_part_info,
+ partition_info *old_part_info);
+bool set_up_defaults_for_partitioning(partition_info *part_info,
+ handler *file,
+ ulonglong max_rows,
+ uint start_no);
handler *get_ha_partition(partition_info *part_info);
int get_parts_for_update(const byte *old_data, byte *new_data,
const byte *rec0, partition_info *part_info,
@@ -1208,6 +1237,20 @@
virtual char *update_table_comment(const char * comment)
{ return (char*) comment;}
virtual void append_create_info(String *packet) {}
+ /*
+ SYNOPSIS
+ is_fk_defined_on_table_or_index()
+ index Index to check if foreign key uses it
+ RETURN VALUE
+ TRUE Foreign key defined on table or index
+ FALSE No foreign key defined
+ DESCRIPTION
+ If index == MAX_KEY then a check for table is made and if index <
+ MAX_KEY then a check is made if the table has foreign keys and if
+ a foreign key uses this index (and thus the index cannot be dropped).
+ */
+ virtual bool is_fk_defined_on_table_or_index(uint index)
+ { return FALSE; }
virtual char* get_foreign_key_create_info()
{ return(NULL);} /* gets foreign key create string from InnoDB */
/* used in ALTER TABLE; 1 if changing storage engine is allowed */
@@ -1223,6 +1266,7 @@
virtual const char *table_type() const =0;
virtual const char **bas_ext() const =0;
virtual ulong table_flags(void) const =0;
+ virtual ulong alter_table_flags(void) const { return 0; }
#ifdef HAVE_PARTITION_DB
virtual ulong partition_flags(void) const { return 0;}
virtual int get_default_no_partitions(ulonglong max_rows) { return 1;}
@@ -1268,6 +1312,19 @@
virtual int create(const char *name, TABLE *form, HA_CREATE_INFO *info)=0;
virtual int create_handler_files(const char *name) { return FALSE;}
+ /*
+ SYNOPSIS
+ drop_partitions()
+ path Complete path of db and table name
+ RETURN VALUE
+ TRUE Failure
+ FALSE Success
+ DESCRIPTION
+ Drop a partition, during this operation no other activity is ongoing
+ in this server on the table.
+ */
+ virtual int drop_partitions(const char *path)
+ { return HA_ERR_WRONG_COMMAND; }
/* lock_count() can be more than one if the table is a MERGE */
virtual uint lock_count(void) const { return 1; }
virtual THR_LOCK_DATA **store_lock(THD *thd,
--- 1.120/sql/item.cc 2005-08-09 09:49:30 +02:00
+++ 1.121/sql/item.cc 2005-08-27 07:49:55 +02:00
@@ -1016,14 +1016,18 @@
; // Do nothing
}
else if ((flags & MY_COLL_ALLOW_SUPERSET_CONV) &&
- derivation < dt.derivation &&
- collation->state & MY_CS_UNICODE)
+ collation->state & MY_CS_UNICODE &&
+ (derivation < dt.derivation ||
+ (derivation == dt.derivation &&
+ !(dt.collation->state & MY_CS_UNICODE))))
{
// Do nothing
}
else if ((flags & MY_COLL_ALLOW_SUPERSET_CONV) &&
- dt.derivation < derivation &&
- dt.collation->state & MY_CS_UNICODE)
+ dt.collation->state & MY_CS_UNICODE &&
+ (dt.derivation < derivation ||
+ (dt.derivation == derivation &&
+ !(collation->state & MY_CS_UNICODE))))
{
set(dt);
}
@@ -2134,7 +2138,7 @@
CHARSET_INFO *tocs= thd->variables.collation_connection;
uint32 dummy_offset;
- value.cs_info.character_set_client= fromcs;
+ value.cs_info.character_set_of_placeholder= fromcs;
/*
Setup source and destination character sets so that they
are different only if conversion is necessary: this will
@@ -2452,10 +2456,17 @@
buf= str->c_ptr_quick();
ptr= buf;
- *ptr++= '\'';
- ptr+= escape_string_for_mysql(str_value.charset(), ptr, 0,
- str_value.ptr(), str_value.length());
- *ptr++= '\'';
+ if (value.cs_info.character_set_client->escape_with_backslash_is_dangerous)
+ {
+ ptr= str_to_hex(ptr, str_value.ptr(), str_value.length());
+ }
+ else
+ {
+ *ptr++= '\'';
+ ptr+= escape_string_for_mysql(str_value.charset(), ptr, 0,
+ str_value.ptr(), str_value.length());
+ *ptr++='\'';
+ }
str->length((uint32) (ptr - buf));
break;
}
@@ -2485,10 +2496,10 @@
here only if conversion is really necessary.
*/
if (value.cs_info.final_character_set_of_str_value !=
- value.cs_info.character_set_client)
+ value.cs_info.character_set_of_placeholder)
{
rc= thd->convert_string(&str_value,
- value.cs_info.character_set_client,
+ value.cs_info.character_set_of_placeholder,
value.cs_info.final_character_set_of_str_value);
}
else
@@ -3067,7 +3078,9 @@
expression to 'reference', i.e. it substitute that expression instead
of this Item_field
*/
- if ((from_field= find_field_in_tables(thd, this, context->table_list,
+ if ((from_field= find_field_in_tables(thd, this,
+ context->first_name_resolution_table,
+ context->last_name_resolution_table,
reference,
IGNORE_EXCEPT_NON_UNIQUE,
!any_privileges &&
@@ -3076,13 +3089,13 @@
not_found_field)
{
/*
- If there is an outer contexts (outer selects, but current select is
+ If there are outer contexts (outer selects, but current select is
not derived table or view) try to resolve this reference in the
outer contexts.
We treat each subselect as a separate namespace, so that different
- subselects may contain columns with the same names. The subselects are
- searched starting from the innermost.
+ subselects may contain columns with the same names. The subselects
+ are searched starting from the innermost.
*/
Name_resolution_context *last_checked_context= context;
Item **ref= (Item **) not_found_item;
@@ -3111,7 +3124,10 @@
(!select->with_sum_func &&
select->group_list.elements == 0)) &&
(from_field= find_field_in_tables(thd, this,
- outer_context->table_list,
+ outer_context->
+ first_name_resolution_table,
+ outer_context->
+ last_name_resolution_table,
reference,
IGNORE_EXCEPT_NON_UNIQUE,
outer_context->
@@ -3186,7 +3202,9 @@
else
{
/* Call find_field_in_tables only to report the error */
- find_field_in_tables(thd, this, context->table_list,
+ find_field_in_tables(thd, this,
+ context->first_name_resolution_table,
+ context->last_name_resolution_table,
reference, REPORT_ALL_ERRORS,
!any_privileges &&
context->check_privileges, TRUE);
@@ -4359,7 +4377,10 @@
expression instead of this Item_ref
*/
from_field= find_field_in_tables(thd, this,
- outer_context->table_list,
+ outer_context->
+ first_name_resolution_table,
+ outer_context->
+ last_name_resolution_table,
reference,
IGNORE_EXCEPT_NON_UNIQUE,
outer_context->check_privileges,
@@ -4978,9 +4999,8 @@
Try to find field by its name and if it will be found
set field_idx properly.
*/
- (void)find_field_in_real_table(thd, table, field_name,
- (uint) strlen(field_name),
- 0, 0, &field_idx);
+ (void)find_field_in_table(thd, table, field_name, (uint) strlen(field_name),
+ 0, 0, &field_idx);
thd->set_query_id= save_set_query_id;
triggers= table->triggers;
}
--- 1.142/sql/lex.h 2005-07-21 16:15:15 +02:00
+++ 1.143/sql/lex.h 2005-08-27 07:49:55 +02:00
@@ -112,6 +112,7 @@
{ "CIPHER", SYM(CIPHER_SYM)},
{ "CLIENT", SYM(CLIENT_SYM)},
{ "CLOSE", SYM(CLOSE_SYM)},
+ { "COALESCE", SYM(COALESCE)},
{ "COLLATE", SYM(COLLATE_SYM)},
{ "COLLATION", SYM(COLLATION_SYM)},
{ "COLUMN", SYM(COLUMN_SYM)},
@@ -422,6 +423,7 @@
{ "RELEASE", SYM(RELEASE_SYM)},
{ "RELOAD", SYM(RELOAD)},
{ "RENAME", SYM(RENAME)},
+ { "REORGANISE", SYM(REORGANISE_SYM)},
{ "REPAIR", SYM(REPAIR)},
{ "REPEATABLE", SYM(REPEATABLE_SYM)},
{ "REPLACE", SYM(REPLACE)},
@@ -606,7 +608,6 @@
{ "CENTROID", F_SYM(FUNC_ARG1),0,CREATE_FUNC_GEOM(create_func_centroid)},
{ "CHAR_LENGTH", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_char_length)},
{ "CHARACTER_LENGTH", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_char_length)},
- { "COALESCE", SYM(COALESCE)},
{ "COERCIBILITY", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_coercibility)},
{ "COMPRESS", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_compress)},
{ "CONCAT", SYM(CONCAT)},
@@ -764,6 +765,7 @@
{ "SIN", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_sin)},
{ "SHA", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_sha)},
{ "SHA1", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_sha)},
+ { "SLEEP", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_sleep)},
{ "SOUNDEX", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_soundex)},
{ "SPACE", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_space)},
{ "SQRT", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_sqrt)},
@@ -780,7 +782,7 @@
{ "SUBSTRING_INDEX", SYM(SUBSTRING_INDEX)},
{ "SUBTIME", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_subtime)},
{ "SUM", SYM(SUM_SYM)},
- { "SYSDATE", SYM(NOW_SYM)},
+ { "SYSDATE", SYM(SYSDATE)},
{ "SYSTEM_USER", SYM(USER)},
{ "TAN", F_SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_tan)},
{ "TIME_FORMAT", F_SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_time_format)},
--- 1.72/sql/lock.cc 2005-08-09 09:49:30 +02:00
+++ 1.73/sql/lock.cc 2005-08-27 07:49:55 +02:00
@@ -848,10 +848,6 @@
So in this exceptional case the COMMIT should not be blocked by the FLUSH
TABLES WITH READ LOCK.
- TODO in MySQL 5.x: make_global_read_lock_block_commit() should be
- killable. Normally CPU does not spend a long time in this function (COMMITs
- are quite fast), but it would still be nice.
-
****************************************************************************/
volatile uint global_read_lock=0;
@@ -1002,7 +998,7 @@
pthread_cond_wait(&COND_refresh, &LOCK_global_read_lock);
DBUG_EXECUTE_IF("make_global_read_lock_block_commit_loop",
protect_against_global_read_lock--;);
- if (error= thd->killed)
+ if ((error= test(thd->killed)))
global_read_lock_blocks_commit--; // undo what we did
else
thd->global_read_lock= MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT;
--- 1.298/sql/mysql_priv.h 2005-08-09 09:49:30 +02:00
+++ 1.299/sql/mysql_priv.h 2005-08-27 07:49:55 +02:00
@@ -284,6 +284,11 @@
#define OPTION_SETUP_TABLES_DONE (1L << 30) // intern
/* If not set then the thread will ignore all warnings with level notes. */
#define OPTION_SQL_NOTES (1L << 31) // THD, user
+/*
+ Force the used temporary table to be a MyISAM table (because we will use
+ fulltext functions when reading from it.
+*/
+#define TMP_TABLE_FORCE_MYISAM (LL(1) << 32)
/*
Maximum length of time zone name that we support
@@ -494,8 +499,7 @@
void free_items(Item *item);
void cleanup_items(Item *item);
class THD;
-void close_thread_tables(THD *thd, bool locked=0, bool skip_derived=0,
- TABLE *stopper= 0);
+void close_thread_tables(THD *thd, bool locked=0, bool skip_derived=0);
bool check_one_table_access(THD *thd, ulong privilege,
TABLE_LIST *tables);
bool check_routine_access(THD *thd,ulong want_access,char *db,char *name,
@@ -588,7 +592,7 @@
const char *table_name);
void close_cached_table(THD *thd, TABLE *table);
bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list);
-bool mysql_change_db(THD *thd,const char *name);
+bool mysql_change_db(THD *thd,const char *name,bool no_access_check);
void mysql_parse(THD *thd,char *inBuf,uint length);
bool mysql_test_parse_for_slave(THD *thd,char *inBuf,uint length);
bool is_update_query(enum enum_sql_command command);
@@ -628,6 +632,10 @@
bool check_global_access(THD *thd, ulong want_access);
/*
+ Support routine for SQL parser on partitioning syntax
+*/
+my_bool is_partition_management(LEX *lex);
+/*
General routine to change field->ptr of a NULL-terminated array of Field
objects. Useful when needed to call val_int, val_str or similar and the
field data is not in table->record[0] but in some other structure.
@@ -740,7 +748,7 @@
enum enum_duplicates handle_duplicates, bool ignore);
bool mysql_multi_update(THD *thd, TABLE_LIST *table_list,
List<Item> *fields, List<Item> *values,
- COND *conds, ulong options,
+ COND *conds, ulonglong options,
enum enum_duplicates handle_duplicates, bool ignore,
SELECT_LEX_UNIT *unit, SELECT_LEX *select_lex);
bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, TABLE *table,
@@ -756,7 +764,7 @@
TABLE_LIST *table_list);
bool mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds);
bool mysql_delete(THD *thd, TABLE_LIST *table, COND *conds, SQL_LIST *order,
- ha_rows rows, ulong options);
+ ha_rows rows, ulonglong options);
bool mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok);
bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create);
TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type update);
@@ -781,23 +789,25 @@
enum find_item_error_report_type {REPORT_ALL_ERRORS, REPORT_EXCEPT_NOT_FOUND,
IGNORE_ERRORS, REPORT_EXCEPT_NON_UNIQUE,
IGNORE_EXCEPT_NON_UNIQUE};
-Field *find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
- Item **ref,
- find_item_error_report_type report_error,
- bool check_privileges,
- bool register_tree_change);
Field *
-find_field_in_table(THD *thd, TABLE_LIST *table_list,
- const char *name, const char *item_name,
- uint length, Item **ref,
- bool check_grants_table, bool check_grants_view,
- bool allow_rowid,
- uint *cached_field_index_ptr,
- bool register_tree_change);
+find_field_in_tables(THD *thd, Item_ident *item,
+ TABLE_LIST *first_table, TABLE_LIST *last_table,
+ Item **ref, find_item_error_report_type report_error,
+ bool check_privileges, bool register_tree_change);
Field *
-find_field_in_real_table(THD *thd, TABLE *table, const char *name,
- uint length, bool check_grants, bool allow_rowid,
- uint *cached_field_index_ptr);
+find_field_in_table_ref(THD *thd, TABLE_LIST *table_list,
+ const char *name, const char *item_name,
+ const char *table_name, const char *db_name,
+ uint length, Item **ref,
+ bool check_grants_table, bool check_grants_view,
+ bool allow_rowid,
+ uint *cached_field_index_ptr,
+ bool register_tree_change, TABLE_LIST **actual_table);
+Field *
+find_field_in_table(THD *thd, TABLE *table, const char *name,
+ uint length, bool check_grants, bool allow_rowid,
+ uint *cached_field_index_ptr);
+
Field *
find_field_in_table_sef(TABLE *table, const char *name);
@@ -907,8 +917,10 @@
uint uint_geom_type);
void store_position_for_column(const char *name);
bool add_to_list(THD *thd, SQL_LIST &list,Item *group,bool asc);
+Name_resolution_context *make_join_on_context(THD *thd, TABLE_LIST *left_op,
+ TABLE_LIST *right_op);
void add_join_on(TABLE_LIST *b,Item *expr);
-void add_join_natural(TABLE_LIST *a,TABLE_LIST *b);
+void add_join_natural(TABLE_LIST *a,TABLE_LIST *b,List<String> *using_fields);
bool add_proc_to_list(THD *thd, Item *item);
TABLE *unlink_open_table(THD *thd,TABLE *list,TABLE *find);
@@ -925,8 +937,8 @@
const char *db_name, const char *table_name,
List_iterator<Item> *it, bool any_privileges);
bool setup_tables(THD *thd, Name_resolution_context *context,
- TABLE_LIST *tables, Item **conds,
- TABLE_LIST **leaves, bool select_insert);
+ List<TABLE_LIST> *from_clause, TABLE_LIST *tables,
+ Item **conds, TABLE_LIST **leaves, bool select_insert);
int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
List<Item> *sum_func_list, uint wild_num);
bool setup_fields(THD *thd, Item** ref_pointer_array,
@@ -949,10 +961,10 @@
int setup_ftfuncs(SELECT_LEX* select);
int init_ftfuncs(THD *thd, SELECT_LEX* select, bool no_order);
void wait_for_refresh(THD *thd);
-int open_tables(THD *thd, TABLE_LIST **tables, uint *counter);
+int open_tables(THD *thd, TABLE_LIST **tables, uint *counter, uint flags);
int simple_open_n_lock_tables(THD *thd,TABLE_LIST *tables);
bool open_and_lock_tables(THD *thd,TABLE_LIST *tables);
-bool open_normal_and_derived_tables(THD *thd, TABLE_LIST *tables);
+bool open_normal_and_derived_tables(THD *thd, TABLE_LIST *tables, uint flags);
int lock_tables(THD *thd, TABLE_LIST *tables, uint counter);
TABLE *open_temporary_table(THD *thd, const char *path, const char *db,
const char *table_name, bool link_in_list);
@@ -997,7 +1009,7 @@
bool ignore_errors,
Table_triggers_list *triggers,
enum trg_event_type event);
-OPEN_TABLE_LIST *list_open_tables(THD *thd, const char *wild);
+OPEN_TABLE_LIST *list_open_tables(THD *thd, const char *db, const char *wild);
inline TABLE_LIST *find_table_in_global_list(TABLE_LIST *table,
const char *db_name,
@@ -1125,6 +1137,7 @@
extern double log_10[32];
extern ulonglong log_10_int[20];
extern ulonglong keybuff_size;
+extern ulonglong thd_startup_options;
extern ulong refresh_version,flush_version, thread_id;
extern ulong binlog_cache_use, binlog_cache_disk_use;
extern ulong aborted_threads,aborted_connects;
@@ -1134,7 +1147,7 @@
extern ulong delayed_rows_in_use,delayed_insert_errors;
extern ulong slave_open_temp_tables;
extern ulong query_cache_size, query_cache_min_res_unit;
-extern ulong thd_startup_options, slow_launch_threads, slow_launch_time;
+extern ulong slow_launch_threads, slow_launch_time;
extern ulong table_cache_size;
extern ulong max_connections,max_connect_errors, connect_timeout;
extern ulong slave_net_timeout, slave_trans_retries;
@@ -1474,6 +1487,12 @@
table->status= STATUS_NO_RECORD;
table->keys_in_use_for_query= table->s->keys_in_use;
table->maybe_null= table_list->outer_join;
+ TABLE_LIST *embedding= table_list->embedding;
+ while (!table->maybe_null && embedding)
+ {
+ table->maybe_null= embedding->outer_join;
+ embedding= embedding->embedding;
+ }
table->tablenr= tablenr;
table->map= (table_map) 1 << tablenr;
table->force_index= table_list->force_index;
--- 1.454/sql/mysqld.cc 2005-08-09 09:49:31 +02:00
+++ 1.455/sql/mysqld.cc 2005-08-27 07:49:55 +02:00
@@ -362,7 +362,12 @@
ulong opt_ndb_cache_check_time;
const char *opt_ndb_mgmd;
ulong opt_ndb_nodeid;
-bool opt_ndb_linear_hash;
+
+const char *ndb_distribution_names[]= {"KEYHASH", "LINHASH", NullS};
+TYPELIB ndb_distribution_typelib= { array_elements(ndb_distribution_names)-1,
+ "", ndb_distribution_names, NULL };
+const char *opt_ndb_distribution= ndb_distribution_names[ND_KEYHASH];
+enum ndb_distribution opt_ndb_distribution_id= ND_KEYHASH;
#endif
my_bool opt_readonly, use_temp_pool, relay_log_purge;
my_bool opt_sync_frm, opt_allow_suspicious_udfs;
@@ -389,8 +394,8 @@
uint lower_case_table_names;
uint tc_heuristic_recover= 0;
uint volatile thread_count, thread_running;
-ulong back_log, connect_timeout, concurrency;
-ulong server_id, thd_startup_options;
+ulonglong thd_startup_options;
+ulong back_log, connect_timeout, concurrency, server_id;
ulong table_cache_size, thread_stack, what_to_log;
ulong query_buff_size, slow_launch_time, slave_open_temp_tables;
ulong open_files_limit, max_binlog_size, max_relay_log_size;
@@ -715,7 +720,6 @@
}
#endif
end_thr_alarm(0); // Abort old alarms.
- end_slave();
/*
First signal all threads that it's time to die
@@ -731,6 +735,10 @@
{
DBUG_PRINT("quit",("Informing thread %ld that it's time to die",
tmp->thread_id));
+ /* We skip slave threads on this first loop through. */
+ if (tmp->slave_thread)
+ continue;
+
tmp->killed= THD::KILL_CONNECTION;
if (tmp->mysys_var)
{
@@ -747,6 +755,8 @@
}
(void) pthread_mutex_unlock(&LOCK_thread_count); // For unlink from list
+ end_slave();
+
if (thread_count)
sleep(2); // Give threads time to die
@@ -1051,6 +1061,7 @@
(void) ha_panic(HA_PANIC_CLOSE); /* close all tables and logs */
if (tc_log)
tc_log->close();
+ xid_cache_free();
delete_elements(&key_caches, (void (*)(const char*, gptr)) free_key_cache);
multi_keycache_free();
end_thr_alarm(1); /* Free allocated memory */
@@ -1906,7 +1917,8 @@
static void sig_reload(int signo)
{
// Flush everything
- reload_acl_and_cache((THD*) 0,REFRESH_LOG, (TABLE_LIST*) 0, NULL);
+ bool not_used;
+ reload_acl_and_cache((THD*) 0,REFRESH_LOG, (TABLE_LIST*) 0, ¬_used);
signal(signo, SIG_ACK);
}
@@ -2265,12 +2277,13 @@
case SIGHUP:
if (!abort_loop)
{
+ bool not_used;
mysql_print_status(); // Print some debug info
reload_acl_and_cache((THD*) 0,
(REFRESH_LOG | REFRESH_TABLES | REFRESH_FAST |
REFRESH_GRANT |
REFRESH_THREADS | REFRESH_HOSTS),
- (TABLE_LIST*) 0, NULL); // Flush logs
+ (TABLE_LIST*) 0, ¬_used); // Flush logs
}
break;
#ifdef USE_ONE_SIGNAL_HAND
@@ -2918,6 +2931,11 @@
using_update_log=1;
}
+ if (xid_cache_init())
+ {
+ sql_print_error("Out of memory");
+ unireg_abort(1);
+ }
if (ha_init())
{
sql_print_error("Can't init databases");
@@ -4311,7 +4329,7 @@
OPT_NDB_FORCE_SEND, OPT_NDB_AUTOINCREMENT_PREFETCH_SZ,
OPT_NDB_SHM, OPT_NDB_OPTIMIZED_NODE_SELECTION, OPT_NDB_CACHE_CHECK_TIME,
OPT_NDB_MGMD, OPT_NDB_NODEID,
- OPT_NDB_LINEAR_HASH,
+ OPT_NDB_DISTRIBUTION,
OPT_SKIP_SAFEMALLOC,
OPT_TEMP_POOL, OPT_TX_ISOLATION, OPT_COMPLETION_TYPE,
OPT_SKIP_STACK_TRACE, OPT_SKIP_SYMLINKS,
@@ -4879,16 +4897,11 @@
(gptr*) &global_system_variables.ndb_autoincrement_prefetch_sz,
(gptr*) &global_system_variables.ndb_autoincrement_prefetch_sz,
0, GET_ULONG, REQUIRED_ARG, 32, 1, 256, 0, 0, 0},
- {"ndb-use-linear-hash", OPT_NDB_LINEAR_HASH,
- "Flag to indicate whether to use linear hash for default in new tables",
- (gptr*) &opt_ndb_linear_hash,
- (gptr*) &opt_ndb_linear_hash,
- 0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0},
- {"ndb_use_linear_hash", OPT_NDB_LINEAR_HASH,
- "Flag to indicate whether to use linear hash for default in new tables",
- (gptr*) &opt_ndb_linear_hash,
- (gptr*) &opt_ndb_linear_hash,
- 0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0},
+ {"ndb-distibution", OPT_NDB_DISTRIBUTION,
+ "Default distribution for new tables in ndb",
+ (gptr*) &opt_ndb_distribution,
+ (gptr*) &opt_ndb_distribution,
+ 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"ndb-force-send", OPT_NDB_FORCE_SEND,
"Force send of buffers to ndb immediately without waiting for "
"other threads.",
@@ -5337,6 +5350,10 @@
"Helps in performance tuning in heavily concurrent environments.",
(gptr*) &srv_thread_concurrency, (gptr*) &srv_thread_concurrency,
0, GET_LONG, REQUIRED_ARG, 20, 1, 1000, 0, 1, 0},
+ {"innodb_commit_concurrency", OPT_INNODB_THREAD_CONCURRENCY,
+ "Helps in performance tuning in heavily concurrent environments.",
+ (gptr*) &srv_commit_concurrency, (gptr*) &srv_commit_concurrency,
+ 0, GET_LONG, REQUIRED_ARG, 0, 0, 1000, 0, 1, 0},
{"innodb_thread_sleep_delay", OPT_INNODB_THREAD_SLEEP_DELAY,
"Time of innodb thread sleeping before joining InnoDB queue (usec). Value 0"
" disable a sleep",
@@ -6673,6 +6690,20 @@
else
opt_ndb_constrbuf[opt_ndb_constrbuf_len]= 0;
opt_ndbcluster_connectstring= opt_ndb_constrbuf;
+ break;
+ case OPT_NDB_DISTRIBUTION:
+ int id;
+ if ((id= find_type(argument, &ndb_distribution_typelib, 2)) <= 0)
+ {
+ fprintf(stderr,
+ "Unknown ndb distribution type: '%s' "
+ "(should be '%s' or '%s')\n",
+ argument,
+ ndb_distribution_names[ND_KEYHASH],
+ ndb_distribution_names[ND_LINHASH]);
+ exit(1);
+ }
+ opt_ndb_distribution_id= (enum ndb_distribution)(id-1);
break;
#endif
case OPT_INNODB:
--- 1.81/sql/sql_cache.cc 2005-08-09 09:49:31 +02:00
+++ 1.82/sql/sql_cache.cc 2005-08-27 07:49:55 +02:00
@@ -762,7 +762,7 @@
TABLE_COUNTER_TYPE local_tables;
ulong tot_length;
DBUG_ENTER("Query_cache::store_query");
- if (query_cache_size == 0)
+ if (query_cache_size == 0 || thd->locked_tables)
DBUG_VOID_RETURN;
uint8 tables_type= 0;
@@ -923,6 +923,10 @@
0 The query was cached and user was sent the result.
-1 The query was cached but we didn't have rights to use it.
No error is sent to the client yet.
+
+ NOTE
+ This method requires that sql points to allocated memory of size:
+ tot_length= query_length + thd->db_length + 1 + QUERY_CACHE_FLAGS_SIZE;
*/
int
@@ -936,8 +940,8 @@
Query_cache_query_flags flags;
DBUG_ENTER("Query_cache::send_result_to_client");
- if (query_cache_size == 0 || thd->variables.query_cache_type == 0)
-
+ if (query_cache_size == 0 || thd->locked_tables ||
+ thd->variables.query_cache_type == 0)
goto err;
/* Check that we haven't forgot to reset the query cache variables */
--- 1.178/sql/sql_class.cc 2005-08-09 09:49:31 +02:00
+++ 1.179/sql/sql_class.cc 2005-08-27 07:49:56 +02:00
@@ -157,8 +157,8 @@
** Thread specific functions
****************************************************************************/
-Open_tables_state::Open_tables_state()
- :version(refresh_version)
+Open_tables_state::Open_tables_state(ulong version_arg)
+ :version(version_arg)
{
reset_open_tables_state();
}
@@ -172,9 +172,9 @@
THD::THD()
:Statement(CONVENTIONAL_EXECUTION, 0, ALLOC_ROOT_MIN_BLOCK_SIZE, 0),
- Open_tables_state(),
+ Open_tables_state(refresh_version),
lock_id(&main_lock_id),
- user_time(0), in_sub_stmt(FALSE), global_read_lock(0), is_fatal_error(0),
+ user_time(0), in_sub_stmt(0), global_read_lock(0), is_fatal_error(0),
rand_used(0), time_zone_used(0),
last_insert_id_used(0), insert_id_used(0), clear_next_insert_id(0),
in_lock_tables(0), bootstrap(0), derived_tables_processing(FALSE),
@@ -323,7 +323,8 @@
variables.trans_alloc_block_size,
variables.trans_prealloc_size);
#endif
- transaction.xid.null();
+ transaction.xid_state.xid.null();
+ transaction.xid_state.in_thd=1;
}
@@ -358,9 +359,15 @@
{
DBUG_ENTER("THD::cleanup");
#ifdef ENABLE_WHEN_BINLOG_WILL_BE_ABLE_TO_PREPARE
- if (transaction.xa_state != XA_PREPARED)
+ if (transaction.xid_state.xa_state == XA_PREPARED)
+ {
+#error xid_state in the cache should be replaced by the allocated value
+ }
#endif
+ {
ha_rollback(this);
+ xid_cache_delete(&transaction.xid_state);
+ }
if (locked_tables)
{
lock=locked_tables; locked_tables=0;
@@ -1813,31 +1820,195 @@
access to mysql.proc table to find definitions of stored routines.
****************************************************************************/
-bool THD::push_open_tables_state()
+void THD::reset_n_backup_open_tables_state(Open_tables_state *backup)
{
- Open_tables_state *state;
- DBUG_ENTER("push_open_table_state");
- /* Currently we only push things one level */
- DBUG_ASSERT(open_state_list.elements == 0);
-
- if (!(state= (Open_tables_state*) alloc(sizeof(*state))))
- DBUG_RETURN(1); // Fatal error is set
- /* Store state for currently open tables */
- state->set_open_tables_state(this);
- if (open_state_list.push_back(state, mem_root))
- DBUG_RETURN(1); // Fatal error is set
+ DBUG_ENTER("reset_n_backup_open_tables_state");
+ backup->set_open_tables_state(this);
reset_open_tables_state();
- DBUG_RETURN(0);
+ DBUG_VOID_RETURN;
}
-void THD::pop_open_tables_state()
-{
- Open_tables_state *state;
- DBUG_ENTER("pop_open_table_state");
- /* Currently we only push things one level */
- DBUG_ASSERT(open_state_list.elements == 1);
- state= open_state_list.pop();
- set_open_tables_state(state);
+void THD::restore_backup_open_tables_state(Open_tables_state *backup)
+{
+ DBUG_ENTER("restore_backup_open_tables_state");
+ /*
+ Before we will throw away current open tables state we want
+ to be sure that it was properly cleaned up.
+ */
+ DBUG_ASSERT(open_tables == 0 && temporary_tables == 0 &&
+ handler_tables == 0 && derived_tables == 0 &&
+ lock == 0 && locked_tables == 0 &&
+ prelocked_mode == NON_PRELOCKED);
+ set_open_tables_state(backup);
DBUG_VOID_RETURN;
}
+
+
+
+/****************************************************************************
+ Handling of statement states in functions and triggers.
+
+ This is used to ensure that the function/trigger gets a clean state
+ to work with and does not cause any side effects of the calling statement.
+
+ It also allows most stored functions and triggers to replicate even
+ if they are used items that would normally be stored in the binary
+ replication (like last_insert_id() etc...)
+
+ The following things is done
+ - Disable binary logging for the duration of the statement
+ - Disable multi-result-sets for the duration of the statement
+ - Value of last_insert_id() is reset and restored
+ - Value set by 'SET INSERT_ID=#' is reset and restored
+ - Value for found_rows() is reset and restored
+ - examined_row_count is added to the total
+ - cuted_fields is added to the total
+
+ NOTES:
+ Seed for random() is saved for the first! usage of RAND()
+ We reset examined_row_count and cuted_fields and add these to the
+ result to ensure that if we have a bug that would reset these within
+ a function, we are not loosing any rows from the main statement.
+****************************************************************************/
+
+void THD::reset_sub_statement_state(Sub_statement_state *backup,
+ uint new_state)
+{
+ backup->options= options;
+ backup->in_sub_stmt= in_sub_stmt;
+ backup->no_send_ok= net.no_send_ok;
+ backup->enable_slow_log= enable_slow_log;
+ backup->last_insert_id= last_insert_id;
+ backup->next_insert_id= next_insert_id;
+ backup->insert_id_used= insert_id_used;
+ backup->limit_found_rows= limit_found_rows;
+ backup->examined_row_count= examined_row_count;
+ backup->sent_row_count= sent_row_count;
+ backup->cuted_fields= cuted_fields;
+ backup->client_capabilities= client_capabilities;
+
+ options&= ~OPTION_BIN_LOG;
+ /* Disable result sets */
+ client_capabilities &= ~CLIENT_MULTI_RESULTS;
+ in_sub_stmt|= new_state;
+ last_insert_id= 0;
+ next_insert_id= 0;
+ insert_id_used= 0;
+ examined_row_count= 0;
+ sent_row_count= 0;
+ cuted_fields= 0;
+
+#ifndef EMBEDDED_LIBRARY
+ /* Surpress OK packets in case if we will execute statements */
+ net.no_send_ok= TRUE;
+#endif
+}
+
+
+void THD::restore_sub_statement_state(Sub_statement_state *backup)
+{
+ options= backup->options;
+ in_sub_stmt= backup->in_sub_stmt;
+ net.no_send_ok= backup->no_send_ok;
+ enable_slow_log= backup->enable_slow_log;
+ last_insert_id= backup->last_insert_id;
+ next_insert_id= backup->next_insert_id;
+ insert_id_used= backup->insert_id_used;
+ limit_found_rows= backup->limit_found_rows;
+ sent_row_count= backup->sent_row_count;
+ client_capabilities= backup->client_capabilities;
+
+ /*
+ The following is added to the old values as we are interested in the
+ total complexity of the query
+ */
+ examined_row_count+= backup->examined_row_count;
+ cuted_fields+= backup->cuted_fields;
+}
+
+
+/***************************************************************************
+ Handling of XA id cacheing
+***************************************************************************/
+
+pthread_mutex_t LOCK_xid_cache;
+HASH xid_cache;
+
+static byte *xid_get_hash_key(const byte *ptr,uint *length,
+ my_bool not_used __attribute__((unused)))
+{
+ *length=((XID_STATE*)ptr)->xid.length();
+ return (byte *)&((XID_STATE*)ptr)->xid;
+}
+
+static void xid_free_hash (void *ptr)
+{
+ if (!((XID_STATE*)ptr)->in_thd)
+ my_free((byte *)ptr, MYF(0));
+}
+
+bool xid_cache_init()
+{
+ pthread_mutex_init(&LOCK_xid_cache, MY_MUTEX_INIT_FAST);
+ return hash_init(&xid_cache, &my_charset_bin, 100, 0, 0,
+ xid_get_hash_key, xid_free_hash, 0) != 0;
+}
+
+void xid_cache_free()
+{
+ if (hash_inited(&xid_cache))
+ {
+ hash_free(&xid_cache);
+ pthread_mutex_destroy(&LOCK_xid_cache);
+ }
+}
+
+XID_STATE *xid_cache_search(XID *xid)
+{
+ pthread_mutex_lock(&LOCK_xid_cache);
+ XID_STATE *res=(XID_STATE *)hash_search(&xid_cache, (byte *)xid, xid->length());
+ pthread_mutex_unlock(&LOCK_xid_cache);
+ return res;
+}
+
+
+bool xid_cache_insert(XID *xid, enum xa_states xa_state)
+{
+ XID_STATE *xs;
+ my_bool res;
+ pthread_mutex_lock(&LOCK_xid_cache);
+ if (hash_search(&xid_cache, (byte *)xid, xid->length()))
+ res=0;
+ else if (!(xs=(XID_STATE *)my_malloc(sizeof(*xs), MYF(MY_WME))))
+ res=1;
+ else
+ {
+ xs->xa_state=xa_state;
+ xs->xid.set(xid);
+ xs->in_thd=0;
+ res=my_hash_insert(&xid_cache, (byte*)xs);
+ }
+ pthread_mutex_unlock(&LOCK_xid_cache);
+ return res;
+}
+
+
+bool xid_cache_insert(XID_STATE *xid_state)
+{
+ pthread_mutex_lock(&LOCK_xid_cache);
+ DBUG_ASSERT(hash_search(&xid_cache, (byte *)&xid_state->xid,
+ xid_state->xid.length())==0);
+ my_bool res=my_hash_insert(&xid_cache, (byte*)xid_state);
+ pthread_mutex_unlock(&LOCK_xid_cache);
+ return res;
+}
+
+
+void xid_cache_delete(XID_STATE *xid_state)
+{
+ pthread_mutex_lock(&LOCK_xid_cache);
+ hash_delete(&xid_cache, (byte *)xid_state);
+ pthread_mutex_unlock(&LOCK_xid_cache);
+}
+
--- 1.234/sql/sql_class.h 2005-08-09 09:49:31 +02:00
+++ 1.235/sql/sql_class.h 2005-08-27 07:49:56 +02:00
@@ -351,8 +351,6 @@
inline uint32 get_open_count() { return open_count; }
};
-/* character conversion tables */
-
typedef struct st_copy_info {
ha_rows records;
@@ -566,11 +564,11 @@
#endif /* HAVE_NDBCLUSTER_DB */
my_bool old_alter_table;
my_bool old_passwords;
-
+
/* Only charset part of these variables is sensible */
- CHARSET_INFO *character_set_client;
+ CHARSET_INFO *character_set_client;
CHARSET_INFO *character_set_results;
-
+
/* Both charset and collation parts of these variables are important */
CHARSET_INFO *collation_server;
CHARSET_INFO *collation_database;
@@ -633,7 +631,7 @@
ulong filesort_range_count;
ulong filesort_rows;
ulong filesort_scan_count;
- /* Ppepared statements and binary protocol */
+ /* Prepared statements and binary protocol */
ulong com_stmt_prepare;
ulong com_stmt_execute;
ulong com_stmt_send_long_data;
@@ -658,8 +656,8 @@
/* The following macro is to make init of Query_arena simpler */
#ifndef DBUG_OFF
#define INIT_ARENA_DBUG_INFO is_backup_arena= 0
-#else
-#define INIT_ARENA_DBUG_INFO
+#else
+#define INIT_ARENA_DBUG_INFO
#endif
@@ -934,6 +932,22 @@
enum xa_states {XA_NOTR=0, XA_ACTIVE, XA_IDLE, XA_PREPARED};
extern const char *xa_state_names[];
+typedef struct st_xid_state {
+ /* For now, this is only used to catch duplicated external xids */
+ XID xid; // transaction identifier
+ enum xa_states xa_state; // used by external XA only
+ bool in_thd;
+} XID_STATE;
+
+extern pthread_mutex_t LOCK_xid_cache;
+extern HASH xid_cache;
+bool xid_cache_init(void);
+void xid_cache_free(void);
+XID_STATE *xid_cache_search(XID *xid);
+bool xid_cache_insert(XID *xid, enum xa_states xa_state);
+bool xid_cache_insert(XID_STATE *xid_state);
+void xid_cache_delete(XID_STATE *xid_state);
+
/*
A registry for item tree transformations performed during
query optimization. We register only those changes which require
@@ -955,7 +969,7 @@
/*
- Class that holds information about tables which were open and locked
+ Class that holds information about tables which were opened and locked
by the thread. It is also used to save/restore this information in
push_open_tables_state()/pop_open_tables_state().
*/
@@ -1018,7 +1032,13 @@
ulong version;
uint current_tablenr;
- Open_tables_state();
+ /*
+ This constructor serves for creation of Open_tables_state instances
+ which are used as backup storage.
+ */
+ Open_tables_state() {};
+
+ Open_tables_state(ulong version_arg);
void set_open_tables_state(Open_tables_state *state)
{
@@ -1034,6 +1054,27 @@
};
+/* class to save context when executing a function or trigger */
+
+/* Defines used for Sub_statement_state::in_sub_stmt */
+
+#define SUB_STMT_TRIGGER 1
+#define SUB_STMT_FUNCTION 2
+
+class Sub_statement_state
+{
+public:
+ ulonglong options;
+ ulonglong last_insert_id, next_insert_id;
+ ulonglong limit_found_rows;
+ ha_rows cuted_fields, sent_row_count, examined_row_count;
+ ulong client_capabilities;
+ uint in_sub_stmt;
+ bool enable_slow_log, insert_id_used;
+ my_bool no_send_ok;
+};
+
+
/*
For each client connection we create a separate thread with THD serving as
a thread/connection descriptor
@@ -1071,7 +1112,7 @@
// the lock_id of a cursor.
pthread_mutex_t LOCK_delete; // Locked before thd is deleted
/* all prepared statements and cursors of this connection */
- Statement_map stmt_map;
+ Statement_map stmt_map;
/*
A pointer to the stack frame of handle_one_connection(),
which is called first in the thread for handling a client
@@ -1140,11 +1181,10 @@
time_t connect_time,thr_create_time; // track down slow pthread_create
thr_lock_type update_lock_default;
delayed_insert *di;
- my_bool tablespace_op; /* This is TRUE in DISCARD/IMPORT TABLESPACE */
-
- /* TRUE if we are inside of trigger or stored function. */
- bool in_sub_stmt;
-
+
+ /* <> 0 if we are inside of trigger or stored function. */
+ uint in_sub_stmt;
+
/* container for handler's private per-connection data */
void *ha_data[MAX_HA];
struct st_transactions {
@@ -1152,8 +1192,7 @@
THD_TRANS all; // Trans since BEGIN WORK
THD_TRANS stmt; // Trans for current statement
bool on; // see ha_enable_transaction()
- XID xid; // transaction identifier
- enum xa_states xa_state; // used by external XA only
+ XID_STATE xid_state;
/*
Tables changed in transaction (that must be invalidated in query cache).
List contain only transactional tables, that not invalidated in query
@@ -1173,7 +1212,7 @@
st_transactions()
{
bzero((char*)this, sizeof(*this));
- xid.null();
+ xid_state.xid.null();
init_sql_alloc(&mem_root, ALLOC_ROOT_MIN_BLOCK_SIZE, 0);
}
#endif
@@ -1226,8 +1265,16 @@
*/
ulonglong current_insert_id;
ulonglong limit_found_rows;
+ ulonglong options; /* Bitmap of states */
+ longlong row_count_func; /* For the ROW_COUNT() function */
ha_rows cuted_fields,
sent_row_count, examined_row_count;
+ /*
+ The set of those tables whose fields are referenced in all subqueries
+ of the query.
+ TODO: possibly this it is incorrect to have used tables in THD because
+ with more than one subquery, it is not clear what does the field mean.
+ */
table_map used_tables;
USER_CONN *user_connect;
CHARSET_INFO *db_charset;
@@ -1240,7 +1287,6 @@
List <MYSQL_ERROR> warn_list;
uint warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_END];
uint total_warn_count;
- List <Open_tables_state> open_state_list;
/*
Id of current query. Statement can be reused to execute several queries
query_id is global in context of the whole MySQL server.
@@ -1250,7 +1296,7 @@
update auto-updatable fields (like auto_increment and timestamp).
*/
query_id_t query_id, warn_id;
- ulong options, thread_id, col_access;
+ ulong thread_id, col_access;
/* Statement id is thread-wide. This counter is used to generate ids */
ulong statement_id_counter;
@@ -1290,7 +1336,8 @@
bool no_warnings_for_error; /* no warnings on call to my_error() */
/* set during loop of derived table processing */
bool derived_tables_processing;
- longlong row_count_func; /* For the ROW_COUNT() function */
+ my_bool tablespace_op; /* This is TRUE in DISCARD/IMPORT TABLESPACE */
+
sp_rcontext *spcont; // SP runtime context
sp_cache *sp_proc_cache;
sp_cache *sp_func_cache;
@@ -1496,13 +1543,15 @@
void set_status_var_init();
bool is_context_analysis_only()
{ return current_arena->is_stmt_prepare() || lex->view_prepare_mode; }
- bool push_open_tables_state();
- void pop_open_tables_state();
+ void reset_n_backup_open_tables_state(Open_tables_state *backup);
+ void restore_backup_open_tables_state(Open_tables_state *backup);
+ void reset_sub_statement_state(Sub_statement_state *backup, uint new_state);
+ void restore_sub_statement_state(Sub_statement_state *backup);
};
#define tmp_disable_binlog(A) \
- {ulong tmp_disable_binlog__save_options= (A)->options; \
+ {ulonglong tmp_disable_binlog__save_options= (A)->options; \
(A)->options&= ~OPTION_BIN_LOG
#define reenable_binlog(A) (A)->options= tmp_disable_binlog__save_options;}
@@ -1569,6 +1618,7 @@
statement/stored procedure.
*/
virtual void cleanup();
+ void set_thd(THD *thd_arg) { thd= thd_arg; }
};
@@ -1924,14 +1974,13 @@
{
TABLE_LIST *delete_tables, *table_being_deleted;
Unique **tempfiles;
- THD *thd;
ha_rows deleted, found;
uint num_of_tables;
int error;
bool do_delete, transactional_tables, normal_tables, delete_while_scanning;
public:
- multi_delete(THD *thd, TABLE_LIST *dt, uint num_of_tables);
+ multi_delete(TABLE_LIST *dt, uint num_of_tables);
~multi_delete();
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
bool send_data(List<Item> &items);
@@ -1947,7 +1996,6 @@
TABLE_LIST *all_tables; /* query/update command tables */
TABLE_LIST *leaves; /* list of leves of join table tree */
TABLE_LIST *update_tables, *table_being_updated;
- THD *thd;
TABLE **tmp_tables, *main_table, *table_to_update;
TMP_TABLE_PARAM *tmp_table_param;
ha_rows updated, found;
@@ -1959,7 +2007,7 @@
bool do_update, trans_safe, transactional_tables, ignore;
public:
- multi_update(THD *thd_arg, TABLE_LIST *ut, TABLE_LIST *leaves_list,
+ multi_update(TABLE_LIST *ut, TABLE_LIST *leaves_list,
List<Item> *fields, List<Item> *values,
enum_duplicates handle_duplicates, bool ignore);
~multi_update();
--- 1.151/sql/sql_delete.cc 2005-07-21 15:33:42 +02:00
+++ 1.152/sql/sql_delete.cc 2005-08-27 07:49:56 +02:00
@@ -30,7 +30,7 @@
#include "sql_trigger.h"
bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
- SQL_LIST *order, ha_rows limit, ulong options)
+ SQL_LIST *order, ha_rows limit, ulonglong options)
{
bool will_batch;
int error, loc_error;
@@ -309,6 +309,7 @@
DBUG_ENTER("mysql_prepare_delete");
if (setup_tables(thd, &thd->lex->select_lex.context,
+ &thd->lex->select_lex.top_join_list,
table_list, conds, &select_lex->leaf_tables,
FALSE) ||
setup_conds(thd, table_list, select_lex->leaf_tables, conds) ||
@@ -367,6 +368,7 @@
lex->query_tables also point on local list of DELETE SELECT_LEX
*/
if (setup_tables(thd, &thd->lex->select_lex.context,
+ &thd->lex->select_lex.top_join_list,
lex->query_tables, &lex->select_lex.where,
&lex->select_lex.leaf_tables, FALSE))
DBUG_RETURN(TRUE);
@@ -415,9 +417,8 @@
}
-multi_delete::multi_delete(THD *thd_arg, TABLE_LIST *dt,
- uint num_of_tables_arg)
- : delete_tables(dt), thd(thd_arg), deleted(0), found(0),
+multi_delete::multi_delete(TABLE_LIST *dt, uint num_of_tables_arg)
+ : delete_tables(dt), deleted(0), found(0),
num_of_tables(num_of_tables_arg), error(0),
do_delete(0), transactional_tables(0), normal_tables(0)
{
@@ -826,7 +827,7 @@
ha_enable_transaction(thd, FALSE);
mysql_init_select(thd->lex);
error= mysql_delete(thd, table_list, (COND*) 0, (SQL_LIST*) 0,
- HA_POS_ERROR, 0);
+ HA_POS_ERROR, LL(0));
ha_enable_transaction(thd, TRUE);
thd->options= save_options;
DBUG_RETURN(error);
--- 1.182/sql/sql_lex.h 2005-07-25 10:30:26 +02:00
+++ 1.183/sql/sql_lex.h 2005-08-27 07:49:56 +02:00
@@ -308,7 +308,7 @@
*link_next, **link_prev; /* list of whole SELECT_LEX */
public:
- ulong options;
+ ulonglong options;
/*
result of this query can't be cached, bit field, can be :
UNCACHEABLE_DEPENDENT
@@ -461,6 +461,7 @@
inline bool is_prepared() { return prepared; }
bool change_result(select_subselect *result, select_subselect *old_result);
void set_limit(st_select_lex *values);
+ void set_thd(THD *thd_arg) { thd= thd_arg; }
friend void lex_start(THD *thd, uchar *buf, uint length);
friend int subselect_union_engine::exec();
@@ -474,14 +475,16 @@
{
public:
Name_resolution_context context;
- char *db, *db1, *table1, *db2, *table2; /* For outer join using .. */
+ char *db;
Item *where, *having; /* WHERE & HAVING clauses */
Item *prep_where; /* saved WHERE clause for prepared statement processing */
/* point on lex in which it was created, used in view subquery detection */
st_lex *parent_lex;
enum olap_type olap;
- SQL_LIST table_list, group_list; /* FROM & GROUP BY clauses */
- List<Item> item_list; /* list of fields & expressions */
+ /* FROM clause - points to the beginning of the TABLE_LIST::next_local list. */
+ SQL_LIST table_list;
+ SQL_LIST group_list; /* GROUP BY clause. */
+ List<Item> item_list; /* list of fields & expressions */
List<String> interval_list, use_index, *use_index_ptr,
ignore_index, *ignore_index_ptr;
/*
@@ -494,7 +497,12 @@
List<TABLE_LIST> top_join_list; /* join list of the top level */
List<TABLE_LIST> *join_list; /* list for the currently parsed join */
TABLE_LIST *embedding; /* table embedding to the above list */
- TABLE_LIST *leaf_tables; /* list of leaves in join table tree */
+ /*
+ Beginning of the list of leaves in a FROM clause, where the leaves
+ inlcude all base tables including view tables. The tables are connected
+ by TABLE_LIST::next_leaf, so leaf_tables points to the left-most leaf.
+ */
+ TABLE_LIST *leaf_tables;
const char *type; /* type of select for EXPLAIN */
SQL_LIST order_list; /* ORDER clause */
@@ -596,7 +604,6 @@
bool init_nested_join(THD *thd);
TABLE_LIST *end_nested_join(THD *thd);
TABLE_LIST *nest_last_join(THD *thd);
- void save_names_for_using_list(TABLE_LIST *tab1, TABLE_LIST *tab2);
void add_joined_table(TABLE_LIST *table);
TABLE_LIST *convert_right_join();
List<Item>* get_item_list();
@@ -652,6 +659,10 @@
#define ALTER_CONVERT 1024
#define ALTER_FORCE 2048
#define ALTER_RECREATE 4096
+#define ALTER_ADD_PARTITION 8192
+#define ALTER_DROP_PARTITION 16384
+#define ALTER_COALESCE_PARTITION 32768
+#define ALTER_REORGANISE_PARTITION 65536
typedef struct st_alter_info
{
@@ -660,9 +671,17 @@
uint flags;
enum enum_enable_or_disable keys_onoff;
enum tablespace_op_type tablespace_op;
+ List<char> partition_names;
+ uint no_parts;
st_alter_info(){clear();}
- void clear(){keys_onoff= LEAVE_AS_IS;tablespace_op= NO_TABLESPACE_OP;}
+ void clear()
+ {
+ keys_onoff= LEAVE_AS_IS;
+ tablespace_op= NO_TABLESPACE_OP;
+ no_parts= 0;
+ partition_names.empty();
+ }
void reset(){drop_list.empty();alter_list.empty();clear();}
} ALTER_INFO;
@@ -741,6 +760,21 @@
List<set_var_base> var_list;
List<Item_param> param_list;
List<LEX_STRING> view_list; // view list (list of field names in view)
+ /*
+ A stack of name resolution contexts for the query. This stack is used
+ at parse time to set local name resolution contexts for various parts
+ of a query. For example, in a JOIN ... ON (some_condition) clause the
+ Items in 'some_condition' must be resolved only against the operands
+ of the the join, and not against the whole clause. Similarly, Items in
+ subqueries should be resolved against the subqueries (and outer queries).
+ The stack is used in the following way: when the parser detects that
+ all Items in some clause need a local context, it creates a new context
+ and pushes it on the stack. All newly created Items always store the
+ top-most context in the stack. Once the parser leaves the clause that
+ required a local context, the parser pops the top-most context.
+ */
+ List<Name_resolution_context> context_stack;
+
SQL_LIST proc_list, auxilliary_table_list, save_list;
create_field *last_field;
udf_func udf;
@@ -938,6 +972,21 @@
return ( query_tables_own_last ? *query_tables_own_last : 0);
}
void cleanup_after_one_table_open();
+
+ void push_context(Name_resolution_context *context)
+ {
+ context_stack.push_front(context);
+ }
+
+ void pop_context()
+ {
+ context_stack.pop();
+ }
+
+ Name_resolution_context *current_context()
+ {
+ return context_stack.head();
+ }
} LEX;
struct st_lex_local: public st_lex
--- 1.432/sql/sql_parse.cc 2005-08-09 09:49:31 +02:00
+++ 1.433/sql/sql_parse.cc 2005-08-27 07:49:56 +02:00
@@ -242,7 +242,8 @@
/*
- Check if user exist and password supplied is correct.
+ Check if user exist and password supplied is correct.
+
SYNOPSIS
check_user()
thd thread handle, thd->{host,user,ip} are used
@@ -277,9 +278,13 @@
/* Change database if necessary */
if (db && db[0])
{
+ /*
+ thd->db is saved in caller and needs to be freed by caller if this
+ function returns 0
+ */
thd->db= 0;
thd->db_length= 0;
- if (mysql_change_db(thd, db))
+ if (mysql_change_db(thd, db, FALSE))
{
/* Send the error to the client */
net_send_error(thd);
@@ -288,8 +293,7 @@
DBUG_RETURN(-1);
}
}
- else
- send_ok(thd);
+ send_ok(thd);
DBUG_RETURN(0);
#else
@@ -414,7 +418,7 @@
/* Change database if necessary */
if (db && db[0])
{
- if (mysql_change_db(thd, db))
+ if (mysql_change_db(thd, db, FALSE))
{
/* Send error to the client */
net_send_error(thd);
@@ -423,8 +427,7 @@
DBUG_RETURN(-1);
}
}
- else
- send_ok(thd);
+ send_ok(thd);
thd->password= test(passwd_len); // remember for error messages
/* Ready to handle queries */
DBUG_RETURN(0);
@@ -1105,11 +1108,11 @@
execute_init_command(thd, &sys_init_connect, &LOCK_sys_init_connect);
if (thd->query_error)
thd->killed= THD::KILL_CONNECTION;
+ thd->proc_info=0;
+ thd->set_time();
+ thd->init_for_queries();
}
- thd->proc_info=0;
- thd->set_time();
- thd->init_for_queries();
while (!net->error && net->vio != 0 &&
!(thd->killed == THD::KILL_CONNECTION))
{
@@ -1219,7 +1222,8 @@
length--;
buff[length]=0;
thd->query_length=length;
- thd->query= thd->memdup_w_gap(buff, length+1, thd->db_length+1);
+ thd->query= thd->memdup_w_gap(buff, length+1,
+ thd->db_length+1+QUERY_CACHE_FLAGS_SIZE);
thd->query[length] = '\0';
/*
We don't need to obtain LOCK_thread_count here because in bootstrap
@@ -1468,6 +1472,7 @@
/*
Perform one connection-level (COM_XXXX) command.
+
SYNOPSIS
dispatch_command()
thd connection handle
@@ -1518,8 +1523,11 @@
&LOCK_status);
thd->convert_string(&tmp, system_charset_info,
packet, strlen(packet), thd->charset());
- if (!mysql_change_db(thd, tmp.str))
+ if (!mysql_change_db(thd, tmp.str, FALSE))
+ {
mysql_log.write(thd,command,"%s",thd->db);
+ send_ok(thd);
+ }
break;
}
#ifdef HAVE_REPLICATION
@@ -1867,17 +1875,18 @@
}
#endif
case COM_REFRESH:
- {
- statistic_increment(thd->status_var.com_stat[SQLCOM_FLUSH],
- &LOCK_status);
- ulong options= (ulong) (uchar) packet[0];
- if (check_global_access(thd,RELOAD_ACL))
- break;
- mysql_log.write(thd,command,NullS);
- if (!reload_acl_and_cache(thd, options, (TABLE_LIST*) 0, NULL))
- send_ok(thd);
+ {
+ bool not_used;
+ statistic_increment(thd->status_var.com_stat[SQLCOM_FLUSH],
+ &LOCK_status);
+ ulong options= (ulong) (uchar) packet[0];
+ if (check_global_access(thd,RELOAD_ACL))
break;
- }
+ mysql_log.write(thd,command,NullS);
+ if (!reload_acl_and_cache(thd, options, (TABLE_LIST*) 0, ¬_used))
+ send_ok(thd);
+ break;
+ }
#ifndef EMBEDDED_LIBRARY
case COM_SHUTDOWN:
{
@@ -2021,7 +2030,7 @@
*/
bzero(&thd->transaction.stmt, sizeof(thd->transaction.stmt));
if (!thd->active_transaction())
- thd->transaction.xid.null();
+ thd->transaction.xid_state.xid.null();
/* report error issued during command execution */
if (thd->killed_errno() && !thd->net.report_error)
@@ -2047,7 +2056,17 @@
void log_slow_statement(THD *thd)
{
- time_t start_of_query=thd->start_time;
+ time_t start_of_query;
+
+ /*
+ The following should never be true with our current code base,
+ but better to keep this here so we don't accidently try to log a
+ statement in a trigger or stored function
+ */
+ if (unlikely(thd->in_sub_stmt))
+ return; // Don't set time for sub stmt
+
+ start_of_query= thd->start_time;
thd->end_time(); // Set start time
/*
@@ -2138,6 +2157,8 @@
{
TABLE_LIST **query_tables_last= lex->query_tables_last;
sel= new SELECT_LEX();
+ /* 'parent_lex' is used in init_query() so it must be before it. */
+ sel->parent_lex= lex;
sel->init_query();
if (!sel->add_table_to_list(thd, table_ident, 0, 0, TL_READ,
(List<String> *) 0, (List<String> *) 0))
@@ -2946,8 +2967,8 @@
*/
if (thd->locked_tables || thd->active_transaction())
{
- my_message(ER_LOCK_OR_ACTIVE_TRANSACTION, ER(ER_LOCK_OR_ACTIVE_TRANSACTION),
- MYF(0));
+ my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
+ ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
goto error;
}
{
@@ -3241,19 +3262,26 @@
if (!(res= open_and_lock_tables(thd, all_tables)))
{
/* Skip first table, which is the table we are inserting in */
- select_lex->table_list.first= (byte*)first_table->next_local;
-
+ TABLE_LIST *second_table= first_table->next_local;
+ select_lex->table_list.first= (byte*) second_table;
+ select_lex->context.table_list=
+ select_lex->context.first_name_resolution_table= second_table;
res= mysql_insert_select_prepare(thd);
- lex->select_lex.context.table_list= first_table->next_local;
if (!res && (result= new select_insert(first_table, first_table->table,
&lex->field_list,
&lex->update_list,
&lex->value_list,
lex->duplicates, lex->ignore)))
{
- /* Skip first table, which is the table we are inserting in */
- select_lex->context.table_list= first_table->next_local;
-
+ /*
+ Skip first table, which is the table we are inserting in.
+ Below we set context.table_list again because the call above to
+ mysql_insert_select_prepare() calls resolve_in_table_list_only(),
+ which in turn resets context.table_list and
+ context.first_name_resolution_table.
+ */
+ select_lex->context.table_list=
+ select_lex->context.first_name_resolution_table= second_table;
res= handle_select(thd, lex, result, OPTION_SETUP_TABLES_DONE);
delete result;
}
@@ -3322,7 +3350,7 @@
if ((res= mysql_multi_delete_prepare(thd)))
goto error;
- if (!thd->is_fatal_error && (result= new multi_delete(thd,aux_tables,
+ if (!thd->is_fatal_error && (result= new multi_delete(aux_tables,
lex->table_count)))
{
res= mysql_select(thd, &select_lex->ref_pointer_array,
@@ -3411,7 +3439,8 @@
}
#endif
case SQLCOM_CHANGE_DB:
- mysql_change_db(thd,select_lex->db);
+ if (!mysql_change_db(thd,select_lex->db,FALSE))
+ send_ok(thd);
break;
case SQLCOM_LOAD:
@@ -3642,7 +3671,7 @@
if (!(res = mysql_create_function(thd, &lex->udf)))
send_ok(thd);
#else
- net_printf_error(thd, ER_CANT_OPEN_LIBRARY, lex->udf.dl, 0, "feature disabled");
+ my_error(ER_CANT_OPEN_LIBRARY, MYF(0), lex->udf.dl, 0, "feature disabled");
res= TRUE;
#endif
break;
@@ -3826,13 +3855,13 @@
lex->no_write_to_binlog= 1;
case SQLCOM_FLUSH:
{
+ bool write_to_binlog;
if (check_global_access(thd,RELOAD_ACL) || check_db_used(thd, all_tables))
goto error;
/*
reload_acl_and_cache() will tell us if we are allowed to write to the
binlog or not.
*/
- bool write_to_binlog;
if (!reload_acl_and_cache(thd, lex->type, first_table, &write_to_binlog))
{
/*
@@ -4064,8 +4093,8 @@
name= thd->strdup(name);
db= thd->strmake(lex->sphead->m_db.str, lex->sphead->m_db.length);
res= (result= lex->sphead->create(thd));
- switch (result) {
- case SP_OK:
+ if (result == SP_OK)
+ {
lex->unit.cleanup();
delete lex->sphead;
lex->sphead= 0;
@@ -4085,33 +4114,26 @@
}
#endif
send_ok(thd);
- break;
- case SP_WRITE_ROW_FAILED:
- my_error(ER_SP_ALREADY_EXISTS, MYF(0), SP_TYPE_STRING(lex), name);
- lex->unit.cleanup();
- delete lex->sphead;
- lex->sphead= 0;
- goto error;
- case SP_NO_DB_ERROR:
- my_error(ER_BAD_DB_ERROR, MYF(0), lex->sphead->m_db.str);
- lex->unit.cleanup();
- delete lex->sphead;
- lex->sphead= 0;
- goto error;
- case SP_BAD_IDENTIFIER:
- my_error(ER_TOO_LONG_IDENT, MYF(0), name);
- lex->unit.cleanup();
- delete lex->sphead;
- lex->sphead= 0;
- goto error;
- case SP_BODY_TOO_LONG:
- my_error(ER_TOO_LONG_BODY, MYF(0), name);
- lex->unit.cleanup();
- delete lex->sphead;
- lex->sphead= 0;
- goto error;
- default:
- my_error(ER_SP_STORE_FAILED, MYF(0), SP_TYPE_STRING(lex), name);
+ }
+ else
+ {
+ switch (result) {
+ case SP_WRITE_ROW_FAILED:
+ my_error(ER_SP_ALREADY_EXISTS, MYF(0), SP_TYPE_STRING(lex), name);
+ break;
+ case SP_NO_DB_ERROR:
+ my_error(ER_BAD_DB_ERROR, MYF(0), lex->sphead->m_db.str);
+ break;
+ case SP_BAD_IDENTIFIER:
+ my_error(ER_TOO_LONG_IDENT, MYF(0), name);
+ break;
+ case SP_BODY_TOO_LONG:
+ my_error(ER_TOO_LONG_BODY, MYF(0), name);
+ break;
+ default:
+ my_error(ER_SP_STORE_FAILED, MYF(0), SP_TYPE_STRING(lex), name);
+ break;
+ }
lex->unit.cleanup();
delete lex->sphead;
lex->sphead= 0;
@@ -4506,14 +4528,15 @@
break;
}
case SQLCOM_XA_START:
- if (thd->transaction.xa_state == XA_IDLE && thd->lex->xa_opt == XA_RESUME)
+ if (thd->transaction.xid_state.xa_state == XA_IDLE &&
+ thd->lex->xa_opt == XA_RESUME)
{
- if (! thd->transaction.xid.eq(thd->lex->xid))
+ if (! thd->transaction.xid_state.xid.eq(thd->lex->xid))
{
my_error(ER_XAER_NOTA, MYF(0));
break;
}
- thd->transaction.xa_state=XA_ACTIVE;
+ thd->transaction.xid_state.xa_state=XA_ACTIVE;
send_ok(thd);
break;
}
@@ -4522,10 +4545,10 @@
my_error(ER_XAER_INVAL, MYF(0));
break;
}
- if (thd->transaction.xa_state != XA_NOTR)
+ if (thd->transaction.xid_state.xa_state != XA_NOTR)
{
my_error(ER_XAER_RMFAIL, MYF(0),
- xa_state_names[thd->transaction.xa_state]);
+ xa_state_names[thd->transaction.xid_state.xa_state]);
break;
}
if (thd->active_transaction() || thd->locked_tables)
@@ -4533,9 +4556,15 @@
my_error(ER_XAER_OUTSIDE, MYF(0));
break;
}
- DBUG_ASSERT(thd->transaction.xid.is_null());
- thd->transaction.xa_state=XA_ACTIVE;
- thd->transaction.xid.set(thd->lex->xid);
+ if (xid_cache_search(thd->lex->xid))
+ {
+ my_error(ER_XAER_DUPID, MYF(0));
+ break;
+ }
+ DBUG_ASSERT(thd->transaction.xid_state.xid.is_null());
+ thd->transaction.xid_state.xa_state=XA_ACTIVE;
+ thd->transaction.xid_state.xid.set(thd->lex->xid);
+ xid_cache_insert(&thd->transaction.xid_state);
thd->options= ((thd->options & (ulong) ~(OPTION_STATUS_NO_TRANS_UPDATE)) |
OPTION_BEGIN);
thd->server_status|= SERVER_STATUS_IN_TRANS;
@@ -4548,28 +4577,28 @@
my_error(ER_XAER_INVAL, MYF(0));
break;
}
- if (thd->transaction.xa_state != XA_ACTIVE)
+ if (thd->transaction.xid_state.xa_state != XA_ACTIVE)
{
my_error(ER_XAER_RMFAIL, MYF(0),
- xa_state_names[thd->transaction.xa_state]);
+ xa_state_names[thd->transaction.xid_state.xa_state]);
break;
}
- if (!thd->transaction.xid.eq(thd->lex->xid))
+ if (!thd->transaction.xid_state.xid.eq(thd->lex->xid))
{
my_error(ER_XAER_NOTA, MYF(0));
break;
}
- thd->transaction.xa_state=XA_IDLE;
+ thd->transaction.xid_state.xa_state=XA_IDLE;
send_ok(thd);
break;
case SQLCOM_XA_PREPARE:
- if (thd->transaction.xa_state != XA_IDLE)
+ if (thd->transaction.xid_state.xa_state != XA_IDLE)
{
my_error(ER_XAER_RMFAIL, MYF(0),
- xa_state_names[thd->transaction.xa_state]);
+ xa_state_names[thd->transaction.xid_state.xa_state]);
break;
}
- if (!thd->transaction.xid.eq(thd->lex->xid))
+ if (!thd->transaction.xid_state.xid.eq(thd->lex->xid))
{
my_error(ER_XAER_NOTA, MYF(0));
break;
@@ -4577,22 +4606,28 @@
if (ha_prepare(thd))
{
my_error(ER_XA_RBROLLBACK, MYF(0));
- thd->transaction.xa_state=XA_NOTR;
+ xid_cache_delete(&thd->transaction.xid_state);
+ thd->transaction.xid_state.xa_state=XA_NOTR;
break;
}
- thd->transaction.xa_state=XA_PREPARED;
+ thd->transaction.xid_state.xa_state=XA_PREPARED;
send_ok(thd);
break;
case SQLCOM_XA_COMMIT:
- if (!thd->transaction.xid.eq(thd->lex->xid))
+ if (!thd->transaction.xid_state.xid.eq(thd->lex->xid))
{
- if (!(res= !ha_commit_or_rollback_by_xid(thd->lex->xid, 1)))
+ XID_STATE *xs=xid_cache_search(thd->lex->xid);
+ if (!xs || xs->in_thd)
my_error(ER_XAER_NOTA, MYF(0));
else
+ {
+ ha_commit_or_rollback_by_xid(thd->lex->xid, 1);
+ xid_cache_delete(xs);
send_ok(thd);
+ }
break;
}
- if (thd->transaction.xa_state == XA_IDLE &&
+ if (thd->transaction.xid_state.xa_state == XA_IDLE &&
thd->lex->xa_opt == XA_ONE_PHASE)
{
int r;
@@ -4601,7 +4636,7 @@
else
send_ok(thd);
}
- else if (thd->transaction.xa_state == XA_PREPARED &&
+ else if (thd->transaction.xid_state.xa_state == XA_PREPARED &&
thd->lex->xa_opt == XA_NONE)
{
if (wait_if_global_read_lock(thd, 0, 0))
@@ -4621,27 +4656,33 @@
else
{
my_error(ER_XAER_RMFAIL, MYF(0),
- xa_state_names[thd->transaction.xa_state]);
+ xa_state_names[thd->transaction.xid_state.xa_state]);
break;
}
thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE);
thd->server_status&= ~SERVER_STATUS_IN_TRANS;
- thd->transaction.xa_state=XA_NOTR;
+ xid_cache_delete(&thd->transaction.xid_state);
+ thd->transaction.xid_state.xa_state=XA_NOTR;
break;
case SQLCOM_XA_ROLLBACK:
- if (!thd->transaction.xid.eq(thd->lex->xid))
+ if (!thd->transaction.xid_state.xid.eq(thd->lex->xid))
{
- if (!(res= !ha_commit_or_rollback_by_xid(thd->lex->xid, 0)))
+ XID_STATE *xs=xid_cache_search(thd->lex->xid);
+ if (!xs || xs->in_thd)
my_error(ER_XAER_NOTA, MYF(0));
else
+ {
+ ha_commit_or_rollback_by_xid(thd->lex->xid, 0);
+ xid_cache_delete(xs);
send_ok(thd);
+ }
break;
}
- if (thd->transaction.xa_state != XA_IDLE &&
- thd->transaction.xa_state != XA_PREPARED)
+ if (thd->transaction.xid_state.xa_state != XA_IDLE &&
+ thd->transaction.xid_state.xa_state != XA_PREPARED)
{
my_error(ER_XAER_RMFAIL, MYF(0),
- xa_state_names[thd->transaction.xa_state]);
+ xa_state_names[thd->transaction.xid_state.xa_state]);
break;
}
if (ha_rollback(thd))
@@ -4650,7 +4691,8 @@
send_ok(thd);
thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE);
thd->server_status&= ~SERVER_STATUS_IN_TRANS;
- thd->transaction.xa_state=XA_NOTR;
+ xid_cache_delete(&thd->transaction.xid_state);
+ thd->transaction.xid_state.xa_state=XA_NOTR;
break;
case SQLCOM_XA_RECOVER:
res= mysql_xa_recover(thd);
@@ -5173,17 +5215,21 @@
DBUG_ENTER("mysql_reset_thd_for_next_command");
thd->free_list= 0;
thd->select_number= 1;
- thd->total_warn_count=0; // Warnings for this query
thd->last_insert_id_used= thd->query_start_used= thd->insert_id_used=0;
- thd->sent_row_count= thd->examined_row_count= 0;
- thd->is_fatal_error= thd->rand_used= thd->time_zone_used= 0;
+ thd->is_fatal_error= thd->time_zone_used= 0;
thd->server_status&= ~ (SERVER_MORE_RESULTS_EXISTS |
SERVER_QUERY_NO_INDEX_USED |
SERVER_QUERY_NO_GOOD_INDEX_USED);
thd->tmp_table_used= 0;
- if (opt_bin_log)
- reset_dynamic(&thd->user_var_events);
- thd->clear_error();
+ if (!thd->in_sub_stmt)
+ {
+ if (opt_bin_log)
+ reset_dynamic(&thd->user_var_events);
+ thd->clear_error();
+ thd->total_warn_count=0; // Warnings for this query
+ thd->rand_used= 0;
+ thd->sent_row_count= thd->examined_row_count= 0;
+ }
DBUG_VOID_RETURN;
}
@@ -5212,9 +5258,9 @@
if (!(select_lex= new (thd->mem_root) SELECT_LEX()))
DBUG_RETURN(1);
select_lex->select_number= ++thd->select_number;
+ select_lex->parent_lex= lex; /* Used in init_query. */
select_lex->init_query();
select_lex->init_select();
- select_lex->parent_lex= lex;
/*
Don't evaluate this subquery during statement prepare even if
it's a constant one. The flag is switched off in the end of
@@ -5272,6 +5318,7 @@
fake->include_standalone(unit,
(SELECT_LEX_NODE**)&unit->fake_select_lex);
fake->select_number= INT_MAX;
+ fake->parent_lex= lex; /* Used in init_query. */
fake->make_empty_select();
fake->linkage= GLOBAL_OPTIONS_TYPE;
fake->select_limit= 0;
@@ -5280,6 +5327,11 @@
/* allow item list resolving in fake select for ORDER BY */
fake->context.resolve_in_select_list= TRUE;
fake->context.select_lex= fake;
+ /*
+ Remove the name resolution context of the fake select from the
+ context stack.
+ */
+ lex->pop_context();
}
select_lex->context.outer_context= outer_context;
}
@@ -5328,10 +5380,12 @@
We set the name of Item to @@session.var_name because that then is used
as the column name in the output.
*/
- var= get_system_var(thd, OPT_SESSION, tmp, null_lex_string);
- end= strxmov(buff, "@@session.", var_name, NullS);
- var->set_name(buff, end-buff, system_charset_info);
- add_item_to_list(thd, var);
+ if ((var= get_system_var(thd, OPT_SESSION, tmp, null_lex_string)))
+ {
+ end= strxmov(buff, "@@session.", var_name, NullS);
+ var->set_name(buff, end-buff, system_charset_info);
+ add_item_to_list(thd, var);
+ }
DBUG_VOID_RETURN;
}
@@ -5357,11 +5411,12 @@
void mysql_parse(THD *thd, char *inBuf, uint length)
{
DBUG_ENTER("mysql_parse");
-
mysql_init_query(thd, (uchar*) inBuf, length);
if (query_cache_send_result_to_client(thd, inBuf, length) <= 0)
{
LEX *lex= thd->lex;
+ sp_cache_flush_obsolete(&thd->sp_proc_cache);
+ sp_cache_flush_obsolete(&thd->sp_func_cache);
if (!yyparse((void *)thd) && ! thd->is_fatal_error)
{
#ifndef NO_EMBEDDED_ACCESS_CHECKS
@@ -5829,7 +5884,7 @@
new_field->length= 1;
if (new_field->length > MAX_BIT_FIELD_LENGTH)
{
- my_error(ER_TOO_BIG_FIELDLENGTH, MYF(0), field_name,
+ my_error(ER_TOO_BIG_DISPLAYWIDTH, MYF(0), field_name,
MAX_BIT_FIELD_LENGTH);
DBUG_RETURN(NULL);
}
@@ -5848,7 +5903,10 @@
type != MYSQL_TYPE_STRING &&
type != MYSQL_TYPE_VARCHAR && type != FIELD_TYPE_GEOMETRY)))
{
- my_error(ER_TOO_BIG_FIELDLENGTH, MYF(0),
+ my_error((type == MYSQL_TYPE_VAR_STRING || type == MYSQL_TYPE_VARCHAR ||
+ type == MYSQL_TYPE_STRING) ? ER_TOO_BIG_FIELDLENGTH :
+ ER_TOO_BIG_DISPLAYWIDTH,
+ MYF(0),
field_name, max_field_charlength); /* purecov: inspected */
DBUG_RETURN(NULL);
}
@@ -5967,9 +6025,11 @@
LEX_STRING *option)
{
register TABLE_LIST *ptr;
+ TABLE_LIST *previous_table_ref; /* The table preceding the current one. */
char *alias_str;
LEX *lex= thd->lex;
DBUG_ENTER("add_table_to_list");
+ LINT_INIT(previous_table_ref);
if (!table)
DBUG_RETURN(0); // End of memory
@@ -6062,8 +6122,34 @@
}
}
}
- /* Link table in local list (list for current select) */
+ /* Store the table reference preceding the current one. */
+ if (table_list.elements > 0)
+ {
+ /*
+ table_list.next points to the last inserted TABLE_LIST->next_local'
+ element
+ */
+ previous_table_ref= (TABLE_LIST*) (table_list.next -
+ offsetof(TABLE_LIST, next_local));
+ DBUG_ASSERT(previous_table_ref);
+ /*
+ Set next_name_resolution_table of the previous table reference to point
+ to the current table reference. In effect the list
+ TABLE_LIST::next_name_resolution_table coincides with
+ TABLE_LIST::next_local. Later this may be changed in
+ store_top_level_join_columns() for NATURAL/USING joins.
+ */
+ previous_table_ref->next_name_resolution_table= ptr;
+ }
+
+ /*
+ Link the current table reference in a local list (list for current select).
+ Notice that as a side effect here we set the next_local field of the
+ previous table reference to 'ptr'. Here we also add one element to the
+ list 'table_list'.
+ */
table_list.link_in_list((byte*) ptr, (byte**) &ptr->next_local);
+ ptr->next_name_resolution_table= NULL;
/* Link table in global list (all used tables) */
lex->add_to_query_tables(ptr);
DBUG_RETURN(ptr);
@@ -6097,10 +6183,12 @@
NESTED_JOIN *nested_join;
DBUG_ENTER("init_nested_join");
- if (!(ptr = (TABLE_LIST *) thd->calloc(sizeof(TABLE_LIST))) ||
- !(nested_join= ptr->nested_join=
- (NESTED_JOIN *) thd->calloc(sizeof(NESTED_JOIN))))
+ if (!(ptr= (TABLE_LIST*) thd->calloc(ALIGN_SIZE(sizeof(TABLE_LIST))+
+ sizeof(NESTED_JOIN))))
DBUG_RETURN(1);
+ nested_join= ptr->nested_join=
+ ((NESTED_JOIN*) ((byte*) ptr + ALIGN_SIZE(sizeof(TABLE_LIST))));
+
join_list->push_front(ptr);
ptr->embedding= embedding;
ptr->join_list= join_list;
@@ -6168,30 +6256,48 @@
The function nest last join operation as if it was enclosed in braces.
RETURN VALUE
- Pointer to TABLE_LIST element created for the new nested join, if success
- 0, otherwise
+ 0 Error
+ # Pointer to TABLE_LIST element created for the new nested join
+
*/
TABLE_LIST *st_select_lex::nest_last_join(THD *thd)
{
TABLE_LIST *ptr;
NESTED_JOIN *nested_join;
+ List<TABLE_LIST> *embedded_list;
DBUG_ENTER("nest_last_join");
- if (!(ptr = (TABLE_LIST *) thd->calloc(sizeof(TABLE_LIST))) ||
- !(nested_join= ptr->nested_join=
- (NESTED_JOIN *) thd->calloc(sizeof(NESTED_JOIN))))
+ if (!(ptr= (TABLE_LIST*) thd->calloc(ALIGN_SIZE(sizeof(TABLE_LIST))+
+ sizeof(NESTED_JOIN))))
DBUG_RETURN(0);
+ nested_join= ptr->nested_join=
+ ((NESTED_JOIN*) ((byte*) ptr + ALIGN_SIZE(sizeof(TABLE_LIST))));
+
ptr->embedding= embedding;
ptr->join_list= join_list;
- List<TABLE_LIST> *embedded_list= &nested_join->join_list;
+ embedded_list= &nested_join->join_list;
embedded_list->empty();
- for (int i=0; i < 2; i++)
+
+ for (uint i=0; i < 2; i++)
{
TABLE_LIST *table= join_list->pop();
table->join_list= embedded_list;
table->embedding= ptr;
embedded_list->push_back(table);
+ if (table->natural_join)
+ {
+ ptr->is_natural_join= TRUE;
+ /*
+ If this is a JOIN ... USING, move the list of joined fields to the
+ table reference that describes the join.
+ */
+ if (table->join_using_fields)
+ {
+ ptr->join_using_fields= table->join_using_fields;
+ table->join_using_fields= NULL;
+ }
+ }
}
join_list->push_front(ptr);
nested_join->used_tables= nested_join->not_null_tables= (table_map) 0;
@@ -6200,44 +6306,6 @@
/*
- Save names for a join with using clause
-
- SYNOPSIS
- save_names_for_using_list
- tab1 left table in join
- tab2 right table in join
-
- DESCRIPTION
- The function saves the full names of the tables in st_select_lex
- to be able to build later an on expression to replace the using clause.
-
- RETURN VALUE
- None
-*/
-
-void st_select_lex::save_names_for_using_list(TABLE_LIST *tab1,
- TABLE_LIST *tab2)
-{
- while (tab1->nested_join)
- {
- tab1= tab1->nested_join->join_list.head();
- }
- db1= tab1->db;
- table1= tab1->alias;
- while (tab2->nested_join)
- {
- TABLE_LIST *next;
- List_iterator_fast<TABLE_LIST> it(tab2->nested_join->join_list);
- tab2= it++;
- while ((next= it++))
- tab2= next;
- }
- db2= tab2->db;
- table2= tab2->alias;
-}
-
-
-/*
Add a table to the current join list
SYNOPSIS
@@ -6340,16 +6408,70 @@
}
-void add_join_on(TABLE_LIST *b,Item *expr)
+/*
+ Create a new name resolution context for a JOIN ... ON clause.
+
+ SYNOPSIS
+ make_join_on_context()
+ thd pointer to current thread
+ left_op lefto operand of the JOIN
+ right_op rigth operand of the JOIN
+
+ DESCRIPTION
+ Create a new name resolution context for a JOIN ... ON clause,
+ and set the first and last leaves of the list of table references
+ to be used for name resolution.
+
+ RETURN
+ A new context if all is OK
+ NULL - if a memory allocation error occured
+*/
+
+Name_resolution_context *
+make_join_on_context(THD *thd, TABLE_LIST *left_op, TABLE_LIST *right_op)
+{
+ Name_resolution_context *on_context;
+ if (!(on_context= new (thd->mem_root) Name_resolution_context))
+ return NULL;
+ on_context->init();
+ on_context->first_name_resolution_table=
+ left_op->first_leaf_for_name_resolution();
+ on_context->last_name_resolution_table=
+ right_op->last_leaf_for_name_resolution();
+ return on_context;
+}
+
+
+/*
+ Add an ON condition to the second operand of a JOIN ... ON.
+
+ SYNOPSIS
+ add_join_on
+ b the second operand of a JOIN ... ON
+ expr the condition to be added to the ON clause
+
+ DESCRIPTION
+ Add an ON condition to the right operand of a JOIN ... ON clause.
+
+ RETURN
+ FALSE if there was some error
+ TRUE if all is OK
+*/
+
+void add_join_on(TABLE_LIST *b, Item *expr)
{
if (expr)
{
if (!b->on_expr)
- b->on_expr=expr;
+ b->on_expr= expr;
else
{
- /* This only happens if you have both a right and left join */
- b->on_expr=new Item_cond_and(b->on_expr,expr);
+ /*
+ If called from the parser, this happens if you have both a
+ right and left join. If called later, it happens if we add more
+ than one condition to the ON clause.
+ */
+ b->on_expr= new Item_cond_and(b->on_expr,expr);
}
b->on_expr->top_level_item();
}
@@ -6357,46 +6479,67 @@
/*
- Mark that we have a NATURAL JOIN between two tables
+ Mark that there is a NATURAL JOIN or JOIN ... USING between two
+ tables.
SYNOPSIS
add_join_natural()
- a Table to do normal join with
- b Do normal join with this table
-
+ a Left join argument
+ b Right join argument
+ using_fields Field names from USING clause
+
IMPLEMENTATION
- This function just marks that table b should be joined with a.
- The function setup_cond() will create in b->on_expr a list
- of equal condition between all fields of the same name.
+ This function marks that table b should be joined with a either via
+ a NATURAL JOIN or via JOIN ... USING. Both join types are special
+ cases of each other, so we treat them together. The function
+ setup_conds() creates a list of equal condition between all fields
+ of the same name for NATURAL JOIN or the fields in 'using_fields'
+ for JOIN ... USING. The list of equality conditions is stored
+ either in b->on_expr, or in JOIN::conds, depending on whether there
+ was an outer join.
+ EXAMPLE
SELECT * FROM t1 NATURAL LEFT JOIN t2
<=>
SELECT * FROM t1 LEFT JOIN t2 ON (t1.i=t2.i and t1.j=t2.j ... )
+
+ SELECT * FROM t1 NATURAL JOIN t2 WHERE <some_cond>
+ <=>
+ SELECT * FROM t1, t2 WHERE (t1.i=t2.i and t1.j=t2.j and <some_cond>)
+
+ SELECT * FROM t1 JOIN t2 USING(j) WHERE <some_cond>
+ <=>
+ SELECT * FROM t1, t2 WHERE (t1.j=t2.j and <some_cond>)
+
+ RETURN
+ None
*/
-void add_join_natural(TABLE_LIST *a,TABLE_LIST *b)
+void add_join_natural(TABLE_LIST *a, TABLE_LIST *b, List<String> *using_fields)
{
- b->natural_join=a;
+ b->natural_join= a;
+ b->join_using_fields= using_fields;
}
+
/*
Reload/resets privileges and the different caches.
SYNOPSIS
reload_acl_and_cache()
- thd Thread handler
+ thd Thread handler (can be NULL!)
options What should be reset/reloaded (tables, privileges,
slave...)
tables Tables to flush (if any)
write_to_binlog Depending on 'options', it may be very bad to write the
query to the binlog (e.g. FLUSH SLAVE); this is a
- pointer where, if it is not NULL, reload_acl_and_cache()
- will put 0 if it thinks we really should not write to
- the binlog. Otherwise it will put 1.
+ pointer where reload_acl_and_cache() will put 0 if
+ it thinks we really should not write to the binlog.
+ Otherwise it will put 1.
RETURN
0 ok
- !=0 error
+ !=0 error. thd->killed or thd->net.report_error is set
*/
bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
@@ -6405,6 +6548,13 @@
bool result=0;
select_errors=0; /* Write if more errors */
bool tmp_write_to_binlog= 1;
+
+ if (thd && thd->in_sub_stmt)
+ {
+ my_error(ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0), "FLUSH");
+ return 1;
+ }
+
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (options & REFRESH_GRANT)
{
@@ -6460,15 +6610,34 @@
if ((options & REFRESH_READ_LOCK) && thd)
{
/*
+ We must not try to aspire a global read lock if we have a write
+ locked table. This would lead to a deadlock when trying to
+ reopen (and re-lock) the table after the flush.
+ */
+ if (thd->locked_tables)
+ {
+ THR_LOCK_DATA **lock_p= thd->locked_tables->locks;
+ THR_LOCK_DATA **end_p= lock_p + thd->locked_tables->lock_count;
+
+ for (; lock_p < end_p; lock_p++)
+ {
+ if ((*lock_p)->type == TL_WRITE)
+ {
+ my_error(ER_LOCK_OR_ACTIVE_TRANSACTION, MYF(0));
+ return 1;
+ }
+ }
+ }
+ /*
Writing to the binlog could cause deadlocks, as we don't log
UNLOCK TABLES
*/
tmp_write_to_binlog= 0;
if (lock_global_read_lock(thd))
- return 1;
+ return 1; // Killed
result=close_cached_tables(thd,(options & REFRESH_FAST) ? 0 : 1,
tables);
- if (make_global_read_lock_block_commit(thd))
+ if (make_global_read_lock_block_commit(thd)) // Killed
{
/* Don't leave things in a half-locked state */
unlock_global_read_lock(thd);
@@ -6490,7 +6659,10 @@
{
tmp_write_to_binlog= 0;
if (reset_master(thd))
+ {
result=1;
+ thd->fatal_error(); // Ensure client get error
+ }
}
#endif
#ifdef OPENSSL
@@ -6512,8 +6684,7 @@
#endif
if (options & REFRESH_USER_RESOURCES)
reset_mqh((LEX_USER *) NULL);
- if (write_to_binlog)
- *write_to_binlog= tmp_write_to_binlog;
+ *write_to_binlog= tmp_write_to_binlog;
return result;
}
--- 1.327/sql/sql_select.cc 2005-08-09 09:49:34 +02:00
+++ 1.328/sql/sql_select.cc 2005-08-27 07:49:56 +02:00
@@ -338,7 +338,7 @@
/* Check that all tables, fields, conds and order are ok */
if ((!(select_options & OPTION_SETUP_TABLES_DONE) &&
- setup_tables(thd, &select_lex->context,
+ setup_tables(thd, &select_lex->context, join_list,
tables_list, &conds, &select_lex->leaf_tables,
FALSE)) ||
setup_wild(thd, tables_list, fields_list, &all_fields, wild_num) ||
@@ -1086,9 +1086,10 @@
order=0;
}
}
-
- if (thd->lex->subqueries)
+
+ if (select_lex->uncacheable && !is_top_level_join())
{
+ /* If this join belongs to an uncacheable subquery */
if (!(tmp_join= (JOIN*)thd->alloc(sizeof(JOIN))))
DBUG_RETURN(-1);
error= 0; // Ensure that tmp_join.error= 0
@@ -1282,7 +1283,15 @@
if (need_tmp)
{
if (tmp_join)
+ {
+ /*
+ We are in a non cacheable sub query. Get the saved join structure
+ after optimization.
+ (curr_join may have been modified during last exection and we need
+ to reset it)
+ */
curr_join= tmp_join;
+ }
curr_tmp_table= exec_tmp_table1;
/* Copy data to the temporary table */
@@ -1576,7 +1585,8 @@
curr_join->tmp_having= make_cond_for_table(curr_join->tmp_having,
~ (table_map) 0,
~used_tables);
- DBUG_EXECUTE("where",print_where(conds,"having after sort"););
+ DBUG_EXECUTE("where",print_where(curr_join->tmp_having,
+ "having after sort"););
}
}
{
@@ -1647,9 +1657,7 @@
curr_join->fields= curr_fields_list;
curr_join->procedure= procedure;
- if (unit == &thd->lex->unit &&
- (unit->fake_select_lex == 0 || select_lex == unit->fake_select_lex) &&
- thd->cursor && tables != const_tables)
+ if (is_top_level_join() && thd->cursor && tables != const_tables)
{
/*
We are here if this is JOIN::exec for the last select of the main unit
@@ -1726,6 +1734,7 @@
Cursor::Cursor(THD *thd)
:Query_arena(&main_mem_root, INITIALIZED),
join(0), unit(0),
+ protocol(thd),
close_at_commit(FALSE)
{
/* We will overwrite it at open anyway. */
@@ -8142,7 +8151,7 @@
TABLE *
create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
ORDER *group, bool distinct, bool save_sum_fields,
- ulong select_options, ha_rows rows_limit,
+ ulonglong select_options, ha_rows rows_limit,
char *table_alias)
{
TABLE *table;
@@ -8400,7 +8409,7 @@
/* If result table is small; use a heap */
if (blob_count || using_unique_constraint ||
(select_options & (OPTION_BIG_TABLES | SELECT_SMALL_RESULT)) ==
- OPTION_BIG_TABLES)
+ OPTION_BIG_TABLES || (select_options & TMP_TABLE_FORCE_MYISAM))
{
table->file=get_new_handler(table,table->s->db_type= DB_TYPE_MYISAM);
if (group &&
@@ -11934,13 +11943,14 @@
SYNOPSIS
find_order_in_list()
- thd Pointer to current thread structure
- ref_pointer_array All select, group and order by fields
- tables List of tables to search in (usually FROM clause)
- order Column reference to be resolved
- fields List of fields to search in (usually SELECT list)
- all_fields All select, group and order by fields
- is_group_field True if order is a GROUP field, false if ORDER by field
+ thd [in] Pointer to current thread structure
+ ref_pointer_array [in/out] All select, group and order by fields
+ tables [in] List of tables to search in (usually FROM clause)
+ order [in] Column reference to be resolved
+ fields [in] List of fields to search in (usually SELECT list)
+ all_fields [in/out] All select, group and order by fields
+ is_group_field [in] True if order is a GROUP field, false if
+ ORDER by field
DESCRIPTION
Given a column reference (represented by 'order') from a GROUP BY or ORDER
@@ -12016,7 +12026,7 @@
order_item_type == Item::REF_ITEM)
{
from_field= find_field_in_tables(thd, (Item_ident*) order_item, tables,
- &view_ref, IGNORE_ERRORS, TRUE,
+ NULL, &view_ref, IGNORE_ERRORS, TRUE,
FALSE);
if (!from_field)
from_field= (Field*) not_found_field;
@@ -12250,9 +12260,7 @@
li.rewind();
while ((item=li++))
{
- if (item->const_item() || item->with_sum_func)
- continue;
- if (!item->marker)
+ if (!item->const_item() && !item->with_sum_func && !item->marker)
{
ORDER *ord=(ORDER*) thd->calloc(sizeof(ORDER));
if (!ord)
--- 1.229/sql/sql_table.cc 2005-08-09 09:49:34 +02:00
+++ 1.230/sql/sql_table.cc 2005-08-27 07:49:57 +02:00
@@ -45,6 +45,64 @@
static bool check_engine(THD *thd, const char *table_name,
enum db_type *new_engine);
+/*
+ SYNOPSIS
+ write_bin_log()
+ thd Thread object
+ clear_error is clear_error to be called
+ RETURN VALUES
+ NONE
+ DESCRIPTION
+ Write the binlog if open, routine used in multiple places in this
+ file
+*/
+
+static void write_bin_log(THD *thd, bool clear_error)
+{
+ if (mysql_bin_log.is_open())
+ {
+ if (clear_error)
+ thd->clear_error();
+ Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE);
+ mysql_bin_log.write(&qinfo);
+ }
+}
+
+/*
+ SYNOPSIS
+ abort_and_upgrade_lock()
+ thd Thread object
+ table Table object
+ db Database name
+ table_name Table name
+ old_lock_level Old lock level
+ RETURN VALUES
+ TRUE Failure
+ FALSE Success
+ DESCRIPTION
+ Remember old lock level (for possible downgrade later on), abort all
+ waiting threads and ensure that all keeping locks currently are
+ completed such that we own the lock exclusively and no other interaction
+ is ongoing.
+*/
+
+static bool abort_and_upgrade_lock(THD *thd, TABLE *table, const char *db,
+ const char *table_name,
+ uint *old_lock_level)
+{
+ uint flags= RTFC_WAIT_OTHER_THREAD_FLAG | RTFC_CHECK_KILLED_FLAG;
+ DBUG_ENTER("abort_and_upgrade_locks");
+
+ *old_lock_level= table->reginfo.lock_type;
+ mysql_lock_abort(thd, table);
+ VOID(remove_table_from_cache(thd, db, table_name, flags));
+ if (thd->killed)
+ {
+ thd->no_warnings_for_error= 0;
+ DBUG_RETURN(TRUE);
+ }
+ DBUG_RETURN(FALSE);
+}
/*
Build the path to a file for a table (or the base path that can
@@ -230,6 +288,7 @@
for (table= tables; table; table= table->next_local)
{
char *db=table->db;
+ table->was_dropped= 0;
mysql_ha_flush(thd, table, MYSQL_HA_CLOSE_FINAL);
if (!close_temporary_table(thd, db, table->table_name))
{
@@ -301,6 +360,8 @@
wrong_tables.append(',');
wrong_tables.append(String(table->table_name,system_charset_info));
}
+ else
+ table->was_dropped= 1;
}
thd->tmp_table_used= tmp_table_deleted;
error= 0;
@@ -2784,12 +2845,7 @@
}
// Must be written before unlock
- if (mysql_bin_log.is_open())
- {
- thd->clear_error();
- Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE);
- mysql_bin_log.write(&qinfo);
- }
+ write_bin_log(thd, TRUE);
res= FALSE;
goto err;
@@ -2895,11 +2951,7 @@
error=1;
if (error)
goto err;
- if (mysql_bin_log.is_open())
- {
- Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE);
- mysql_bin_log.write(&qinfo);
- }
+ write_bin_log(thd, FALSE);
err:
close_thread_tables(thd);
thd->tablespace_op=FALSE;
@@ -3301,7 +3353,10 @@
enum db_type old_db_type,new_db_type;
uint need_copy_table= 0;
#ifdef HAVE_PARTITION_DB
+ bool online_add_empty_partition= FALSE;
+ bool online_drop_partition= FALSE;
bool partition_changed= FALSE;
+ enum db_type default_engine_type;
#endif
DBUG_ENTER("mysql_alter_table");
@@ -3378,66 +3433,421 @@
old_db_type= table->s->db_type;
if (create_info->db_type == DB_TYPE_DEFAULT)
create_info->db_type= old_db_type;
+
#ifdef HAVE_PARTITION_DB
/*
- When thd->lex->part_info has a reference to a partition_info the
- ALTER TABLE contained a definition of a partitioning.
-
- Case I:
- If there was a partition before and there is a new one defined.
- We use the new partitioning. The new partitioning is already
- defined in the correct variable so no work is needed to
- accomplish this.
- We do however need to update partition_changed to ensure that not
- only the frm file is changed in the ALTER TABLE command.
-
- Case IIa:
- There was a partitioning before and there is no new one defined.
- Also the user has not specified an explicit engine to use.
-
- We use the old partitioning also for the new table. We do this
- by assigning the partition_info from the table loaded in
- open_ltable to the partition_info struct used by mysql_create_table
- later in this method.
-
- Case IIb:
- There was a partitioning before and there is no new one defined.
- The user has specified an explicit engine to use.
-
- Since the user has specified an explicit engine to use we override
- the old partitioning info and create a new table using the specified
- engine. This is the reason for the extra check if old and new engine
- is equal.
- In this case the partition also is changed.
-
- Case III:
- There was no partitioning before altering the table, there is
- partitioning defined in the altered table. Use the new partitioning.
- No work needed since the partitioning info is already in the
- correct variable.
- Also here partition has changed and thus a new table must be
- created.
-
- Case IV:
- There was no partitioning before and no partitioning defined. Obviously
- no work needed.
- */
- if (table->s->part_info)
- {
- if (!thd->lex->part_info &&
- create_info->db_type == old_db_type)
- thd->lex->part_info= table->s->part_info;
- }
- if (thd->lex->part_info)
+ We need to handle both partition management command such as Add Partition
+ and others here as well as an ALTER TABLE that completely changes the
+ partitioning and yet others that don't change anything at all. We start
+ by checking the partition management variants and then check the general
+ change patterns.
+ */
+ if (alter_info->flags & (ALTER_ADD_PARTITION +
+ ALTER_DROP_PARTITION + ALTER_COALESCE_PARTITION +
+ ALTER_REORGANISE_PARTITION))
{
+ partition_info *tab_part_info= table->s->part_info;
+ if (!tab_part_info)
+ {
+ my_error(ER_PARTITION_MGMT_ON_NONPARTITIONED, MYF(0));
+ DBUG_RETURN(TRUE);
+ }
+ {
+ List_iterator<partition_element> t_it(tab_part_info->partitions);
+ partition_element *t_part_elem= t_it++;
+ if (is_sub_partitioned(tab_part_info))
+ {
+ List_iterator<partition_element> s_it(t_part_elem->subpartitions);
+ t_part_elem= s_it++;
+ }
+ default_engine_type= t_part_elem->engine_type;
+ }
/*
- Need to cater for engine types that can handle partition without
- using the partition handler.
+ We are going to manipulate the partition info on the table object
+ so we need to ensure that the data structure of the table object
+ is freed by setting version to 0.
*/
- if (thd->lex->part_info != table->s->part_info)
- partition_changed= TRUE;
- thd->lex->part_info->default_engine_type= create_info->db_type;
+ table->s->version= 0L;
+ if (alter_info->flags == ALTER_ADD_PARTITION)
+ {
+ /*
+ We start by moving the new partitions to the list of temporary
+ partitions. We will then check that the new partitions fit in the
+ partitioning scheme as currently set-up.
+ Partitions are always added at the end in ADD PARTITION.
+ */
+ partition_info *alt_part_info= thd->lex->part_info;
+ uint no_new_partitions= alt_part_info->no_parts;
+ uint no_orig_partitions= tab_part_info->no_parts;
+ uint check_total_partitions= no_new_partitions + no_orig_partitions;
+ uint new_total_partitions= check_total_partitions;
+ /*
+ We allow quite a lot of values to be supplied by defaults, however we
+ must know the number of new partitions in this case.
+ */
+ if (no_new_partitions == 0)
+ {
+ my_error(ER_ADD_PARTITION_NO_NEW_PARTITION, MYF(0));
+ DBUG_RETURN(TRUE);
+ }
+ if (is_sub_partitioned(tab_part_info))
+ {
+ if (alt_part_info->no_subparts == 0)
+ alt_part_info->no_subparts= tab_part_info->no_subparts;
+ else if (alt_part_info->no_subparts != tab_part_info->no_subparts)
+ {
+ my_error(ER_ADD_PARTITION_SUBPART_ERROR, MYF(0));
+ DBUG_RETURN(TRUE);
+ }
+ check_total_partitions= new_total_partitions*
+ alt_part_info->no_subparts;
+ }
+ if (check_total_partitions > MAX_PARTITIONS)
+ {
+ my_error(ER_TOO_MANY_PARTITIONS_ERROR, MYF(0));
+ DBUG_RETURN(TRUE);
+ }
+ alt_part_info->part_type= tab_part_info->part_type;
+ if (set_up_defaults_for_partitioning(alt_part_info,
+ table->file,
+ (ulonglong)0ULL,
+ tab_part_info->no_parts))
+ {
+ DBUG_RETURN(TRUE);
+ }
+ /*
+ Need to concatenate the lists here to make it possible to check the
+ partition info for correctness using check_partition_info
+ */
+ {
+ List_iterator<partition_element> alt_it(alt_part_info->partitions);
+ uint part_count= 0;
+ do
+ {
+ partition_element *part_elem= alt_it++;
+ tab_part_info->partitions.push_back(part_elem);
+ tab_part_info->temp_partitions.push_back(part_elem);
+ } while (++part_count < no_new_partitions);
+ tab_part_info->no_parts+= no_new_partitions;
+ }
+ {
+ List_iterator<partition_element> tab_it(tab_part_info->partitions);
+ partition_element *part_elem= tab_it++;
+ if (is_sub_partitioned(tab_part_info))
+ {
+ List_iterator<partition_element> sub_it(part_elem->subpartitions);
+ part_elem= sub_it++;
+ }
+ if (check_partition_info(tab_part_info, part_elem->engine_type,
+ table->file, (ulonglong)0ULL))
+ {
+ DBUG_RETURN(TRUE);
+ }
+ }
+ create_info->db_type= DB_TYPE_PARTITION_DB;
+ thd->lex->part_info= tab_part_info;
+ if (table->file->alter_table_flags() & HA_ONLINE_ADD_EMPTY_PARTITION &&
+ (tab_part_info->part_type == RANGE_PARTITION ||
+ tab_part_info->part_type == LIST_PARTITION))
+ {
+ /*
+ For range and list partitions add partition is simply adding a new
+ empty partition to the table. If the handler support this we will
+ use the simple method of doing this. In this case we need to break
+ out the new partitions from the list again and only keep them in the
+ temporary list. Added partitions are always added at the end.
+ */
+ {
+ List_iterator<partition_element> tab_it(tab_part_info->partitions);
+ uint part_count= 0;
+ do
+ {
+ tab_it++;
+ } while (++part_count < no_orig_partitions);
+ do
+ {
+ tab_it++;
+ tab_it.remove();
+ } while (++part_count < new_total_partitions);
+ }
+ tab_part_info->no_parts-= no_new_partitions;
+ online_add_empty_partition= TRUE;
+ }
+ else
+ {
+ tab_part_info->temp_partitions.empty();
+ }
+ }
+ else if (alter_info->flags == ALTER_DROP_PARTITION)
+ {
+ /*
+ Drop a partition from a range partition and list partitioning is
+ always safe and can be made more or less immediate. It is necessary
+ however to ensure that the partition to be removed is safely removed
+ and that REPAIR TABLE can remove the partition if for some reason the
+ command to drop the partition failed in the middle.
+ */
+ uint part_count= 0;
+ uint no_parts_dropped= alter_info->partition_names.elements;
+ uint no_parts_found= 0;
+ List_iterator<partition_element> part_it(tab_part_info->partitions);
+ if (!(tab_part_info->part_type == RANGE_PARTITION ||
+ tab_part_info->part_type == LIST_PARTITION))
+ {
+ my_error(ER_ONLY_ON_RANGE_LIST_PARTITION, MYF(0), "DROP");
+ DBUG_RETURN(TRUE);
+ }
+ if (no_parts_dropped >= tab_part_info->no_parts)
+ {
+ my_error(ER_DROP_LAST_PARTITION, MYF(0));
+ DBUG_RETURN(TRUE);
+ }
+ do
+ {
+ partition_element *part_elem= part_it++;
+ if (is_partition_in_list(part_elem->partition_name,
+ alter_info->partition_names))
+ {
+ /*
+ Remove the partition from the list and put it instead in the
+ list of temporary partitions with a new state.
+ */
+ no_parts_found++;
+ part_elem->part_state= PART_IS_DROPPED;
+ }
+ } while (++part_count < tab_part_info->no_parts);
+ if (no_parts_found != no_parts_dropped)
+ {
+ my_error(ER_DROP_PARTITION_NON_EXISTENT, MYF(0));
+ DBUG_RETURN(TRUE);
+ }
+ if (!(table->file->alter_table_flags() & HA_ONLINE_DROP_PARTITION))
+ {
+ my_error(ER_DROP_PARTITION_FAILURE, MYF(0));
+ DBUG_RETURN(TRUE);
+ }
+ if (table->file->is_fk_defined_on_table_or_index(MAX_KEY))
+ {
+ my_error(ER_DROP_PARTITION_WHEN_FK_DEFINED, MYF(0));
+ DBUG_RETURN(TRUE);
+ }
+ /*
+ This code needs set-up of structures needed by mysql_create_table
+ before it is called and thus we only set a boolean variable to be
+ checked later down in the code when all needed data structures are
+ prepared.
+ */
+ online_drop_partition= TRUE;
+ }
+ else if (alter_info->flags == ALTER_COALESCE_PARTITION)
+ {
+ /*
+ In this version COALESCE PARTITION is implemented by simply removing
+ a partition from the table and using the normal ALTER TABLE code
+ and ensuring that copy to a new table occurs. Later on we can optimise
+ this function for Linear Hash partitions. In that case we can avoid
+ reorganising the entire table. For normal hash partitions it will
+ be a complete reorganise anyways so that can only be made on-line
+ if it still uses a copy table.
+ */
+ uint part_count= 0;
+ uint no_parts_coalesced= alter_info->no_parts;
+ uint no_parts_remain= tab_part_info->no_parts - no_parts_coalesced;
+ List_iterator<partition_element> part_it(tab_part_info->partitions);
+ if (tab_part_info->part_type != HASH_PARTITION)
+ {
+ my_error(ER_COALESCE_ONLY_ON_HASH_PARTITION, MYF(0));
+ DBUG_RETURN(TRUE);
+ }
+ if (no_parts_coalesced == 0)
+ {
+ my_error(ER_COALESCE_PARTITION_NO_PARTITION, MYF(0));
+ DBUG_RETURN(TRUE);
+ }
+ if (no_parts_coalesced >= tab_part_info->no_parts)
+ {
+ my_error(ER_DROP_LAST_PARTITION, MYF(0));
+ DBUG_RETURN(TRUE);
+ }
+ do
+ {
+ part_it++;
+ if (++part_count > no_parts_remain)
+ part_it.remove();
+ } while (part_count < tab_part_info->no_parts);
+ tab_part_info->no_parts= no_parts_remain;
+ }
+ else if (alter_info->flags == ALTER_REORGANISE_PARTITION)
+ {
+ /*
+ Reorganise partitions takes a number of partitions that are next
+ to each other (at least for RANGE PARTITIONS) and then uses those
+ to create a set of new partitions. So data is copied from those
+ partitions into the new set of partitions. Those new partitions
+ can have more values in the LIST value specifications or less both
+ are allowed. The ranges can be different but since they are
+ changing a set of consecutive partitions they must cover the same
+ range as those changed from.
+ This command can be used on RANGE and LIST partitions.
+ */
+ uint no_parts_reorged= alter_info->partition_names.elements;
+ uint no_parts_new= thd->lex->part_info->partitions.elements;
+ partition_info *alt_part_info= thd->lex->part_info;
+ uint check_total_partitions;
+ if (no_parts_reorged > tab_part_info->no_parts)
+ {
+ my_error(ER_REORG_PARTITION_NOT_EXIST, MYF(0));
+ DBUG_RETURN(TRUE);
+ }
+ if (!(tab_part_info->part_type == RANGE_PARTITION ||
+ tab_part_info->part_type == LIST_PARTITION))
+ {
+ my_error(ER_ONLY_ON_RANGE_LIST_PARTITION, MYF(0), "REORGANISE");
+ DBUG_RETURN(TRUE);
+ }
+ if (is_partitions_in_table(alt_part_info, tab_part_info))
+ {
+ my_error(ER_SAME_NAME_PARTITION, MYF(0));
+ DBUG_RETURN(TRUE);
+ }
+ check_total_partitions= tab_part_info->no_parts + no_parts_new;
+ check_total_partitions-= no_parts_reorged;
+ if (check_total_partitions > MAX_PARTITIONS)
+ {
+ my_error(ER_TOO_MANY_PARTITIONS_ERROR, MYF(0));
+ DBUG_RETURN(TRUE);
+ }
+ {
+ List_iterator<partition_element> tab_it(tab_part_info->partitions);
+ uint part_count= 0;
+ bool found_first= FALSE, found_last= FALSE;
+ uint drop_count= 0;
+ longlong tab_max_range, alt_max_range;
+ do
+ {
+ partition_element *part_elem= tab_it++;
+ if (is_partition_in_list(part_elem->partition_name,
+ alter_info->partition_names))
+ {
+ drop_count++;
+ tab_max_range= part_elem->range_value;
+ if (!found_first)
+ {
+ uint alt_part_count= 0;
+ found_first= TRUE;
+ List_iterator<partition_element> alt_it(alt_part_info->partitions);
+ do
+ {
+ partition_element *alt_part_elem= alt_it++;
+ alt_max_range= alt_part_elem->range_value;
+ if (alt_part_count == 0)
+ tab_it.replace(alt_part_elem);
+ else
+ tab_it.after(alt_part_elem);
+ } while (++alt_part_count < no_parts_new);
+ }
+ else if (found_last)
+ {
+ my_error(ER_CONSECUTIVE_REORG_PARTITIONS, MYF(0));
+ DBUG_RETURN(TRUE);
+ }
+ else
+ tab_it.remove();
+ }
+ else
+ {
+ if (found_first)
+ found_last= TRUE;
+ }
+ } while (++part_count < tab_part_info->no_parts);
+ if (drop_count != no_parts_reorged)
+ {
+ my_error(ER_DROP_PARTITION_NON_EXISTENT, MYF(0));
+ DBUG_RETURN(TRUE);
+ }
+ if (tab_part_info->part_type == RANGE_PARTITION &&
+ alt_max_range > tab_max_range)
+ {
+ my_error(ER_REORG_OUTSIDE_RANGE, MYF(0));
+ DBUG_RETURN(TRUE);
+ }
+ }
+ }
+ partition_changed= TRUE;
create_info->db_type= DB_TYPE_PARTITION_DB;
+ thd->lex->part_info= tab_part_info;
+ if (alter_info->flags == ALTER_ADD_PARTITION ||
+ alter_info->flags == ALTER_REORGANISE_PARTITION)
+ {
+ if (check_partition_info(tab_part_info, default_engine_type,
+ table->file, (ulonglong)0ULL))
+ {
+ DBUG_RETURN(TRUE);
+ }
+ }
+ }
+ else
+ {
+ /*
+ When thd->lex->part_info has a reference to a partition_info the
+ ALTER TABLE contained a definition of a partitioning.
+
+ Case I:
+ If there was a partition before and there is a new one defined.
+ We use the new partitioning. The new partitioning is already
+ defined in the correct variable so no work is needed to
+ accomplish this.
+ We do however need to update partition_changed to ensure that not
+ only the frm file is changed in the ALTER TABLE command.
+
+ Case IIa:
+ There was a partitioning before and there is no new one defined.
+ Also the user has not specified an explicit engine to use.
+
+ We use the old partitioning also for the new table. We do this
+ by assigning the partition_info from the table loaded in
+ open_ltable to the partition_info struct used by mysql_create_table
+ later in this method.
+
+ Case IIb:
+ There was a partitioning before and there is no new one defined.
+ The user has specified an explicit engine to use.
+
+ Since the user has specified an explicit engine to use we override
+ the old partitioning info and create a new table using the specified
+ engine. This is the reason for the extra check if old and new engine
+ is equal.
+ In this case the partition also is changed.
+
+ Case III:
+ There was no partitioning before altering the table, there is
+ partitioning defined in the altered table. Use the new partitioning.
+ No work needed since the partitioning info is already in the
+ correct variable.
+ Also here partition has changed and thus a new table must be
+ created.
+
+ Case IV:
+ There was no partitioning before and no partitioning defined.
+ Obviously no work needed.
+ */
+ if (table->s->part_info)
+ {
+ if (!thd->lex->part_info &&
+ create_info->db_type == old_db_type)
+ thd->lex->part_info= table->s->part_info;
+ }
+ if (thd->lex->part_info)
+ {
+ /*
+ Need to cater for engine types that can handle partition without
+ using the partition handler.
+ */
+ if (thd->lex->part_info != table->s->part_info)
+ partition_changed= TRUE;
+ thd->lex->part_info->default_engine_type= create_info->db_type;
+ create_info->db_type= DB_TYPE_PARTITION_DB;
+ }
}
#endif
if (check_engine(thd, new_name, &create_info->db_type))
@@ -3503,12 +3913,7 @@
}
if (!error)
{
- if (mysql_bin_log.is_open())
- {
- thd->clear_error();
- Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE);
- mysql_bin_log.write(&qinfo);
- }
+ write_bin_log(thd, TRUE);
if (do_send_ok)
send_ok(thd);
}
@@ -3824,6 +4229,102 @@
if (!need_copy_table)
create_info->frm_only= 1;
+#ifdef HAVE_PARTITION_DB
+ if (partition_changed)
+ {
+ if (online_drop_partition)
+ {
+ /*
+ Now after all checks and setting state on dropped partitions we can
+ start the actual dropping of the partitions.
+ 1) Lock table in TL_WRITE_ONLY to ensure all other accesses on table
+ are completed and no new ones are started until we have changed
+ the frm file.
+ 2) Write the new frm file where state of dropped partitions is
+ changed to PART_IS_DROPPED
+ 3) Perform the actual drop of the partition using the handler of the
+ table.
+ 4) Write a new frm file of the table where the partitions are dropped
+ from the table.
+
+ */
+ uint old_lock_type;
+ partition_info *part_info= table->s->part_info;
+ char path[FN_REFLEN+1];
+ uint db_options= 0, key_count, syntax_len;
+ KEY *key_info_buffer;
+ char *part_syntax_buf;
+
+ VOID(pthread_mutex_lock(&LOCK_open));
+ if (abort_and_upgrade_lock(thd, table, db, table_name, &old_lock_type))
+ {
+ DBUG_RETURN(TRUE);
+ }
+ VOID(pthread_mutex_unlock(&LOCK_open));
+ mysql_prepare_table(thd, create_info, &create_list,
+ &key_list, /*tmp_table*/ 0, &db_options,
+ table->file, &key_info_buffer, &key_count,
+ /*select_field_count*/ 0);
+ if (!(part_syntax_buf= generate_partition_syntax(part_info,
+ &syntax_len,
+ TRUE)))
+ {
+ DBUG_RETURN(TRUE);
+ }
+ part_info->part_info_string= part_syntax_buf;
+ part_info->part_info_len= syntax_len;
+ build_table_path(path, sizeof(path), db, table_name, reg_ext);
+ if (mysql_create_frm(thd, path, db, table_name, create_info,
+ create_list, key_count, key_info_buffer,
+ table->file))
+ {
+ DBUG_RETURN(TRUE);
+ }
+ thd->lex->part_info= part_info;
+ build_table_path(path, sizeof(path), db, table_name, "");
+ if (table->file->drop_partitions(path))
+ {
+ DBUG_RETURN(TRUE);
+ }
+ {
+ List_iterator<partition_element> part_it(part_info->partitions);
+ uint i= 0, remove_count= 0;
+ do
+ {
+ partition_element *part_elem= part_it++;
+ if (is_partition_in_list(part_elem->partition_name,
+ alter_info->partition_names))
+ {
+ part_it.remove();
+ remove_count++;
+ }
+ } while (++i < part_info->no_parts);
+ part_info->no_parts-= remove_count;
+ }
+ if (!(part_syntax_buf= generate_partition_syntax(part_info,
+ &syntax_len,
+ TRUE)))
+ {
+ DBUG_RETURN(TRUE);
+ }
+ part_info->part_info_string= part_syntax_buf;
+ part_info->part_info_len= syntax_len;
+ build_table_path(path, sizeof(path), db, table_name, reg_ext);
+ if (mysql_create_frm(thd, path, db, table_name, create_info,
+ create_list, key_count, key_info_buffer,
+ table->file) ||
+ table->file->create_handler_files(path))
+ {
+ DBUG_RETURN(TRUE);
+ }
+ thd->proc_info="end";
+ write_bin_log(thd, FALSE);
+ send_ok(thd);
+ DBUG_RETURN(FALSE);
+ }
+ }
+#endif
+
/*
Handling of symlinked tables:
If no rename:
@@ -3949,12 +4450,7 @@
my_free((gptr) new_table,MYF(0));
goto err;
}
- if (mysql_bin_log.is_open())
- {
- thd->clear_error();
- Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE);
- mysql_bin_log.write(&qinfo);
- }
+ write_bin_log(thd, TRUE);
goto end_temporary;
}
@@ -4085,15 +4581,14 @@
goto err;
}
thd->proc_info="end";
- if (mysql_bin_log.is_open())
- {
- thd->clear_error();
- Query_log_event qinfo(thd, thd->query, thd->query_length, FALSE, FALSE);
- mysql_bin_log.write(&qinfo);
- }
+ write_bin_log(thd, TRUE);
VOID(pthread_cond_broadcast(&COND_refresh));
VOID(pthread_mutex_unlock(&LOCK_open));
#ifdef HAVE_BERKELEY_DB
+ /*
+ TODO RONM: This problem needs to handled for Berkeley DB partitions
+ as well
+ */
if (old_db_type == DB_TYPE_BERKELEY_DB)
{
/*
--- 1.371/sql/sql_yacc.yy 2005-07-25 10:50:22 +02:00
+++ 1.372/sql/sql_yacc.yy 2005-08-27 07:49:57 +02:00
@@ -526,6 +526,7 @@
%token RELEASE_SYM
%token RELOAD
%token RENAME
+%token REORGANISE_SYM
%token REPAIR
%token REPEATABLE_SYM
%token REPEAT_SYM
@@ -605,6 +606,7 @@
%token SUM_SYM
%token SUPER_SYM
%token SUSPEND_SYM
+%token SYSDATE
%token TABLES
%token TABLESPACE
%token TABLE_SYM
@@ -746,7 +748,7 @@
bool_term bool_factor bool_test bool_pri
predicate bit_expr bit_term bit_factor value_expr term factor
table_wild simple_expr udf_expr
- using_list expr_or_default set_expr_or_default interval_expr
+ expr_or_default set_expr_or_default interval_expr
param_marker singlerow_subselect singlerow_subselect_init
exists_subselect exists_subselect_init geometry_function
signed_literal now_or_signed_literal opt_escape
@@ -769,7 +771,7 @@
key_alg opt_btree_or_rtree
%type <string_list>
- key_usage_list
+ key_usage_list using_list
%type <key_part>
key_part
@@ -1353,6 +1355,12 @@
YYTHD->client_capabilities |= CLIENT_MULTI_QUERIES;
sp->restore_thd_mem_root(YYTHD);
+ if (sp->m_multi_results)
+ {
+ my_error(ER_SP_NO_RETSET, MYF(0), "trigger");
+ YYABORT;
+ }
+
/*
We have to do it after parsing trigger body, because some of
sp_proc_stmt alternatives are not saving/restoring LEX, so
@@ -1505,8 +1513,7 @@
if (sp->m_multi_results)
{
- my_message(ER_SP_NO_RETSET_IN_FUNC, ER(ER_SP_NO_RETSET_IN_FUNC),
- MYF(0));
+ my_error(ER_SP_NO_RETSET, MYF(0), "function");
YYABORT;
}
if (sp->check_backpatch(YYTHD))
@@ -2002,7 +2009,7 @@
}
if (lex->sql_command == SQLCOM_CHANGE_DB)
{ /* "USE db" doesn't work in a procedure */
- my_message(ER_SP_NO_USE, ER(ER_SP_NO_USE), MYF(0));
+ my_error(ER_SP_BADSTATEMENT, MYF(0), "USE");
YYABORT;
}
/*
@@ -3007,7 +3014,15 @@
partitioning:
PARTITION_SYM
- { Lex->part_info= new partition_info(); }
+ {
+ LEX *lex= Lex;
+ lex->part_info= new partition_info();
+ if (!lex->part_info)
+ {
+ my_error(ER_OUTOFMEMORY, MYF(0), sizeof(partition_info));
+ YYABORT;
+ }
+ }
partition
;
@@ -3022,6 +3037,11 @@
partition info string into part_info data structure.
*/
lex->part_info= new partition_info();
+ if (!lex->part_info)
+ {
+ my_error(ER_OUTOFMEMORY, MYF(0), sizeof(partition_info));
+ YYABORT;
+ }
}
else
{
@@ -3029,10 +3049,12 @@
YYABORT;
}
}
- partition {};
+ partition {}
+ ;
partition:
- BY part_type_def opt_no_parts {} opt_sub_part {} part_defs;
+ BY part_type_def opt_no_parts {} opt_sub_part {} part_defs
+ ;
part_type_def:
opt_linear KEY_SYM '(' part_field_list ')'
@@ -3049,22 +3071,26 @@
part_func {}
| LIST_SYM
{ Lex->part_info->part_type= LIST_PARTITION; }
- part_func {};
+ part_func {}
+ ;
opt_linear:
/* empty */ {}
| LINEAR_SYM
- { Lex->part_info->linear_hash_ind= TRUE;};
+ { Lex->part_info->linear_hash_ind= TRUE;}
+ ;
part_field_list:
part_field_item {}
- | part_field_list ',' part_field_item {};
+ | part_field_list ',' part_field_item {}
+ ;
part_field_item:
ident
{
Lex->part_info->part_field_list.push_back($1.str);
- };
+ }
+ ;
part_func:
'(' remember_name part_func_expr remember_end ')'
@@ -3075,7 +3101,8 @@
lex->part_info->part_expr= $3;
lex->part_info->part_func_string= $2+1;
lex->part_info->part_func_len= expr_len;
- };
+ }
+ ;
sub_part_func:
'(' remember_name part_func_expr remember_end ')'
@@ -3086,7 +3113,8 @@
lex->part_info->subpart_expr= $3;
lex->part_info->subpart_func_string= $2+1;
lex->part_info->subpart_func_len= expr_len;
- };
+ }
+ ;
opt_no_parts:
@@ -3100,7 +3128,8 @@
YYABORT;
}
Lex->part_info->no_parts= no_parts;
- };
+ }
+ ;
opt_sub_part:
/* empty */ {}
@@ -3114,15 +3143,18 @@
lex->part_info->subpart_type= HASH_PARTITION;
lex->part_info->list_of_subpart_fields= TRUE;
}
- opt_no_subparts {};
+ opt_no_subparts {}
+ ;
sub_part_field_list:
sub_part_field_item {}
- | sub_part_field_list ',' sub_part_field_item {};
+ | sub_part_field_list ',' sub_part_field_item {}
+ ;
sub_part_field_item:
ident
- { Lex->part_info->subpart_field_list.push_back($1.str); };
+ { Lex->part_info->subpart_field_list.push_back($1.str); }
+ ;
part_func_expr:
bit_expr
@@ -3138,6 +3170,7 @@
}
$$=$1;
}
+ ;
opt_no_subparts:
/* empty */ {}
@@ -3150,7 +3183,8 @@
YYABORT;
}
Lex->part_info->no_subparts= no_parts;
- };
+ }
+ ;
part_defs:
/* empty */
@@ -3174,11 +3208,13 @@
}
part_info->count_curr_subparts= 0;
part_info->count_curr_parts= 0;
- };
+ }
+ ;
part_def_list:
part_definition {}
- | part_def_list ',' part_definition {};
+ | part_def_list ',' part_definition {}
+ ;
part_definition:
PARTITION_SYM
@@ -3201,47 +3237,61 @@
part_name {}
opt_part_values {}
opt_part_options {}
- opt_sub_partition {};
+ opt_sub_partition {}
+ ;
part_name:
ident_or_text
- { Lex->part_info->curr_part_elem->partition_name= $1.str; };
+ { Lex->part_info->curr_part_elem->partition_name= $1.str; }
+ ;
opt_part_values:
/* empty */
{
LEX *lex= Lex;
- if (lex->part_info->part_type == RANGE_PARTITION)
- {
- my_error(ER_PARTITION_REQUIRES_VALUES_ERROR, MYF(0),
- "RANGE", "LESS THAN");
- YYABORT;
- }
- if (lex->part_info->part_type == LIST_PARTITION)
+ if (!is_partition_management(lex))
{
- my_error(ER_PARTITION_REQUIRES_VALUES_ERROR, MYF(0),
- "LIST", "IN");
- YYABORT;
+ if (lex->part_info->part_type == RANGE_PARTITION)
+ {
+ my_error(ER_PARTITION_REQUIRES_VALUES_ERROR, MYF(0),
+ "RANGE", "LESS THAN");
+ YYABORT;
+ }
+ if (lex->part_info->part_type == LIST_PARTITION)
+ {
+ my_error(ER_PARTITION_REQUIRES_VALUES_ERROR, MYF(0),
+ "LIST", "IN");
+ YYABORT;
+ }
}
}
| VALUES LESS_SYM THAN_SYM part_func_max
{
- if (Lex->part_info->part_type != RANGE_PARTITION)
+ LEX *lex= Lex;
+ if (!is_partition_management(lex))
{
- my_error(ER_PARTITION_WRONG_VALUES_ERROR, MYF(0),
- "RANGE", "LESS THAN");
- YYABORT;
+ if (Lex->part_info->part_type != RANGE_PARTITION)
+ {
+ my_error(ER_PARTITION_WRONG_VALUES_ERROR, MYF(0),
+ "RANGE", "LESS THAN");
+ YYABORT;
+ }
}
}
| VALUES IN_SYM '(' part_list_func ')'
{
- if (Lex->part_info->part_type != LIST_PARTITION)
+ LEX *lex= Lex;
+ if (!is_partition_management(lex))
{
- my_error(ER_PARTITION_WRONG_VALUES_ERROR, MYF(0),
- "LIST", "IN");
- YYABORT;
+ if (Lex->part_info->part_type != LIST_PARTITION)
+ {
+ my_error(ER_PARTITION_WRONG_VALUES_ERROR, MYF(0),
+ "LIST", "IN");
+ YYABORT;
+ }
}
- };
+ }
+ ;
part_func_max:
MAX_VALUE_SYM
@@ -3262,17 +3312,20 @@
yyerror(ER(ER_PARTITION_MAXVALUE_ERROR));
YYABORT;
}
- };
+ }
+ ;
part_range_func:
'(' part_bit_expr ')'
{
Lex->part_info->curr_part_elem->range_value= $2;
- };
+ }
+ ;
part_list_func:
part_list_item {}
- | part_list_func ',' part_list_item {};
+ | part_list_func ',' part_list_item {}
+ ;
part_list_item:
part_bit_expr
@@ -3285,7 +3338,8 @@
}
*value_ptr= $1;
Lex->part_info->curr_part_elem->list_val_list.push_back(value_ptr);
- };
+ }
+ ;
part_bit_expr:
bit_expr
@@ -3315,6 +3369,7 @@
item_value= part_expr->val_int();
$$= item_value;
}
+ ;
opt_sub_partition:
/* empty */ {}
@@ -3336,11 +3391,13 @@
part_info->no_subparts= part_info->count_curr_subparts;
}
part_info->count_curr_subparts= 0;
- };
+ }
+ ;
sub_part_list:
sub_part_definition {}
- | sub_part_list ',' sub_part_definition {};
+ | sub_part_list ',' sub_part_definition {}
+ ;
sub_part_definition:
SUBPARTITION_SYM
@@ -3359,19 +3416,23 @@
part_info->count_curr_subparts++;
p_elem->engine_type= DB_TYPE_UNKNOWN;
}
- sub_name opt_part_options {};
+ sub_name opt_part_options {}
+ ;
sub_name:
ident_or_text
- { Lex->part_info->curr_part_elem->partition_name= $1.str; };
+ { Lex->part_info->curr_part_elem->partition_name= $1.str; }
+ ;
opt_part_options:
/* empty */ {}
- | opt_part_option_list {};
+ | opt_part_option_list {}
+ ;
opt_part_option_list:
opt_part_option_list opt_part_option {}
- | opt_part_option {};
+ | opt_part_option {}
+ ;
opt_part_option:
TABLESPACE opt_equal ident_or_text
@@ -3389,7 +3450,8 @@
| INDEX_SYM DIRECTORY_SYM opt_equal TEXT_STRING_sys
{ Lex->part_info->curr_part_elem->index_file_name= $4.str; }
| COMMENT_SYM opt_equal TEXT_STRING_sys
- { Lex->part_info->curr_part_elem->part_comment= $3.str; };
+ { Lex->part_info->curr_part_elem->part_comment= $3.str; }
+ ;
/*
End of partition parser part
@@ -4262,8 +4324,92 @@
| alter_list
opt_partitioning
| partitioning
+/*
+ From here we insert a number of commands to manage the partitions of a
+ partitioned table such as adding partitions, dropping partitions,
+ reorganising partitions in various manners. In future releases the list
+ will be longer and also include moving partitions to a
+ new table and so forth.
+*/
+ | add_partition_rule
+ | DROP PARTITION_SYM alt_part_name_list
+ {
+ Lex->alter_info.flags|= ALTER_DROP_PARTITION;
+ }
+ | COALESCE PARTITION_SYM ulong_num
+ {
+ LEX *lex= Lex;
+ lex->alter_info.flags|= ALTER_COALESCE_PARTITION;
+ lex->alter_info.no_parts= $3;
+ }
+ | reorg_partition_rule
+ ;
+
+add_partition_rule:
+ ADD PARTITION_SYM
+ {
+ LEX *lex= Lex;
+ lex->part_info= new partition_info();
+ if (!lex->part_info)
+ {
+ my_error(ER_OUTOFMEMORY, MYF(0), sizeof(partition_info));
+ YYABORT;
+ }
+ lex->alter_info.flags|= ALTER_ADD_PARTITION;
+ }
+ add_part_extra
+ {}
+ ;
+
+add_part_extra:
+ | '(' part_def_list ')'
+ {
+ LEX *lex= Lex;
+ lex->part_info->no_parts= lex->part_info->count_curr_parts;
+ }
+ | PARTITIONS_SYM ulong_num
+ {
+ LEX *lex= Lex;
+ lex->part_info->no_parts= $2;
+ }
+ ;
+
+reorg_partition_rule:
+ REORGANISE_SYM PARTITION_SYM
+ {
+ LEX *lex= Lex;
+ lex->part_info= new partition_info();
+ if (!lex->part_info)
+ {
+ my_error(ER_OUTOFMEMORY, MYF(0), sizeof(partition_info));
+ YYABORT;
+ }
+ lex->alter_info.flags|= ALTER_REORGANISE_PARTITION;
+ }
+ alt_part_name_list INTO '(' part_def_list ')'
+ {
+ LEX *lex= Lex;
+ lex->part_info->no_parts= lex->part_info->count_curr_parts;
+ }
;
+alt_part_name_list:
+ alt_part_name_item {}
+ | alt_part_name_list ',' alt_part_name_item {}
+ ;
+
+alt_part_name_item:
+ ident
+ {
+ Lex->alter_info.partition_names.push_back($1.str);
+ }
+ ;
+
+/*
+ End of management of partition commands
+*/
+
alter_list:
alter_list_item
| alter_list ',' alter_list_item
@@ -5279,10 +5425,10 @@
my_error(ER_WRONG_COLUMN_NAME, MYF(0), name->str);
YYABORT;
}
- $$= new Item_default_value(&Select->context, $3);
+ $$= new Item_default_value(Lex->current_context(), $3);
}
| VALUES '(' simple_ident ')'
- { $$= new Item_insert_value(&Select->context, $3); }
+ { $$= new Item_insert_value(Lex->current_context(), $3); }
| FUNC_ARG0 '(' ')'
{
if (!$1.symbol->create_func)
@@ -5537,6 +5683,10 @@
{ $$= new Item_func_substr($3,$5); }
| SUBSTRING_INDEX '(' expr ',' expr ',' expr ')'
{ $$= new Item_func_substr_index($3,$5,$7); }
+ | SYSDATE optional_braces
+ { $$= new Item_func_sysdate_local(); Lex->safe_to_cache_query=0;}
+ | SYSDATE '(' expr ')'
+ { $$= new Item_func_sysdate_local($3); Lex->safe_to_cache_query=0;}
| TIME_SYM '(' expr ')'
{ $$= new Item_time_typecast($3); }
| TIMESTAMP '(' expr ')'
@@ -5573,9 +5723,9 @@
name->init_qname(YYTHD);
sp_add_used_routine(lex, YYTHD, name, TYPE_ENUM_FUNCTION);
if ($5)
- $$= new Item_func_sp(&lex->current_select->context, name, *$5);
+ $$= new Item_func_sp(Lex->current_context(), name, *$5);
else
- $$= new Item_func_sp(&lex->current_select->context, name);
+ $$= new Item_func_sp(Lex->current_context(), name);
lex->safe_to_cache_query=0;
}
| IDENT_sys '(' udf_expr_list ')'
@@ -5663,9 +5813,9 @@
sp_add_used_routine(lex, YYTHD, name, TYPE_ENUM_FUNCTION);
if ($3)
- $$= new Item_func_sp(&lex->current_select->context, name, *$3);
+ $$= new Item_func_sp(Lex->current_context(), name, *$3);
else
- $$= new Item_func_sp(&lex->current_select->context, name);
+ $$= new Item_func_sp(Lex->current_context(), name);
lex->safe_to_cache_query=0;
}
}
@@ -5869,7 +6019,7 @@
{
SELECT_LEX *sel= Select;
sel->in_sum_expr--;
- $$=new Item_func_group_concat(&sel->context, $3, $5,
+ $$=new Item_func_group_concat(Lex->current_context(), $3, $5,
sel->gorder_list, $7);
$5->empty();
};
@@ -6005,68 +6155,116 @@
table_ref normal_join table_ref { YYERROR_UNLESS($1 && ($$=$3)); }
| table_ref STRAIGHT_JOIN table_factor
{ YYERROR_UNLESS($1 && ($$=$3)); $3->straight=1; }
- | table_ref normal_join table_ref ON expr
- { YYERROR_UNLESS($1 && ($$=$3)); add_join_on($3,$5); }
- | table_ref STRAIGHT_JOIN table_factor ON expr
- { YYERROR_UNLESS($1 && ($$=$3)); $3->straight=1; add_join_on($3,$5); }
+ | table_ref normal_join table_ref
+ ON
+ {
+ YYERROR_UNLESS($1 && ($$=$3));
+ /* Change the current name resolution context to a local context. */
+ Name_resolution_context *on_context;
+ if (!(on_context= make_join_on_context(YYTHD,$1,$3)))
+ YYABORT;
+ Lex->push_context(on_context);
+ }
+ expr
+ {
+ add_join_on($3,$6);
+ Lex->pop_context();
+ }
+ | table_ref STRAIGHT_JOIN table_factor
+ ON
+ {
+ YYERROR_UNLESS($1 && ($$=$3));
+ /* Change the current name resolution context to a local context. */
+ Name_resolution_context *on_context;
+ if (!(on_context= make_join_on_context(YYTHD,$1,$3)))
+ YYABORT;
+ Lex->push_context(on_context);
+ }
+ expr
+ {
+ $3->straight=1;
+ add_join_on($3,$6);
+ Lex->pop_context();
+ }
| table_ref normal_join table_ref
USING
{
SELECT_LEX *sel= Select;
YYERROR_UNLESS($1 && $3);
- sel->save_names_for_using_list($1, $3);
}
'(' using_list ')'
- { add_join_on($3,$7); $$=$3; }
-
- | table_ref LEFT opt_outer JOIN_SYM table_ref ON expr
- { YYERROR_UNLESS($1 && $5); add_join_on($5,$7); $5->outer_join|=JOIN_TYPE_LEFT; $$=$5; }
+ { add_join_natural($1,$3,$7); $$=$3; }
+ | table_ref LEFT opt_outer JOIN_SYM table_ref
+ ON
+ {
+ /* Change the current name resolution context to a local context. */
+ Name_resolution_context *on_context;
+ if (!(on_context= make_join_on_context(YYTHD,$1,$5)))
+ YYABORT;
+ Lex->push_context(on_context);
+ }
+ expr
+ {
+ YYERROR_UNLESS($1 && $5);
+ add_join_on($5,$8);
+ Lex->pop_context();
+ $5->outer_join|=JOIN_TYPE_LEFT;
+ $$=$5;
+ }
| table_ref LEFT opt_outer JOIN_SYM table_factor
{
SELECT_LEX *sel= Select;
YYERROR_UNLESS($1 && $5);
- sel->save_names_for_using_list($1, $5);
}
USING '(' using_list ')'
- { add_join_on($5,$9); $5->outer_join|=JOIN_TYPE_LEFT; $$=$5; }
+ { add_join_natural($1,$5,$9); $5->outer_join|=JOIN_TYPE_LEFT; $$=$5; }
| table_ref NATURAL LEFT opt_outer JOIN_SYM table_factor
{
YYERROR_UNLESS($1 && $6);
- add_join_natural($1,$6);
+ add_join_natural($1,$6,NULL);
$6->outer_join|=JOIN_TYPE_LEFT;
$$=$6;
}
- | table_ref RIGHT opt_outer JOIN_SYM table_ref ON expr
+ | table_ref RIGHT opt_outer JOIN_SYM table_ref
+ ON
+ {
+ /* Change the current name resolution context to a local context. */
+ Name_resolution_context *on_context;
+ if (!(on_context= make_join_on_context(YYTHD,$1,$5)))
+ YYABORT;
+ Lex->push_context(on_context);
+ }
+ expr
{
LEX *lex= Lex;
YYERROR_UNLESS($1 && $5);
if (!($$= lex->current_select->convert_right_join()))
YYABORT;
- add_join_on($$, $7);
+ add_join_on($$, $8);
+ Lex->pop_context();
}
| table_ref RIGHT opt_outer JOIN_SYM table_factor
{
SELECT_LEX *sel= Select;
YYERROR_UNLESS($1 && $5);
- sel->save_names_for_using_list($1, $5);
}
USING '(' using_list ')'
{
LEX *lex= Lex;
if (!($$= lex->current_select->convert_right_join()))
YYABORT;
- add_join_on($$, $9);
+ add_join_natural($$,$5,$9);
}
| table_ref NATURAL RIGHT opt_outer JOIN_SYM table_factor
{
YYERROR_UNLESS($1 && $6);
- add_join_natural($6,$1);
+ add_join_natural($6,$1,NULL);
LEX *lex= Lex;
if (!($$= lex->current_select->convert_right_join()))
YYABORT;
}
| table_ref NATURAL JOIN_SYM table_factor
- { YYERROR_UNLESS($1 && ($$=$4)); add_join_natural($1,$4); };
+ { YYERROR_UNLESS($1 && ($$=$4)); add_join_natural($1,$4,NULL); };
normal_join:
@@ -6094,8 +6292,23 @@
YYABORT;
sel->add_joined_table($$);
}
- | '{' ident table_ref LEFT OUTER JOIN_SYM table_ref ON expr '}'
- { YYERROR_UNLESS($3 && $7); add_join_on($7,$9); $7->outer_join|=JOIN_TYPE_LEFT; $$=$7; }
+ | '{' ident table_ref LEFT OUTER JOIN_SYM table_ref
+ ON
+ {
+ /* Change the current name resolution context to a local context. */
+ Name_resolution_context *on_context;
+ if (!(on_context= make_join_on_context(YYTHD,$3,$7)))
+ YYABORT;
+ Lex->push_context(on_context);
+ }
+ expr '}'
+ {
+ YYERROR_UNLESS($3 && $7);
+ add_join_on($7,$10);
+ Lex->pop_context();
+ $7->outer_join|=JOIN_TYPE_LEFT;
+ $$=$7;
+ }
| select_derived_init get_select_lex select_derived2
{
LEX *lex= Lex;
@@ -6149,6 +6362,7 @@
YYABORT;
sel->add_joined_table($$);
+ lex->pop_context();
}
else
if ($4 || $6)
@@ -6288,32 +6502,18 @@
using_list:
ident
{
- SELECT_LEX *sel= Select;
- if (!($$= new Item_func_eq(new Item_field(&sel->context,
- sel->db1, sel->table1,
- $1.str),
- new Item_field(&sel->context,
- sel->db2, sel->table2,
- $1.str))))
+ if (!($$= new List<String>))
YYABORT;
+ $$->push_back(new (YYTHD->mem_root)
+ String((const char *) $1.str, $1.length,
+ system_charset_info));
}
| using_list ',' ident
{
- SELECT_LEX *sel= Select;
- if (!($$=
- new Item_cond_and(new
- Item_func_eq(new
- Item_field(&sel->context,
- sel->db1,
- sel->table1,
- $3.str),
- new
- Item_field(&sel->context,
- sel->db2,
- sel->table2,
- $3.str)),
- $1)))
- YYABORT;
+ $1->push_back(new (YYTHD->mem_root)
+ String((const char *) $3.str, $3.length,
+ system_charset_info));
+ $$= $1;
};
interval:
@@ -6964,7 +7164,7 @@
expr_or_default:
expr { $$= $1;}
- | DEFAULT {$$= new Item_default_value(&Select->context); }
+ | DEFAULT {$$= new Item_default_value(Lex->current_context()); }
;
opt_insert_update:
@@ -7511,9 +7711,14 @@
FLUSH_SYM opt_no_write_to_binlog
{
LEX *lex=Lex;
- if (lex->sphead && lex->sphead->m_type == TYPE_ENUM_FUNCTION)
+ if (lex->sphead && lex->sphead->m_type != TYPE_ENUM_PROCEDURE)
{
- my_error(ER_SP_BADSTATEMENT, MYF(0), "FLUSH");
+ /*
+ Note that both FLUSH TABLES and FLUSH PRIVILEGES will break
+ execution in prelocked mode. So it is better to disable
+ FLUSH in stored functions and triggers completely.
+ */
+ my_error(ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0), "FLUSH");
YYABORT;
}
lex->sql_command= SQLCOM_FLUSH; lex->type=0;
@@ -7920,13 +8125,13 @@
ident '.' '*'
{
SELECT_LEX *sel= Select;
- $$ = new Item_field(&sel->context, NullS, $1.str, "*");
+ $$ = new Item_field(Lex->current_context(), NullS, $1.str, "*");
sel->with_wild++;
}
| ident '.' ident '.' '*'
{
SELECT_LEX *sel= Select;
- $$ = new Item_field(&sel->context, (YYTHD->client_capabilities &
+ $$ = new Item_field(Lex->current_context(), (YYTHD->client_capabilities &
CLIENT_NO_SCHEMA ? NullS : $1.str),
$3.str,"*");
sel->with_wild++;
@@ -7954,8 +8159,8 @@
SELECT_LEX *sel=Select;
$$= (sel->parsing_place != IN_HAVING ||
sel->get_in_sum_expr() > 0) ?
- (Item*) new Item_field(&sel->context, NullS, NullS, $1.str) :
- (Item*) new Item_ref(&sel->context, NullS, NullS, $1.str);
+ (Item*) new Item_field(Lex->current_context(), NullS, NullS, $1.str) :
+ (Item*) new Item_ref(Lex->current_context(), NullS, NullS, $1.str);
}
}
| simple_ident_q { $$= $1; }
@@ -7967,8 +8172,8 @@
SELECT_LEX *sel=Select;
$$= (sel->parsing_place != IN_HAVING ||
sel->get_in_sum_expr() > 0) ?
- (Item*) new Item_field(&sel->context, NullS, NullS, $1.str) :
- (Item*) new Item_ref(&sel->context, NullS, NullS, $1.str);
+ (Item*) new Item_field(Lex->current_context(), NullS, NullS, $1.str) :
+ (Item*) new Item_ref(Lex->current_context(), NullS, NullS, $1.str);
}
| simple_ident_q { $$= $1; }
;
@@ -8005,7 +8210,7 @@
YYABORT;
}
- if (!(trg_fld= new Item_trigger_field(&lex->current_select->context,
+ if (!(trg_fld= new Item_trigger_field(Lex->current_context(),
new_row ?
Item_trigger_field::NEW_ROW:
Item_trigger_field::OLD_ROW,
@@ -8031,8 +8236,8 @@
}
$$= (sel->parsing_place != IN_HAVING ||
sel->get_in_sum_expr() > 0) ?
- (Item*) new Item_field(&sel->context, NullS, $1.str, $3.str) :
- (Item*) new Item_ref(&sel->context, NullS, $1.str, $3.str);
+ (Item*) new Item_field(Lex->current_context(), NullS, $1.str, $3.str) :
+ (Item*) new Item_ref(Lex->current_context(), NullS, $1.str, $3.str);
}
}
| '.' ident '.' ident
@@ -8047,8 +8252,8 @@
}
$$= (sel->parsing_place != IN_HAVING ||
sel->get_in_sum_expr() > 0) ?
- (Item*) new Item_field(&sel->context, NullS, $2.str, $4.str) :
- (Item*) new Item_ref(&sel->context, NullS, $2.str, $4.str);
+ (Item*) new Item_field(Lex->current_context(), NullS, $2.str, $4.str) :
+ (Item*) new Item_ref(Lex->current_context(), NullS, $2.str, $4.str);
}
| ident '.' ident '.' ident
{
@@ -8062,11 +8267,11 @@
}
$$= (sel->parsing_place != IN_HAVING ||
sel->get_in_sum_expr() > 0) ?
- (Item*) new Item_field(&sel->context,
+ (Item*) new Item_field(Lex->current_context(),
(YYTHD->client_capabilities &
CLIENT_NO_SCHEMA ? NullS : $1.str),
$3.str, $5.str) :
- (Item*) new Item_ref(&sel->context,
+ (Item*) new Item_ref(Lex->current_context(),
(YYTHD->client_capabilities &
CLIENT_NO_SCHEMA ? NullS : $1.str),
$3.str, $5.str);
@@ -8295,6 +8500,7 @@
| CHANGED {}
| CIPHER_SYM {}
| CLIENT_SYM {}
+ | COALESCE {}
| COLLATION_SYM {}
| COLUMNS {}
| COMMITTED_SYM {}
@@ -8440,6 +8646,7 @@
| RELAY_LOG_FILE_SYM {}
| RELAY_LOG_POS_SYM {}
| RELOAD {}
+ | REORGANISE_SYM {}
| REPEATABLE_SYM {}
| REPLICATION {}
| RESOURCES {}
@@ -8639,7 +8846,8 @@
/* We are in trigger and assigning value to field of new row */
Item *it;
Item_trigger_field *trg_fld;
- sp_instr_set_trigger_field *i;
+ sp_instr_set_trigger_field *sp_fld;
+ LINT_INIT(sp_fld);
if ($1)
{
yyerror(ER(ER_SYNTAX_ERROR));
@@ -8653,14 +8861,14 @@
it= new Item_null();
}
- if (!(trg_fld= new Item_trigger_field(&lex->current_select->
- context,
+ if (!(trg_fld= new Item_trigger_field(Lex->current_context(),
Item_trigger_field::NEW_ROW,
$2.base_name.str)) ||
- !(i= new sp_instr_set_trigger_field(lex->sphead->
- instructions(),
- lex->spcont, trg_fld,
- it, lex)))
+ !(sp_fld= new sp_instr_set_trigger_field(lex->sphead->
+ instructions(),
+ lex->spcont,
+ trg_fld,
+ it, lex)))
YYABORT;
/*
@@ -8670,7 +8878,7 @@
lex->trg_table_fields.link_in_list((byte *)trg_fld,
(byte **)&trg_fld->next_trg_field);
- lex->sphead->add_instr(i);
+ lex->sphead->add_instr(sp_fld);
}
else if ($2.var)
{ /* System variable */
@@ -8684,7 +8892,7 @@
/* An SP local variable */
sp_pcontext *ctx= lex->spcont;
sp_pvar_t *spv;
- sp_instr_set *i;
+ sp_instr_set *sp_set;
Item *it;
if ($1)
{
@@ -8700,9 +8908,9 @@
it= spv->dflt;
else
it= new Item_null();
- i= new sp_instr_set(lex->sphead->instructions(), ctx,
- spv->offset, it, spv->type, lex, TRUE);
- lex->sphead->add_instr(i);
+ sp_set= new sp_instr_set(lex->sphead->instructions(), ctx,
+ spv->offset, it, spv->type, lex, TRUE);
+ lex->sphead->add_instr(sp_set);
spv->isset= TRUE;
}
}
@@ -9510,7 +9718,14 @@
lex->current_select->master_unit()->union_distinct=
lex->current_select;
}
- select_init {}
+ select_init
+ {
+ /*
+ Remove from the name resolution context stack the context of the
+ last select in the union.
+ */
+ Lex->pop_context();
+ }
;
union_opt:
@@ -9614,6 +9829,7 @@
')'
{
LEX *lex=Lex;
+ lex->pop_context();
lex->current_select = lex->current_select->return_after_parsing();
};
@@ -9665,7 +9881,7 @@
{
Lex->sql_command = SQLCOM_XA_START;
}
- | XA_SYM END xid opt_suspend_or_migrate
+ | XA_SYM END xid opt_suspend
{
Lex->sql_command = SQLCOM_XA_END;
}
@@ -9725,9 +9941,14 @@
| ONE_SYM PHASE_SYM { Lex->xa_opt=XA_ONE_PHASE; }
;
-opt_suspend_or_migrate:
+opt_suspend:
/* nothing */ { Lex->xa_opt=XA_NONE; }
| SUSPEND_SYM { Lex->xa_opt=XA_SUSPEND; }
+ opt_migrate
+ ;
+
+opt_migrate:
+ /* nothing */ { }
| FOR_SYM MIGRATE_SYM { Lex->xa_opt=XA_FOR_MIGRATE; }
;
--- 1.34/sql/share/errmsg.txt 2005-08-09 09:49:34 +02:00
+++ 1.35/sql/share/errmsg.txt 2005-08-27 08:12:18 +02:00
@@ -5137,8 +5137,8 @@
eng "Failed to ALTER %s %s"
ER_SP_SUBSELECT_NYI 0A000
eng "Subselect value not supported"
-ER_SP_NO_USE 42000
- eng "USE is not allowed in a stored procedure"
+ER_STMT_NOT_ALLOWED_IN_SF_OR_TRG 0A000
+ eng "%s is not allowed in stored function or trigger"
ER_SP_VARCOND_AFTER_CURSHNDLR 42000
eng "Variable or condition declaration after cursor or handler declaration"
ER_SP_CURSOR_AFTER_HANDLER 42000
@@ -5194,7 +5194,7 @@
ER_VIEW_SELECT_TMPTABLE
- eng "View's SELECT contains a temporary table '%-.64s'"
+ eng "View's SELECT refers to a temporary table '%-.64s'"
ER_VIEW_WRONG_LIST
@@ -5342,8 +5342,8 @@
eng "Duplicate handler declared in the same block"
ER_SP_NOT_VAR_ARG 42000
eng "OUT or INOUT argument %d for routine %s is not a variable"
-ER_SP_NO_RETSET_IN_FUNC 0A000
- eng "Not allowed to return a result set from a function"
+ER_SP_NO_RETSET 0A000
+ eng "Not allowed to return a result set from a %s"
ER_CANT_CREATE_GEOMETRY_OBJECT 22003
eng "Cannot get geometry object from data you send to the GEOMETRY field"
ER_FAILED_ROUTINE_BREAK_BINLOG
@@ -5380,14 +5380,25 @@
eng "Can't create federated table. The data source connection string '%-.64s' is not in the correct format"
ER_FOREIGN_DATA_STRING_INVALID
eng "The data source connection string '%-.64s' is not in the correct format"
-ER_CANT_CREATE_FEDERATED_TABLE
- eng "Can't create federated table. Foreign data src error : '%-.64s'"
-ER_TRG_IN_WRONG_SCHEMA
- eng "Trigger in wrong schema"
+ER_CANT_CREATE_FEDERATED_TABLE
+ eng "Can't create federated table. Foreign data src error : '%-.64s'"
+ER_TRG_IN_WRONG_SCHEMA
+ eng "Trigger in wrong schema"
ER_STACK_OVERRUN_NEED_MORE
eng "Thread stack overrun: %ld bytes used of a %ld byte stack, and %ld bytes needed. Use 'mysqld -O thread_stack=#' to specify a bigger stack."
ER_TOO_LONG_BODY 42000 S1009
eng "Routine body for '%-.100s' is too long"
+ER_WARN_CANT_DROP_DEFAULT_KEYCACHE
+ eng "Cannot drop default keycache"
+ER_TOO_BIG_DISPLAYWIDTH 42000 S1009
+ eng "Display width out of range for column '%-.64s' (max = %d)"
+ER_XAER_DUPID XAE08
+ eng "XAER_DUPID: The XID already exists"
+ER_DATETIME_FUNCTION_OVERFLOW 22008
+ eng "Datetime function: %-.32s field overflow"
+ER_CANT_UPDATE_USED_TABLE_IN_SF_OR_TRG
+ eng "Can't update table '%-.64s' in stored function/trigger because it is already used by statement which invoked this stored function/trigger."
ER_PARTITION_REQUIRES_VALUES_ERROR
eng "%s PARTITIONING requires definition of VALUES %s for each partition"
@@ -5440,7 +5451,7 @@
eng "Partitioning can not be used stand-alone in query"
ER_MIX_HANDLER_ERROR
- eng "The mix of handlers in the partitions is not allowed in this version in MySQL"
+ eng "The mix of handlers in the partitions is not allowed in this version of MySQL"
ER_PARTITION_NOT_DEFINED_ERROR
eng "For the partitioned engine it is necessary to define all %s"
@@ -5466,6 +5477,47 @@
ER_NO_PARTS_ERROR
eng "Number of %s = 0 is not an allowed value"
+ER_PARTITION_MGMT_ON_NONPARTITIONED
+ eng "Partition management on a not partitioned table is not possible"
+ER_DROP_PARTITION_NON_EXISTENT
+ eng "Error in list of partitions to change"
+ER_DROP_LAST_PARTITION
+ eng "Cannot remove all partitions, use DROP TABLE instead"
+ER_COALESCE_ONLY_ON_HASH_PARTITION
+ eng "COALESCE PARTITION can only be used on HASH/KEY partitions"
+ER_ONLY_ON_RANGE_LIST_PARTITION
+ eng "%s PARTITION can only be used on RANGE/LIST partitions"
+ER_ADD_PARTITION_SUBPART_ERROR
+ eng "Trying to Add partition(s) with wrong number of subpartitions"
+ swe "ADD PARTITION med fel antal subpartitioner"
+ER_ADD_PARTITION_NO_NEW_PARTITION
+ eng "At least one partition must be added"
+ER_COALESCE_PARTITION_NO_PARTITION
+ eng "At least one partition must be coalesced"
+ER_REORG_PARTITION_NOT_EXIST
+ eng "More partitions to reorganise than there are partitions"
+ER_SAME_NAME_PARTITION
+ eng "All partitions must have unique names in the table"
+ER_CONSECUTIVE_REORG_PARTITIONS
+ eng "When reorganising a set of partitions they must be in consecutive order"
+ER_REORG_OUTSIDE_RANGE
+ eng "The new partitions cover a bigger range then the reorganised partitions do"
+ER_DROP_PARTITION_FAILURE
+ eng "Drop partition not supported in this version for this handler"
+ER_DROP_PARTITION_WHEN_FK_DEFINED
+ eng "Cannot drop a partition when a foreign key constraint is defined on the table"
ER_TABLESPACE_OPTION_ONLY_ONCE
eng "It is not allowed to specify %s more than once"
ER_CREATE_TABLESPACE_FAILED
--- 1.27/mysql-test/r/ndb_alter_table.result 2005-04-13 10:10:54 +02:00
+++ 1.28/mysql-test/r/ndb_alter_table.result 2005-08-27 07:49:54 +02:00
@@ -179,8 +179,24 @@
2 two two
alter table t1 drop index c;
select * from t1 where b = 'two';
-ERROR HY000: Table definition has changed, please retry transaction
+a b c
+2 two two
select * from t1 where b = 'two';
a b c
2 two two
drop table t1;
+create table t3 (a int primary key) engine=ndbcluster;
+begin;
+insert into t3 values (1);
+alter table t3 rename t4;
+delete from t3;
+insert into t3 values (1);
+commit;
+select * from t3;
+ERROR HY000: Can't lock file (errno: 155)
+select * from t4;
+a
+1
+drop table t4;
+show tables;
+Tables_in_test
--- 1.23/mysql-test/t/ndb_alter_table.test 2005-08-09 09:49:29 +02:00
+++ 1.24/mysql-test/t/ndb_alter_table.test 2005-08-27 07:49:54 +02:00
@@ -151,7 +151,6 @@
connection server1;
alter table t1 drop index c;
connection server2;
---error 1412
select * from t1 where b = 'two';
select * from t1 where b = 'two';
connection server1;
@@ -180,4 +179,29 @@
#select count(*) from t2;
#drop table t2;
+connection server1;
+create table t3 (a int primary key) engine=ndbcluster;
+
+connection server2;
+begin;
+insert into t3 values (1);
+
+connection server1;
+alter table t3 rename t4;
+
+connection server2;
+# This should work as transaction is ongoing...
+delete from t3;
+insert into t3 values (1);
+commit;
+
+# This should fail as its a new transaction
+--error 1015
+select * from t3;
+select * from t4;
+drop table t4;
+show tables;
+connection server1;
+
# End of 4.1 tests
+
--- 1.12/storage/ndb/include/kernel/AttributeDescriptor.hpp 2005-04-29 16:30:20 +02:00
+++ 1.13/storage/ndb/include/kernel/AttributeDescriptor.hpp 2005-08-27 08:12:18 +02:00
@@ -24,6 +24,7 @@
friend class Dbtup;
friend class Dbtux;
friend class Dblqh;
+ friend class SimulatedBlock;
public:
static void setType(Uint32 &, Uint32 type);
--- 1.7/storage/ndb/include/kernel/BlockNumbers.h 2005-04-29 16:30:20 +02:00
+++ 1.8/storage/ndb/include/kernel/BlockNumbers.h 2005-08-27 08:12:18 +02:00
@@ -45,11 +45,11 @@
#define DBUTIL 0x100
#define SUMA 0x101
#define GREP 0x102
-#define DBTUX 0x103
-#define TSMAN 0x104
-#define LGMAN 0x105
-#define PGMAN 0x106
-#define RESTORE 0x107
+#define DBTUX 0x102
+#define TSMAN 0x103
+#define LGMAN 0x104
+#define PGMAN 0x105
+#define RESTORE 0x106
const BlockReference BACKUP_REF = numberToRef(BACKUP, 0);
const BlockReference DBTC_REF = numberToRef(DBTC, 0);
@@ -65,7 +65,6 @@
const BlockReference TRIX_REF = numberToRef(TRIX, 0);
const BlockReference DBUTIL_REF = numberToRef(DBUTIL, 0);
const BlockReference SUMA_REF = numberToRef(SUMA, 0);
-const BlockReference GREP_REF = numberToRef(GREP, 0);
const BlockReference DBTUX_REF = numberToRef(DBTUX, 0);
const BlockReference TSMAN_REF = numberToRef(TSMAN, 0);
const BlockReference LGMAN_REF = numberToRef(LGMAN, 0);
--- 1.15/storage/ndb/include/kernel/GlobalSignalNumbers.h 2005-07-21 16:15:15 +02:00
+++ 1.16/storage/ndb/include/kernel/GlobalSignalNumbers.h 2005-08-27 07:49:57 +02:00
@@ -788,8 +788,8 @@
/**
* Grep signals
*/
-#define GSN_GREP_SUB_CREATE_REQ 606
-#define GSN_GREP_SUB_CREATE_REF 607
+#define GSN_ALTER_TABLE_REP 606
+#define GSN_API_BROADCAST_REP 607
#define GSN_GREP_SUB_CREATE_CONF 608
#define GSN_GREP_CREATE_REQ 609
#define GSN_GREP_CREATE_REF 610
--- 1.8/storage/ndb/include/kernel/kernel_types.h 2005-04-29 16:30:20 +02:00
+++ 1.9/storage/ndb/include/kernel/kernel_types.h 2005-08-27 08:12:18 +02:00
@@ -68,6 +68,13 @@
class NdbOut&
operator<<(class NdbOut&, const struct Local_key&);
+inline
+Uint32
+table_version_major(Uint32 ver)
+{
+ return ver & 0x00FFFFFF;
+}
+
#endif
--- 1.47/storage/ndb/include/ndbapi/NdbDictionary.hpp 2005-07-25 10:30:27 +02:00
+++ 1.48/storage/ndb/include/ndbapi/NdbDictionary.hpp 2005-08-27 07:49:57 +02:00
@@ -78,9 +78,10 @@
///< changes to take effect
Retrieved, ///< The object exist and has been read
///< into main memory from NDB Kernel
- Invalid ///< The object has been invalidated
+ Invalid, ///< The object has been invalidated
///< and should not be used
-
+ Altered ///< Table has been altered in NDB kernel
+ ///< but is still valid for usage
};
/**
--- 1.5/storage/ndb/src/common/debugger/BlockNames.cpp 2005-04-29 16:30:22 +02:00
+++ 1.6/storage/ndb/src/common/debugger/BlockNames.cpp 2005-08-27 07:49:57 +02:00
@@ -32,7 +32,6 @@
{ "BACKUP", BACKUP },
{ "DBUTIL", DBUTIL },
{ "SUMA", SUMA },
- { "GREP", GREP },
{ "DBTUX", DBTUX }
,{ "TSMAN", TSMAN}
,{ "LGMAN", LGMAN }
--- 1.32/storage/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp 2005-08-24 18:50:25 +02:00
+++ 1.33/storage/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp 2005-08-27 07:49:57 +02:00
@@ -989,7 +989,6 @@
sendSignal(BACKUP_REF, GSN_DUMP_STATE_ORD, signal, signal->length(), JBB);
sendSignal(DBUTIL_REF, GSN_DUMP_STATE_ORD, signal, signal->length(), JBB);
sendSignal(SUMA_REF, GSN_DUMP_STATE_ORD, signal, signal->length(), JBB);
- sendSignal(GREP_REF, GSN_DUMP_STATE_ORD, signal, signal->length(), JBB);
sendSignal(TRIX_REF, GSN_DUMP_STATE_ORD, signal, signal->length(), JBB);
sendSignal(DBTUX_REF, GSN_DUMP_STATE_ORD, signal, signal->length(), JBB);
sendSignal(LGMAN_REF, GSN_DUMP_STATE_ORD, signal, signal->length(), JBB);
--- 1.26/storage/ndb/src/kernel/blocks/dbacc/Dbacc.hpp 2005-07-21 15:33:44 +02:00
+++ 1.27/storage/ndb/src/kernel/blocks/dbacc/Dbacc.hpp 2005-08-27 08:12:18 +02:00
@@ -711,13 +711,6 @@
Uint32 fragptrholder[MAX_FRAG_PER_NODE];
Uint32 tabUserPtr;
BlockReference tabUserRef;
-
- Uint8 noOfKeyAttr;
- Uint8 hasCharAttr; // char or var
- struct KeyAttr {
- Uint32 attributeDescriptor;
- CHARSET_INFO* charsetInfo;
- } keyAttr[MAX_ATTRIBUTES_IN_INDEX];
};
typedef Ptr<Tabrec> TabrecPtr;
@@ -755,7 +748,6 @@
void execACCKEYREQ(Signal* signal);
void execACCSEIZEREQ(Signal* signal);
void execACCFRAGREQ(Signal* signal);
- void execTC_SCHVERREQ(Signal* signal);
void execACC_SRREQ(Signal* signal);
void execNEXT_SCANREQ(Signal* signal);
void execACC_ABORTREQ(Signal* signal);
--- 1.22/storage/ndb/src/kernel/blocks/dbacc/DbaccInit.cpp 2005-07-21 16:15:15 +02:00
+++ 1.23/storage/ndb/src/kernel/blocks/dbacc/DbaccInit.cpp 2005-08-27 07:49:57 +02:00
@@ -116,7 +116,6 @@
addRecSignal(GSN_ACCKEYREQ, &Dbacc::execACCKEYREQ);
addRecSignal(GSN_ACCSEIZEREQ, &Dbacc::execACCSEIZEREQ);
addRecSignal(GSN_ACCFRAGREQ, &Dbacc::execACCFRAGREQ);
- addRecSignal(GSN_TC_SCHVERREQ, &Dbacc::execTC_SCHVERREQ);
addRecSignal(GSN_NEXT_SCANREQ, &Dbacc::execNEXT_SCANREQ);
addRecSignal(GSN_ACC_ABORTREQ, &Dbacc::execACC_ABORTREQ);
addRecSignal(GSN_ACC_SCANREQ, &Dbacc::execACC_SCANREQ);
--- 1.61/storage/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp 2005-08-09 09:49:34 +02:00
+++ 1.62/storage/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp 2005-08-27 08:12:18 +02:00
@@ -29,8 +29,7 @@
#include <signaldata/DropTab.hpp>
#include <signaldata/DumpStateOrd.hpp>
#include <signaldata/TuxMaint.hpp>
-#include <SectionReader.hpp>
-#include <md5_hash.hpp>
+#include <KeyDescriptor.hpp>
// TO_DO_RONM is a label for comments on what needs to be improved in future versions
// when more time is given.
@@ -613,12 +612,6 @@
tabptr.p->fragholder[i] = RNIL;
tabptr.p->fragptrholder[i] = RNIL;
}//for
- tabptr.p->noOfKeyAttr = 0;
- tabptr.p->hasCharAttr = 0;
- for (Uint32 k = 0; k < MAX_ATTRIBUTES_IN_INDEX; k++) {
- tabptr.p->keyAttr[k].attributeDescriptor = 0;
- tabptr.p->keyAttr[k].charsetInfo = 0;
- }
}//for
}//Dbacc::initialiseTableRec()
@@ -731,8 +724,8 @@
Uint32 userPtr = req->userPtr;
BlockReference retRef = req->userRef;
fragrecptr.p->rootState = ACTIVEROOT;
- AccFragConf * const conf = (AccFragConf*)&signal->theData[0];
+ AccFragConf * const conf = (AccFragConf*)&signal->theData[0];
conf->userPtr = userPtr;
conf->rootFragPtr = RNIL;
conf->fragId[0] = fragrecptr.p->fragmentid;
@@ -757,67 +750,6 @@
}//Dbacc::addFragRefuseEarly()
void
-Dbacc::execTC_SCHVERREQ(Signal* signal)
-{
- jamEntry();
- if (! assembleFragments(signal)) {
- jam();
- return;
- }
- tabptr.i = signal->theData[0];
- ptrCheckGuard(tabptr, ctablesize, tabrec);
- Uint32 noOfKeyAttr = signal->theData[6];
- ndbrequire(noOfKeyAttr <= MAX_ATTRIBUTES_IN_INDEX);
- Uint32 hasCharAttr = 0;
-
- SegmentedSectionPtr s0Ptr;
- signal->getSection(s0Ptr, 0);
- SectionReader r0(s0Ptr, getSectionSegmentPool());
- Uint32 i = 0;
- while (i < noOfKeyAttr) {
- jam();
- Uint32 attributeDescriptor = ~0;
- Uint32 csNumber = ~0;
- if (! r0.getWord(&attributeDescriptor) ||
- ! r0.getWord(&csNumber)) {
- jam();
- break;
- }
- csNumber >>= 16;
- CHARSET_INFO* cs = 0;
- if (csNumber != 0) {
- cs = all_charsets[csNumber];
- ndbrequire(cs != 0);
- hasCharAttr = 1;
- }
- if (AttributeDescriptor::getArrayType(attributeDescriptor) !=
- NDB_ARRAYTYPE_FIXED) {
- hasCharAttr = 1; // has Var attr
- }
- tabptr.p->keyAttr[i].attributeDescriptor = attributeDescriptor;
- tabptr.p->keyAttr[i].charsetInfo = cs;
- i++;
- }
- ndbrequire(i == noOfKeyAttr);
- releaseSections(signal);
-
- tabptr.p->noOfKeyAttr = noOfKeyAttr;
- tabptr.p->hasCharAttr = hasCharAttr;
-
- // copy char attr flag to each fragment
- for (Uint32 i1 = 0; i1 < MAX_FRAG_PER_NODE; i1++) {
- jam();
- if (tabptr.p->fragptrholder[i1] != RNIL) {
- fragrecptr.i = tabptr.p->fragptrholder[i1];
- ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
- fragrecptr.p->hasCharAttr = hasCharAttr;
- }
- }
-
- // no reply to DICT
-}
-
-void
Dbacc::execDROP_TAB_REQ(Signal* signal){
jamEntry();
DropTabReq* req = (DropTabReq*)signal->getDataPtr();
@@ -1378,59 +1310,14 @@
void
Dbacc::xfrmKeyData(Signal* signal)
{
- tabptr.i = fragrecptr.p->myTableId;
- ptrCheckGuard(tabptr, ctablesize, tabrec);
-
- Uint32 dst[1024 * MAX_XFRM_MULTIPLY];
- Uint32 dstSize = (sizeof(dst) >> 2);
+ Uint32 table = fragrecptr.p->myTableId;
+ Uint32 dst[MAX_KEY_SIZE_IN_WORDS * MAX_XFRM_MULTIPLY];
+ Uint32 keyPartLen[MAX_ATTRIBUTES_IN_INDEX];
Uint32* src = &signal->theData[7];
- const Uint32 noOfKeyAttr = tabptr.p->noOfKeyAttr;
- Uint32 dstPos = 0;
- Uint32 srcPos = 0;
- Uint32 i = 0;
-
- while (i < noOfKeyAttr) {
- const Tabrec::KeyAttr& keyAttr = tabptr.p->keyAttr[i];
- const uchar* srcPtr = (const uchar*)&src[srcPos];
-
- Uint32 typeId =
- AttributeDescriptor::getType(keyAttr.attributeDescriptor);
- Uint32 maxBytes =
- AttributeDescriptor::getSizeInBytes(keyAttr.attributeDescriptor);
- Uint32 lb, len;
- bool ok = NdbSqlUtil::get_var_length(typeId, srcPtr, maxBytes, lb, len);
- ndbrequire(ok);
-
- Uint32 srcBytes = lb + len;
- Uint32 srcWords = (srcBytes + 3) / 4;
- Uint32 dstWords = ~0;
- uchar* dstPtr = (uchar*)&dst[dstPos];
- CHARSET_INFO* cs = keyAttr.charsetInfo;
-
- if (cs == 0) {
- jam();
- memcpy(dstPtr, srcPtr, srcWords << 2);
- dstWords = srcWords;
- } else {
- jam();
- Uint32 xmul = cs->strxfrm_multiply;
- if (xmul == 0)
- xmul = 1;
- // see comment in DbtcMain.cpp
- Uint32 dstLen = xmul * (maxBytes - lb);
- ndbrequire(dstLen <= ((dstSize - dstPos) << 2));
- int n = NdbSqlUtil::strnxfrm_bug7284(cs, dstPtr, dstLen, srcPtr + lb, len);
- ndbrequire(n != -1);
- while ((n & 3) != 0)
- dstPtr[n++] = 0;
- dstWords = (n >> 2);
- }
- dstPos += dstWords;
- srcPos += srcWords;
- i++;
- }
- memcpy(src, dst, dstPos << 2);
- operationRecPtr.p->xfrmtupkeylen = dstPos;
+ Uint32 len = xfrm_key(table, src, dst, sizeof(dst) >> 2, keyPartLen);
+ ndbrequire(len); // 0 means error
+ memcpy(src, dst, len << 2);
+ operationRecPtr.p->xfrmtupkeylen = len;
}
void Dbacc::accIsLockedLab(Signal* signal)
@@ -5484,6 +5371,8 @@
regFragPtr.p->scan[i] = RNIL;
}//for
+ Uint32 hasCharAttr = g_key_descriptor_pool.getPtr(req->tableId)->hasCharAttr;
+ regFragPtr.p->hasCharAttr = hasCharAttr;
}//Dbacc::initFragAdd()
void Dbacc::initFragGeneral(FragmentrecPtr regFragPtr)
--- 1.90/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp 2005-07-26 15:15:46 +02:00
+++ 1.91/storage/ndb/src/kernel/blocks/dbdict/Dbdict.cpp 2005-08-27 08:12:18 +02:00
@@ -27,6 +27,7 @@
#include <SectionReader.hpp>
#include <SimpleProperties.hpp>
#include <AttributeHeader.hpp>
+#include <KeyDescriptor.hpp>
#include <signaldata/DictSchemaInfo.hpp>
#include <signaldata/DictTabInfo.hpp>
#include <signaldata/DropTabFile.hpp>
@@ -81,6 +82,7 @@
#include <signaldata/CreateFragmentation.hpp>
#include <signaldata/CreateTab.hpp>
#include <NdbSleep.h>
+#include <signaldata/ApiBroadcast.hpp>
#include <signaldata/DropObj.hpp>
#include <signaldata/CreateObj.hpp>
@@ -143,6 +145,25 @@
}
};
+Uint32
+alter_table_inc_schema_version(Uint32 old)
+{
+ return (old & 0x00FFFFFF) + ((old + 0x1000000) & 0xFF000000);
+}
+
+static
+Uint32
+alter_table_dec_schema_version(Uint32 old)
+{
+ return (old & 0x00FFFFFF) + ((old - 0x1000000) & 0xFF000000);
+}
+
+static
+Uint32
+create_table_inc_schema_version(Uint32 old)
+{
+ return (old + 0x00000001) & 0x00FFFFFF;
+}
/* **************************************************************** */
/* ---------------------------------------------------------------- */
@@ -974,7 +995,7 @@
case SchemaFile::ADD_STARTED:
jam();
ok = true;
- ndbrequire((oldVersion + 1) == newVersion);
+ ndbrequire(create_table_inc_schema_version(oldVersion) == newVersion);
ndbrequire(oldState == SchemaFile::INIT ||
oldState == SchemaFile::DROP_TABLE_COMMITTED);
break;
@@ -987,7 +1008,7 @@
case SchemaFile::ALTER_TABLE_COMMITTED:
jam();
ok = true;
- ndbrequire((oldVersion + 1) == newVersion);
+ ndbrequire(alter_table_inc_schema_version(oldVersion) == newVersion);
ndbrequire(oldState == SchemaFile::TABLE_ADD_COMMITTED ||
oldState == SchemaFile::ALTER_TABLE_COMMITTED);
break;
@@ -1893,6 +1914,7 @@
c_pageRecordArray.setSize(ZNUMBER_OF_PAGES);
c_schemaPageRecordArray.setSize(2 * NDB_SF_MAX_PAGES);
c_tableRecordPool.setSize(tablerecSize);
+ g_key_descriptor_pool.setSize(tablerecSize);
c_triggerRecordPool.setSize(c_maxNoOfTriggers);
c_obj_pool.setSize(tablerecSize+c_maxNoOfTriggers);
@@ -3526,6 +3548,21 @@
}
}
+bool
+Dbdict::check_ndb_versions() const
+{
+ Uint32 node = 0;
+ Uint32 version = getNodeInfo(getOwnNodeId()).m_version;
+ while((node = c_aliveNodes.find(node + 1)) != BitmaskImpl::NotFound)
+ {
+ if(getNodeInfo(node).m_version != version)
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
void
Dbdict::execALTER_TABLE_REQ(Signal* signal)
{
@@ -3562,6 +3599,13 @@
alterTableRef(signal, req, AlterTableRef::Busy);
return;
}
+
+ if (!check_ndb_versions())
+ {
+ jam();
+ alterTableRef(signal, req, AlterTableRef::IncompatibleVersions);
+ return;
+ }
const TableRecord::TabState tabState = tablePtr.p->tabState;
bool ok = false;
@@ -3712,7 +3756,7 @@
lreq->clientData = alterTabPtr.p->m_senderData;
lreq->changeMask = alterTabPtr.p->m_changeMask;
lreq->tableId = tablePtr.p->tableId;
- lreq->tableVersion = tablePtr.p->tableVersion + 1;
+ lreq->tableVersion = alter_table_inc_schema_version(tablePtr.p->tableVersion);
lreq->gci = tablePtr.p->gciTableCreated;
lreq->requestType = AlterTabReq::AlterTablePrepare;
@@ -3792,6 +3836,14 @@
alterTabRef(signal, req, AlterTableRef::Busy);
return;
}
+
+ if (!check_ndb_versions())
+ {
+ jam();
+ alterTabRef(signal, req, AlterTableRef::IncompatibleVersions);
+ return;
+ }
+
alterTabPtr.p->m_alterTableId = tableId;
alterTabPtr.p->m_coordinatorRef = senderRef;
@@ -3834,7 +3886,7 @@
}
ndbrequire(ok);
- if(tablePtr.p->tableVersion + 1 != tableVersion){
+ if(alter_table_inc_schema_version(tablePtr.p->tableVersion) != tableVersion){
jam();
alterTabRef(signal, req, AlterTableRef::InvalidTableVersion);
return;
@@ -4328,7 +4380,7 @@
ndbrequire(org.assign(alterTabPtrP->previousTableName));
// Revert schema version
- tablePtr.p->tableVersion = tablePtr.p->tableVersion - 1;
+ tablePtr.p->tableVersion = alter_table_dec_schema_version(tablePtr.p->tableVersion);
}
obj_ptr.p->m_name = tablePtr.p->tableName;
// Put it back
@@ -4387,6 +4439,27 @@
conf->requestType = AlterTabReq::AlterTableCommit;
sendSignal(coordinatorRef, GSN_ALTER_TAB_CONF, signal,
AlterTabConf::SignalLength, JBB);
+
+
+ {
+ ApiBroadcastRep* api= (ApiBroadcastRep*)signal->getDataPtrSend();
+ api->gsn = GSN_ALTER_TABLE_REP;
+ api->minVersion = MAKE_VERSION(4,1,15);
+
+ AlterTableRep* rep = (AlterTableRep*)api->theData;
+ rep->tableId = tabPtr.p->tableId;
+ rep->tableVersion = alter_table_dec_schema_version(tabPtr.p->tableVersion);
+ rep->changeType = AlterTableRep::CT_ALTERED;
+
+ LinearSectionPtr ptr[3];
+ ptr[0].p = (Uint32*)alterTabPtr.p->previousTableName;
+ ptr[0].sz = (sizeof(alterTabPtr.p->previousTableName) + 3) >> 2;
+
+ sendSignal(QMGR_REF, GSN_API_BROADCAST_REP, signal,
+ ApiBroadcastRep::SignalLength + AlterTableRep::SignalLength,
+ JBB, ptr,1);
+ }
+
if(coordinatorRef != reference()) {
jam();
// Release resources
@@ -4438,7 +4511,7 @@
XSchemaFile * xsf = &c_schemaFile[c_schemaRecord.schemaPage != 0];
SchemaFile::TableEntry * tabEntry = getTableEntry(xsf, tabPtr.i);
- tabPtr.p->tableVersion = tabEntry->m_tableVersion + 1;
+ tabPtr.p->tableVersion = create_table_inc_schema_version(tabEntry->m_tableVersion);
/**
* Pack
@@ -4467,7 +4540,7 @@
req->gci = 0;
req->tableId = tabPtr.i;
- req->tableVersion = tabEntry->m_tableVersion + 1;
+ req->tableVersion = create_table_inc_schema_version(tabEntry->m_tableVersion);
sendFragmentedSignal(rg, GSN_CREATE_TAB_REQ, signal,
CreateTabReq::SignalLength, JBB);
@@ -4929,6 +5002,44 @@
sendSignal(DBLQH_REF, GSN_LQHFRAGREQ, signal,
LqhFragReq::SignalLength, JBB);
}
+
+ /**
+ * Create KeyDescriptor
+ */
+ KeyDescriptor* desc= g_key_descriptor_pool.getPtr(tabPtr.i);
+ new (desc) KeyDescriptor();
+
+ Uint32 key = 0;
+ Uint32 tAttr = tabPtr.p->firstAttribute;
+ while (tAttr != RNIL)
+ {
+ jam();
+ AttributeRecord* aRec = c_attributeRecordPool.getPtr(tAttr);
+ if (aRec->tupleKey)
+ {
+ desc->noOfKeyAttr ++;
+ desc->keyAttr[key].attributeDescriptor = aRec->attributeDescriptor;
+
+ Uint32 csNumber = (aRec->extPrecision >> 16);
+ if(csNumber)
+ {
+ desc->keyAttr[key].charsetInfo = all_charsets[csNumber];
+ ndbrequire(all_charsets[csNumber]);
+ desc->hasCharAttr = 1;
+ }
+ else
+ {
+ desc->keyAttr[key].charsetInfo = 0;
+ }
+ if(AttributeDescriptor::getDKey(aRec->attributeDescriptor))
+ {
+ desc->noOfDistrKeys ++;
+ }
+ key++;
+ }
+ tAttr = aRec->nextAttrInTable;
+ }
+ ndbrequire(key == tabPtr.p->noOfPrimkey);
}
void
@@ -5123,33 +5234,10 @@
signal->theData[4] = (Uint32)tabPtr.p->tableType;
signal->theData[5] = createTabPtr.p->key;
signal->theData[6] = (Uint32)tabPtr.p->noOfPrimkey;
-
- Uint32 buf[2 * MAX_ATTRIBUTES_IN_INDEX];
- Uint32 sz = 0;
-
- LocalDLFifoList<AttributeRecord> alist(c_attributeRecordPool,
- tabPtr.p->m_attributes);
- AttributeRecordPtr attrPtr;
- for (alist.first(attrPtr); !attrPtr.isNull(); alist.next(attrPtr)) {
- jam();
- if (attrPtr.p->tupleKey) {
- buf[sz++] = attrPtr.p->attributeDescriptor;
- // TODO send 2nd word of AttributeDescriptor instead
- buf[sz++] = attrPtr.p->extPrecision; // charset number in upper half
- }
- }
- ndbrequire((int)sz == 2 * tabPtr.p->noOfPrimkey);
-
- LinearSectionPtr lsPtr[3];
- lsPtr[0].p = buf;
- lsPtr[0].sz = sz;
- // note: ACC does not reply
- if (tabPtr.p->isTable() || tabPtr.p->isHashIndex())
- sendSignal(DBACC_REF, GSN_TC_SCHVERREQ, signal, 7, JBB, lsPtr, 1);
- sendSignal(DBTC_REF, GSN_TC_SCHVERREQ, signal, 7, JBB, lsPtr, 1);
+ sendSignal(DBTC_REF, GSN_TC_SCHVERREQ, signal, 7, JBB);
return;
}
-
+
ndbrequire(false);
}
@@ -14021,3 +14109,4 @@
execute(signal, t->m_callback, 0);
}
+CArray<KeyDescriptor> g_key_descriptor_pool;
--- 1.36/storage/ndb/src/kernel/blocks/dbdict/Dbdict.hpp 2005-07-25 10:30:28 +02:00
+++ 1.37/storage/ndb/src/kernel/blocks/dbdict/Dbdict.hpp 2005-08-27 07:49:58 +02:00
@@ -752,6 +752,7 @@
void execALTER_TAB_REQ(Signal* signal);
void execALTER_TAB_REF(Signal* signal);
void execALTER_TAB_CONF(Signal* signal);
+ bool check_ndb_versions() const;
void execCREATE_FILE_REQ(Signal* signal);
void execCREATE_FILEGROUP_REQ(Signal* signal);
--- 1.13/storage/ndb/src/kernel/blocks/dbdict/printSchemaFile.cpp 2005-05-24 17:30:58 +02:00
+++ 1.14/storage/ndb/src/kernel/blocks/dbdict/printSchemaFile.cpp 2005-08-27 07:49:58 +02:00
@@ -85,7 +85,8 @@
te.m_tableState != SchemaFile::DROP_TABLE_COMMITTED)) {
ndbout << "Table " << i << ":"
<< " State = " << te.m_tableState
- << " version = " << te.m_tableVersion
+ << " version = " << table_version_major(te.m_tableVersion) <<
+ << "(" << table_version_minor(te.m_tableVersion) << ")"
<< " type = " << te.m_tableType
<< " noOfPages = " << te.m_noOfPages
<< " gcp: " << te.m_gcp << endl;
--- 1.33/storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp 2005-07-25 10:30:28 +02:00
+++ 1.34/storage/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp 2005-08-27 07:49:58 +02:00
@@ -1891,8 +1891,6 @@
// Suma will not send response to this for now, later...
sendSignal(SUMA_REF, GSN_INCL_NODEREQ, signal, 2, JBB);
- // Grep will not send response to this for now, later...
- sendSignal(GREP_REF, GSN_INCL_NODEREQ, signal, 2, JBB);
return;
}//if
if (TstartNode_or_blockref == numberToRef(BACKUP, getOwnNodeId())){
--- 1.50/storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp 2005-07-21 16:15:15 +02:00
+++ 1.51/storage/ndb/src/kernel/blocks/dblqh/Dblqh.hpp 2005-08-27 07:49:58 +02:00
@@ -2198,7 +2198,7 @@
void LQHKEY_abort(Signal* signal, int errortype);
void LQHKEY_error(Signal* signal, int errortype);
void nextRecordCopy(Signal* signal);
- void calculateHash(Signal* signal);
+ Uint32 calculateHash(Uint32 tableId, const Uint32* src);
void continueAfterCheckLcpStopBlocked(Signal* signal);
void checkLcpStopBlockedLab(Signal* signal);
void sendCommittedTc(Signal* signal, BlockReference atcBlockref);
--- 1.94/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp 2005-08-25 21:08:07 +02:00
+++ 1.95/storage/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp 2005-08-27 08:12:19 +02:00
@@ -61,6 +61,7 @@
#include <signaldata/RestoreImpl.hpp>
#include <signaldata/KeyInfo.hpp>
#include <signaldata/AttrInfo.hpp>
+#include <KeyDescriptor.hpp>
// Use DEBUG to print messages that should be
// seen only when we debug the product
@@ -3368,7 +3369,8 @@
LQHKEY_abort(signal, 4);
return;
}
- if(tabptr.p->schemaVersion != schemaVersion){
+ if(table_version_major(tabptr.p->schemaVersion) !=
+ table_version_major(schemaVersion)){
LQHKEY_abort(signal, 5);
return;
}
@@ -4432,7 +4434,7 @@
lqhKeyReq->requestInfo = Treqinfo;
lqhKeyReq->tcBlockref = sig4;
- sig0 = regTcPtr->tableref + (regTcPtr->schemaVersion << 16);
+ sig0 = regTcPtr->tableref + ((regTcPtr->schemaVersion << 16) & 0xFFFF0000);
sig1 = regTcPtr->fragmentid + (regTcPtr->nodeAfterNext[0] << 16);
sig2 = regTcPtr->transid[0];
sig3 = regTcPtr->transid[1];
@@ -8992,44 +8994,17 @@
/* FRAGMENT TO A NEW REPLICA OF THE FRAGMENT. IT DOES ALSO SHUT DOWN ALL */
/* CONNECTIONS TO THE FAILED NODE. */
/*---------------------------------------------------------------------------*/
-void Dblqh::calculateHash(Signal* signal)
+Uint32
+Dblqh::calculateHash(Uint32 tableId, const Uint32* src)
{
- DatabufPtr locDatabufptr;
- UintR Ti;
- UintR Tdata0;
- UintR Tdata1;
- UintR Tdata2;
- UintR Tdata3;
- UintR* Tdata32;
- Uint64 Tdata[512];
-
- Tdata32 = (UintR*)&Tdata[0];
-
- Tdata0 = tcConnectptr.p->tupkeyData[0];
- Tdata1 = tcConnectptr.p->tupkeyData[1];
- Tdata2 = tcConnectptr.p->tupkeyData[2];
- Tdata3 = tcConnectptr.p->tupkeyData[3];
- Tdata32[0] = Tdata0;
- Tdata32[1] = Tdata1;
- Tdata32[2] = Tdata2;
- Tdata32[3] = Tdata3;
- locDatabufptr.i = tcConnectptr.p->firstTupkeybuf;
- Ti = 4;
- while (locDatabufptr.i != RNIL) {
- ptrCheckGuard(locDatabufptr, cdatabufFileSize, databuf);
- Tdata0 = locDatabufptr.p->data[0];
- Tdata1 = locDatabufptr.p->data[1];
- Tdata2 = locDatabufptr.p->data[2];
- Tdata3 = locDatabufptr.p->data[3];
- Tdata32[Ti ] = Tdata0;
- Tdata32[Ti + 1] = Tdata1;
- Tdata32[Ti + 2] = Tdata2;
- Tdata32[Ti + 3] = Tdata3;
- locDatabufptr.i = locDatabufptr.p->nextDatabuf;
- Ti += 4;
- }//while
- tcConnectptr.p->hashValue =
- md5_hash((Uint64*)&Tdata32[0], (UintR)tcConnectptr.p->primKeyLen);
+ jam();
+ Uint64 Tmp[(MAX_KEY_SIZE_IN_WORDS*MAX_XFRM_MULTIPLY) >> 1];
+ Uint32 keyPartLen[MAX_ATTRIBUTES_IN_INDEX];
+ Uint32 keyLen = xfrm_key(tableId, src, (Uint32*)Tmp, sizeof(Tmp) >> 2,
+ keyPartLen);
+ ndbrequire(keyLen);
+
+ return md5_hash(Tmp, keyLen);
}//Dblqh::calculateHash()
/* *************************************** */
@@ -9358,7 +9333,7 @@
const TupKeyConf * const tupKeyConf = (TupKeyConf *)signal->getDataPtr();
UintR readLength = tupKeyConf->readLength;
-
+ Uint32 tableId = tcConnectptr.p->tableref;
scanptr.i = tcConnectptr.p->tcScanRec;
c_scanRecordPool.getPtr(scanptr);
ScanRecord* scanP = scanptr.p;
@@ -9384,7 +9359,14 @@
Uint32 len= tcConnectptr.p->primKeyLen = readPrimaryKeys(scanP, tcConP, tmp);
// Calculate hash (no need to linearies key)
- tcConnectptr.p->hashValue = md5_hash((Uint64*)tmp, len);
+ if (g_key_descriptor_pool.getPtr(tableId)->hasCharAttr)
+ {
+ tcConnectptr.p->hashValue = calculateHash(tableId, tmp);
+ }
+ else
+ {
+ tcConnectptr.p->hashValue = md5_hash((Uint64*)tmp, len);
+ }
// Move into databuffer to make packLqhkeyreqLab happy
memcpy(tcConP->tupkeyData, tmp, 4*4);
@@ -15036,7 +15018,7 @@
tabptr.i = tcConnectptr.p->tableref;
ptrCheckGuard(tabptr, ctabrecFileSize, tablerec);
if (getFragmentrec(signal, tcConnectptr.p->fragmentid) &&
- (tabptr.p->schemaVersion == tcConnectptr.p->schemaVersion)) {
+ (table_version_major(tabptr.p->schemaVersion) == table_version_major(tcConnectptr.p->schemaVersion))) {
if (fragptr.p->execSrStatus != Fragrecord::IDLE) {
if (fragptr.p->execSrNoReplicas > logPartPtr.p->execSrExecuteIndex) {
ndbrequire((fragptr.p->execSrNoReplicas - 1) < 4);
--- 1.31/storage/ndb/src/kernel/blocks/dbtc/Dbtc.hpp 2005-07-21 15:33:45 +02:00
+++ 1.32/storage/ndb/src/kernel/blocks/dbtc/Dbtc.hpp 2005-08-27 07:49:58 +02:00
@@ -969,13 +969,9 @@
Uint8 hasCharAttr; // char or var
Uint8 noOfDistrKeys;
- struct KeyAttr {
- Uint32 attributeDescriptor;
- CHARSET_INFO* charsetInfo;
- } keyAttr[MAX_ATTRIBUTES_IN_INDEX];
-
bool checkTable(Uint32 schemaVersion) const {
- return enabled && !dropping && (schemaVersion == currentSchemaVersion);
+ return enabled && !dropping &&
+ (table_version_major(schemaVersion) == table_version_major(currentSchemaVersion));
}
Uint32 getErrorCode(Uint32 schemaVersion) const;
--- 1.81/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp 2005-07-26 15:25:13 +02:00
+++ 1.82/storage/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp 2005-08-27 08:12:19 +02:00
@@ -66,6 +66,7 @@
#include <signaldata/DictTabInfo.hpp>
#include <AttributeDescriptor.hpp>
#include <SectionReader.hpp>
+#include <KeyDescriptor.hpp>
#include <NdbOut.hpp>
#include <DebuggerNames.hpp>
@@ -329,47 +330,16 @@
BlockReference retPtr = signal->theData[5];
Uint32 noOfKeyAttr = signal->theData[6];
ndbrequire(noOfKeyAttr <= MAX_ATTRIBUTES_IN_INDEX);
- Uint32 hasCharAttr = 0;
- Uint32 noOfDistrKeys = 0;
- SegmentedSectionPtr s0Ptr;
- signal->getSection(s0Ptr, 0);
- SectionReader r0(s0Ptr, getSectionSegmentPool());
- Uint32 i = 0;
- while (i < noOfKeyAttr) {
- jam();
- Uint32 attributeDescriptor = ~0;
- Uint32 csNumber = ~0;
- if (! r0.getWord(&attributeDescriptor) ||
- ! r0.getWord(&csNumber)) {
- jam();
- break;
- }
- csNumber >>= 16;
- CHARSET_INFO* cs = 0;
- if (csNumber != 0) {
- cs = all_charsets[csNumber];
- ndbrequire(cs != 0);
- hasCharAttr = 1;
- }
- if (AttributeDescriptor::getArrayType(attributeDescriptor) !=
- NDB_ARRAYTYPE_FIXED) {
- hasCharAttr = 1; // has Var attr
- }
-
- noOfDistrKeys += AttributeDescriptor::getDKey(attributeDescriptor);
- tabptr.p->keyAttr[i].attributeDescriptor = attributeDescriptor;
- tabptr.p->keyAttr[i].charsetInfo = cs;
- i++;
- }
- ndbrequire(i == noOfKeyAttr);
- releaseSections(signal);
+
+ const KeyDescriptor* desc = g_key_descriptor_pool.getPtr(tabptr.i);
+ ndbrequire(noOfKeyAttr == desc->noOfKeyAttr);
ndbrequire(tabptr.p->enabled == false);
tabptr.p->enabled = true;
tabptr.p->dropping = false;
- tabptr.p->noOfKeyAttr = noOfKeyAttr;
- tabptr.p->hasCharAttr = hasCharAttr;
- tabptr.p->noOfDistrKeys = noOfDistrKeys;
+ tabptr.p->noOfKeyAttr = desc->noOfKeyAttr;
+ tabptr.p->hasCharAttr = desc->hasCharAttr;
+ tabptr.p->noOfDistrKeys = desc->noOfDistrKeys;
signal->theData[0] = tabptr.i;
signal->theData[1] = retPtr;
@@ -2328,114 +2298,37 @@
Uint32 tabPtrI,
bool distr)
{
- Uint64 Tmp[MAX_KEY_SIZE_IN_WORDS * 4 * MAX_XFRM_MULTIPLY];
- const Uint32 dstSize = sizeof(Tmp) / 4;
+ Uint64 Tmp[MAX_KEY_SIZE_IN_WORDS * MAX_XFRM_MULTIPLY];
const TableRecord* tabPtrP = &tableRecord[tabPtrI];
- const Uint32 noOfKeyAttr = tabPtrP->noOfKeyAttr;
- Uint32 noOfDistrKeys = tabPtrP->noOfDistrKeys;
const bool hasCharAttr = tabPtrP->hasCharAttr;
+ const bool hasDistKeys = tabPtrP->noOfDistrKeys > 0;
Uint32 *dst = (Uint32*)Tmp;
Uint32 dstPos = 0;
- Uint32 srcPos = 0;
Uint32 keyPartLen[MAX_ATTRIBUTES_IN_INDEX];
- if (hasCharAttr){
- Uint32 i = 0;
- while (i < noOfKeyAttr) {
- const TableRecord::KeyAttr& keyAttr = tabPtrP->keyAttr[i];
- const uchar* srcPtr = (const uchar*)&src[srcPos];
-
- Uint32 typeId =
- AttributeDescriptor::getType(keyAttr.attributeDescriptor);
- Uint32 maxBytes =
- AttributeDescriptor::getSizeInBytes(keyAttr.attributeDescriptor);
- Uint32 lb, len;
- bool ok = NdbSqlUtil::get_var_length(typeId, srcPtr, maxBytes, lb, len);
- ndbrequire(ok);
-
- Uint32 srcBytes = lb + len;
- Uint32 srcWords = (srcBytes + 3) / 4;
- Uint32 dstWords = ~0;
- uchar* dstPtr = (uchar*)&dst[dstPos];
- CHARSET_INFO* cs = keyAttr.charsetInfo;
-
- if (cs == NULL) {
- jam();
- memcpy(dstPtr, srcPtr, srcWords << 2);
- dstWords = srcWords;
- } else {
- jam();
- Uint32 xmul = cs->strxfrm_multiply;
- if (xmul == 0)
- xmul = 1;
- /*
- * Varchar end spaces do not matter. To get same hash we
- * blank-pad to maximum length via strnxfrm.
- */
- Uint32 dstLen = xmul * (maxBytes - lb);
- ndbrequire(dstLen <= ((dstSize - dstPos) << 2));
- int n = NdbSqlUtil::strnxfrm_bug7284(cs, dstPtr, dstLen, srcPtr + lb, len);
- ndbrequire(n != -1);
- while ((n & 3) != 0) {
- dstPtr[n++] = 0;
- }
- dstWords = (n >> 2);
- }
- dstPos += dstWords;
- srcPos += srcWords;
- keyPartLen[i++] = dstWords;
- }
+ Uint32 * keyPartLenPtr;
+ if(hasCharAttr)
+ {
+ keyPartLenPtr = keyPartLen;
+ dstPos = xfrm_key(tabPtrI, src, dst, sizeof(Tmp) >> 2, keyPartLenPtr);
+ ndbrequire(dstPos);
}
else
{
dst = src;
dstPos = srcLen;
+ keyPartLenPtr = 0;
}
md5_hash(dstHash, (Uint64*)dst, dstPos);
- if(distr && noOfDistrKeys)
+ if(distr && hasDistKeys)
{
jam();
- src = dst;
- dstPos = 0;
- Uint32 i = 0;
- if(hasCharAttr)
- {
- while (i < noOfKeyAttr && noOfDistrKeys)
- {
- const TableRecord::KeyAttr& keyAttr = tabPtrP->keyAttr[i];
- Uint32 len = keyPartLen[i];
- if(AttributeDescriptor::getDKey(keyAttr.attributeDescriptor))
- {
- noOfDistrKeys--;
- memmove(dst+dstPos, src, len << 2);
- dstPos += len;
- }
- src += len;
- i++;
- }
- }
- else
- {
- while (i < noOfKeyAttr && noOfDistrKeys)
- {
- const TableRecord::KeyAttr& keyAttr = tabPtrP->keyAttr[i];
- Uint32 len =
- AttributeDescriptor::getSizeInBytes(keyAttr.attributeDescriptor);
- len = (len + 3) / 4;
- if(AttributeDescriptor::getDKey(keyAttr.attributeDescriptor))
- {
- noOfDistrKeys--;
- memmove(dst+dstPos, src, len << 2);
- dstPos += len;
- }
- src += len;
- i++;
- }
- }
+
Uint32 tmp[4];
- md5_hash(tmp, (Uint64*)dst, dstPos);
+ Uint32 len = create_distr_key(tabPtrI, dst, keyPartLenPtr);
+ md5_hash(tmp, (Uint64*)dst, len);
dstHash[1] = tmp[1];
}
return true; // success
@@ -3353,7 +3246,7 @@
lqhKeyReq->tcBlockref = sig4;
lqhKeyReq->savePointId = sig5;
- sig0 = regCachePtr->tableref + (regCachePtr->schemaVersion << 16);
+ sig0 = regCachePtr->tableref + ((regCachePtr->schemaVersion << 16) & 0xFFFF0000);
sig1 = regCachePtr->fragmentid + (regTcPtr->tcNodedata[1] << 16);
sig2 = regApiPtr->transid[0];
sig3 = regApiPtr->transid[1];
@@ -10210,10 +10103,6 @@
tabptr.p->noOfKeyAttr = 0;
tabptr.p->hasCharAttr = 0;
tabptr.p->noOfDistrKeys = 0;
- for (unsigned k = 0; k < MAX_ATTRIBUTES_IN_INDEX; k++) {
- tabptr.p->keyAttr[k].attributeDescriptor = 0;
- tabptr.p->keyAttr[k].charsetInfo = 0;
- }
}//for
}//Dbtc::initTable()
@@ -13142,7 +13031,7 @@
return ZNO_SUCH_TABLE;
if(dropping)
return ZDROP_TABLE_IN_PROGRESS;
- if(schemaVersion != currentSchemaVersion)
+ if(table_version_major(schemaVersion) != table_version_major(currentSchemaVersion))
return ZWRONG_SCHEMA_VERSION_ERROR;
ErrorReporter::handleAssert("Dbtc::TableRecord::getErrorCode",
__FILE__, __LINE__);
--- 1.23/storage/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp 2005-07-07 01:18:54 +02:00
+++ 1.24/storage/ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp 2005-08-27 07:49:59 +02:00
@@ -76,7 +76,6 @@
{ BACKUP_REF, 1 , 10000, 10999 },
{ DBUTIL_REF, 1 , 11000, 11999 },
{ SUMA_REF, 1 , 13000, 13999 },
- { GREP_REF, 1 , 0, 0 },
{ DBTUX_REF, 1 , 12000, 12999 }
,{ TSMAN_REF, 1 , 0, 0 }
,{ LGMAN_REF, 1 , 0, 0 }
@@ -1457,9 +1456,6 @@
sendSignal(SUMA_REF, GSN_NODE_FAILREP, signal,
NodeFailRep::SignalLength, JBB);
- sendSignal(GREP_REF, GSN_NODE_FAILREP, signal,
- NodeFailRep::SignalLength, JBB);
-
Uint32 nodeId = 0;
while(!allFailed.isclear()){
nodeId = allFailed.find(nodeId + 1);
@@ -2383,7 +2379,6 @@
void Ndbcntr::execSTART_ORD(Signal* signal){
jamEntry();
- ndbrequire(NO_OF_BLOCKS == ALL_BLOCKS_SZ);
c_missra.execSTART_ORD(signal);
}
@@ -2458,7 +2453,7 @@
* Finished...
*/
currentStartPhase = 0;
- for(Uint32 i = 0; i<NO_OF_BLOCKS; i++){
+ for(Uint32 i = 0; i<ALL_BLOCKS_SZ; i++){
if(ALL_BLOCKS[i].NextSP < currentStartPhase)
currentStartPhase = ALL_BLOCKS[i].NextSP;
}
--- 1.21/storage/ndb/src/kernel/blocks/suma/Suma.cpp 2005-06-20 16:44:47 +02:00
+++ 1.22/storage/ndb/src/kernel/blocks/suma/Suma.cpp 2005-08-27 07:49:59 +02:00
@@ -2186,7 +2186,8 @@
case SubCreateReq::DatabaseSnapshot:
case SubCreateReq::SelectiveTableSnapshot:
jam();
- subbPtr.p->m_subscriberRef = GREP_REF;
+ ndbrequire(false);
+ //subbPtr.p->m_subscriberRef = GREP_REF;
subbPtr.p->m_subscriberData = subPtr.p->m_subscriberData;
break;
case SubCreateReq::SingleTableScan:
@@ -3019,16 +3020,6 @@
c_lastCompleteGCI = gci;
/**
- * always send SUB_GCP_COMPLETE_REP to Grep (so
- * Lars can do funky stuff calculating intervals,
- * even before the subscription is started
- */
- rep->senderRef = reference();
- rep->senderData = 0; //ignored in grep
- EXECUTE_DIRECT(refToBlock(GREP_REF), GSN_SUB_GCP_COMPLETE_REP, signal,
- SubGcpCompleteRep::SignalLength);
-
- /**
* Signal to subscriber(s)
*/
@@ -3052,13 +3043,6 @@
ndbout_c("GSN_SUB_GCP_COMPLETE_REP to %s:",
getBlockName(refToBlock(ref)));
#else
- /**
- * Ignore sending to GREP (since we sent earlier)
- */
- if (ref == GREP_REF) {
- jam();
- continue;
- }
CRASH_INSERTION(13018);
--- 1.14/storage/ndb/src/kernel/SimBlockList.cpp 2005-07-21 15:33:43 +02:00
+++ 1.15/storage/ndb/src/kernel/SimBlockList.cpp 2005-08-27 08:12:18 +02:00
@@ -30,7 +30,6 @@
#include <Backup.hpp>
#include <DbUtil.hpp>
#include <Suma.hpp>
-#include <Grep.hpp>
#include <Dbtux.hpp>
#include <tsman.hpp>
#include <lgman.hpp>
@@ -107,7 +106,7 @@
theList[14] = NEW_BLOCK(Backup)(conf);
theList[15] = NEW_BLOCK(DbUtil)(conf);
theList[16] = NEW_BLOCK(Suma)(conf);
- theList[17] = NEW_BLOCK(Grep)(conf);
+ theList[17] = 0;
theList[18] = NEW_BLOCK(Dbtux)(conf);
theList[19] = NEW_BLOCK(Restore)(conf);
}
--- 1.15/storage/ndb/src/kernel/vm/SimulatedBlock.cpp 2005-04-29 16:30:28 +02:00
+++ 1.16/storage/ndb/src/kernel/vm/SimulatedBlock.cpp 2005-08-27 07:49:59 +02:00
@@ -1802,3 +1802,118 @@
}
#endif
+
+#include "KeyDescriptor.hpp"
+
+Uint32
+SimulatedBlock::xfrm_key(Uint32 tab, const Uint32* src,
+ Uint32 *dst, Uint32 dstSize,
+ Uint32 keyPartLen[MAX_ATTRIBUTES_IN_INDEX]) const
+{
+ const KeyDescriptor * desc = g_key_descriptor_pool.getPtr(tab);
+ const Uint32 noOfKeyAttr = desc->noOfKeyAttr;
+
+ Uint32 i = 0;
+ Uint32 srcPos = 0;
+ Uint32 dstPos = 0;
+ while (i < noOfKeyAttr)
+ {
+ const KeyDescriptor::KeyAttr& keyAttr = desc->keyAttr[i];
+
+ Uint32 srcBytes =
+ AttributeDescriptor::getSizeInBytes(keyAttr.attributeDescriptor);
+ Uint32 srcWords = (srcBytes + 3) / 4;
+ Uint32 dstWords = ~0;
+ uchar* dstPtr = (uchar*)&dst[dstPos];
+ const uchar* srcPtr = (const uchar*)&src[srcPos];
+ CHARSET_INFO* cs = keyAttr.charsetInfo;
+
+ if (cs == NULL)
+ {
+ jam();
+ memcpy(dstPtr, srcPtr, srcWords << 2);
+ dstWords = srcWords;
+ }
+ else
+ {
+ jam();
+ Uint32 typeId =
+ AttributeDescriptor::getType(keyAttr.attributeDescriptor);
+ Uint32 lb, len;
+ bool ok = NdbSqlUtil::get_var_length(typeId, srcPtr, srcBytes, lb, len);
+ ndbrequire(ok);
+ Uint32 xmul = cs->strxfrm_multiply;
+ if (xmul == 0)
+ xmul = 1;
+ /*
+ * Varchar is really Char. End spaces do not matter. To get
+ * same hash we blank-pad to maximum length via strnxfrm.
+ * TODO use MySQL charset-aware hash function instead
+ */
+ Uint32 dstLen = xmul * (srcBytes - lb);
+ ndbrequire(dstLen <= ((dstSize - dstPos) << 2));
+ int n = NdbSqlUtil::strnxfrm_bug7284(cs, dstPtr, dstLen, srcPtr + lb, len);
+ ndbrequire(n != -1);
+ while ((n & 3) != 0)
+ {
+ dstPtr[n++] = 0;
+ }
+ dstWords = (n >> 2);
+ }
+ dstPos += dstWords;
+ srcPos += srcWords;
+ keyPartLen[i++] = dstWords;
+ }
+
+ return dstPos;
+}
+
+Uint32
+SimulatedBlock::create_distr_key(Uint32 tableId,
+ Uint32 *data,
+ const Uint32
+ keyPartLen[MAX_ATTRIBUTES_IN_INDEX]) const
+{
+ const KeyDescriptor* desc = g_key_descriptor_pool.getPtr(tableId);
+ const Uint32 noOfKeyAttr = desc->noOfKeyAttr;
+ Uint32 noOfDistrKeys = desc->noOfDistrKeys;
+
+ Uint32 *src = data;
+ Uint32 *dst = data;
+ Uint32 i = 0;
+ Uint32 dstPos = 0;
+
+ if(keyPartLen)
+ {
+ while (i < noOfKeyAttr && noOfDistrKeys)
+ {
+ Uint32 attr = desc->keyAttr[i].attributeDescriptor;
+ Uint32 len = keyPartLen[i];
+ if(AttributeDescriptor::getDKey(attr))
+ {
+ noOfDistrKeys--;
+ memmove(dst+dstPos, src, len << 2);
+ dstPos += len;
+ }
+ src += len;
+ i++;
+ }
+ }
+ else
+ {
+ while (i < noOfKeyAttr && noOfDistrKeys)
+ {
+ Uint32 attr = desc->keyAttr[i].attributeDescriptor;
+ Uint32 len = AttributeDescriptor::getSizeInWords(attr);
+ if(AttributeDescriptor::getDKey(attr))
+ {
+ noOfDistrKeys--;
+ memmove(dst+dstPos, src, len << 2);
+ dstPos += len;
+ }
+ src += len;
+ i++;
+ }
+ }
+ return dstPos;
+}
--- 1.18/storage/ndb/src/kernel/vm/SimulatedBlock.hpp 2005-07-13 10:55:43 +02:00
+++ 1.19/storage/ndb/src/kernel/vm/SimulatedBlock.hpp 2005-08-27 07:49:59 +02:00
@@ -20,11 +20,13 @@
#include <NdbTick.h>
#include <kernel_types.h>
#include <ndb_version.h>
+#include <ndb_limits.h>
#include "VMSignal.hpp"
#include <RefConvert.hpp>
#include <BlockNumbers.h>
#include <GlobalSignalNumbers.h>
+
#include "pc.hpp"
#include <NodeInfo.hpp>
#include <NodeState.hpp>
@@ -392,6 +394,24 @@
*/
const NodeInfo & getNodeInfo(NodeId nodeId) const;
NodeInfo & setNodeInfo(NodeId);
+
+ /**********************
+ * Xfrm stuff
+ */
+
+ /**
+ * @return length
+ */
+ Uint32 xfrm_key(Uint32 tab, const Uint32* src,
+ Uint32 *dst, Uint32 dstLen,
+ Uint32 keyPartLen[MAX_ATTRIBUTES_IN_INDEX]) const;
+
+ /**
+ *
+ */
+ Uint32 create_distr_key(Uint32 tableId,
+ Uint32 *data,
+ const Uint32 keyPaLen[MAX_ATTRIBUTES_IN_INDEX])const;
private:
NewVARIABLE* NewVarRef; /* New Base Address Table for block */
--- 1.51/storage/ndb/src/mgmapi/mgmapi.cpp 2005-08-09 09:49:34 +02:00
+++ 1.52/storage/ndb/src/mgmapi/mgmapi.cpp 2005-08-27 07:49:59 +02:00
@@ -335,15 +335,21 @@
const Properties* p = parser.parse(ctx, session);
if (p == NULL){
- /**
- * Print some info about why the parser returns NULL
- */
- fprintf(handle->errstream,
- "Error in mgm protocol parser. cmd: >%s< status: %d curr: %d\n",
- cmd, (Uint32)ctx.m_status, ctx.m_currentToken);
- DBUG_PRINT("info",("ctx.status: %d, ctx.m_currentToken: %s",
- ctx.m_status, ctx.m_currentToken));
- }
+ if(!ndb_mgm_is_connected(handle)) {
+ return NULL;
+ }
+ else
+ {
+ /**
+ * Print some info about why the parser returns NULL
+ */
+ fprintf(handle->errstream,
+ "Error in mgm protocol parser. cmd: >%s< status: %d curr: %d\n",
+ cmd, (Uint32)ctx.m_status, ctx.m_currentToken);
+ DBUG_PRINT("info",("ctx.status: %d, ctx.m_currentToken: %s",
+ ctx.m_status, ctx.m_currentToken));
+ }
+ }
#ifdef MGMAPI_LOG
else {
/**
@@ -363,6 +369,15 @@
{
if(!handle)
return 0;
+
+ if(handle->connected)
+ {
+ if(Ndb_check_socket_hup(handle->socket))
+ {
+ handle->connected= 0;
+ NDB_CLOSE_SOCKET(handle->socket);
+ }
+ }
return handle->connected;
}
--- 1.14/storage/ndb/src/ndbapi/DictCache.cpp 2005-06-13 15:24:51 +02:00
+++ 1.15/storage/ndb/src/ndbapi/DictCache.cpp 2005-08-27 07:49:59 +02:00
@@ -21,6 +21,9 @@
#include <NdbCondition.h>
#include <NdbSleep.h>
+static NdbTableImpl f_invalid_table;
+static NdbTableImpl f_altered_table;
+
Ndb_local_table_info *
Ndb_local_table_info::create(NdbTableImpl *table_impl, Uint32 sz)
{
@@ -202,21 +205,41 @@
TableVersion & ver = vers->back();
if(ver.m_status != RETREIVING ||
- ver.m_impl != 0 ||
+ !(ver.m_impl == 0 ||
+ ver.m_impl == &f_invalid_table || ver.m_impl == &f_altered_table) ||
ver.m_version != 0 ||
ver.m_refCount == 0){
abort();
}
- if(tab == 0){
+ if(tab == 0)
+ {
DBUG_PRINT("info", ("No table found in db"));
vers->erase(sz - 1);
- } else {
+ }
+ else if (ver.m_impl == 0) {
ver.m_impl = tab;
ver.m_version = tab->m_version;
ver.m_status = OK;
+ }
+ else if (ver.m_impl == &f_invalid_table)
+ {
+ ver.m_impl = tab;
+ ver.m_version = tab->m_version;
+ ver.m_status = DROPPED;
+ ver.m_impl->m_status = NdbDictionary::Object::Invalid;
+ }
+ else if(ver.m_impl == &f_altered_table)
+ {
+ ver.m_impl = tab;
+ ver.m_version = tab->m_version;
+ ver.m_status = DROPPED;
+ ver.m_impl->m_status = NdbDictionary::Object::Altered;
+ }
+ else
+ {
+ abort();
}
-
NdbCondition_Broadcast(m_waitForTableCondition);
DBUG_RETURN(tab);
}
@@ -322,6 +345,47 @@
}
abort();
+}
+
+void
+GlobalDictCache::alter_table_rep(const char * name,
+ Uint32 tableId,
+ Uint32 tableVersion,
+ bool altered)
+{
+ const Uint32 len = strlen(name);
+ Vector<TableVersion> * vers =
+ m_tableHash.getData(name, len);
+
+ if(vers == 0)
+ {
+ return;
+ }
+
+ const Uint32 sz = vers->size();
+ if(sz == 0)
+ {
+ return;
+ }
+
+ for(Uint32 i = 0; i < sz; i++)
+ {
+ TableVersion & ver = (* vers)[i];
+ if(ver.m_version == tableVersion && ver.m_impl &&
+ ver.m_impl->m_tableId == tableId)
+ {
+ ver.m_status = DROPPED;
+ ver.m_impl->m_status = altered ?
+ NdbDictionary::Object::Altered : NdbDictionary::Object::Invalid;
+ return;
+ }
+
+ if(i == sz - 1 && ver.m_status == RETREIVING)
+ {
+ ver.m_impl = altered ? &f_altered_table : &f_invalid_table;
+ return;
+ }
+ }
}
template class Vector<GlobalDictCache::TableVersion>;
--- 1.95/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp 2005-08-13 08:23:33 +02:00
+++ 1.96/storage/ndb/src/ndbapi/NdbDictionaryImpl.cpp 2005-08-27 07:49:59 +02:00
@@ -1662,25 +1662,22 @@
const char * originalInternalName = internalName.c_str();
DBUG_ENTER("NdbDictionaryImpl::alterTable");
- if(!get_local_table_info(internalName, false)){
- m_error.code= 709;
+ Ndb_local_table_info * local = 0;
+ if((local= get_local_table_info(originalInternalName, false)) == 0)
+ {
+ m_error.code = 709;
DBUG_RETURN(-1);
}
+
// Alter the table
int ret = m_receiver.alterTable(m_ndb, impl);
if(ret == 0){
// Remove cached information and let it be refreshed at next access
- if (m_localHash.get(originalInternalName) != NULL) {
- m_localHash.drop(originalInternalName);
- m_globalHash->lock();
- NdbTableImpl * cachedImpl = m_globalHash->get(originalInternalName);
- // If in local cache it must be in global
- if (!cachedImpl)
- abort();
- cachedImpl->m_status = NdbDictionary::Object::Invalid;
- m_globalHash->drop(cachedImpl);
- m_globalHash->unlock();
- }
+ m_globalHash->lock();
+ local->m_table_impl->m_status = NdbDictionary::Object::Invalid;
+ m_globalHash->drop(local->m_table_impl);
+ m_globalHash->unlock();
+ m_localHash.drop(originalInternalName);
}
DBUG_RETURN(ret);
}
--- 1.36/storage/ndb/src/ndbapi/TransporterFacade.cpp 2005-08-09 09:49:35 +02:00
+++ 1.37/storage/ndb/src/ndbapi/TransporterFacade.cpp 2005-08-27 07:49:59 +02:00
@@ -35,6 +35,7 @@
#include <ndb_version.h>
#include <SignalLoggerManager.hpp>
#include <kernel/ndb_limits.h>
+#include <signaldata/AlterTable.hpp>
//#define REPORT_TRANSPORTER
//#define API_TRACE;
@@ -309,6 +310,17 @@
theFacade->theArbitMgr->doStop(theData);
break;
+ case GSN_ALTER_TABLE_REP:
+ {
+ const AlterTableRep* rep = (const AlterTableRep*)theData;
+ theFacade->m_globalDictCache.lock();
+ theFacade->m_globalDictCache.
+ alter_table_rep((const char*)ptr[0].p,
+ rep->tableId,
+ rep->tableVersion,
+ rep->changeType == AlterTableRep::CT_ALTERED);
+ theFacade->m_globalDictCache.unlock();
+ }
default:
break;
--- 1.146/sql/ha_ndbcluster.cc 2005-08-09 09:49:30 +02:00
+++ 1.147/sql/ha_ndbcluster.cc 2005-08-27 08:12:18 +02:00
@@ -35,7 +35,7 @@
// options from from mysqld.cc
extern my_bool opt_ndb_optimized_node_selection;
-extern my_bool opt_ndb_linear_hash;
+extern enum ndb_distribution opt_ndb_distribution_id;
extern const char *opt_ndbcluster_connectstring;
// Default value for parallelism
@@ -2919,7 +2919,16 @@
errkey= m_dupkey;
}
if (flag & HA_STATUS_AUTO)
+ {
DBUG_PRINT("info", ("HA_STATUS_AUTO"));
+ if (m_table)
+ {
+ Ndb *ndb= get_ndb();
+
+ auto_increment_value=
+ ndb->readAutoIncrementValue((const NDBTAB *) m_table);
+ }
+ }
DBUG_VOID_RETURN;
}
@@ -3241,7 +3250,10 @@
DBUG_PRINT("info", ("Table schema version: %d",
tab->getObjectVersion()));
// Check if thread has stale local cache
- if (tab->getObjectStatus() == NdbDictionary::Object::Invalid)
+ // New transaction must not use old tables... (trans != 0)
+ // Running might...
+ if ((trans && tab->getObjectStatus() != NdbDictionary::Object::Retrieved)
+ || tab->getObjectStatus() == NdbDictionary::Object::Invalid)
{
invalidate_dictionary_cache(FALSE);
if (!(tab= dict->getTable(m_tabname, &tab_info)))
@@ -6966,6 +6978,8 @@
break;
Ndb_item *a= cond->next->ndb_item;
Ndb_item *b, *field, *value= NULL;
+ LINT_INIT(field);
+
switch (cond->ndb_item->argument_count()) {
case 1:
field=
@@ -7524,8 +7538,6 @@
DBUG_RETURN(FALSE);
}
-
-
/*
Create a table in NDB Cluster
*/
@@ -7660,7 +7672,7 @@
static void ndb_set_fragmentation(NDBTAB &tab, TABLE *form, uint pk_length)
{
- NDBTAB::FragmentType ftype;
+ NDBTAB::FragmentType ftype= NDBTAB::DistrKeyHash;
ushort node_group[MAX_PARTITIONS];
uint no_nodes= g_ndb_cluster_connection->no_db_nodes(), no_fragments, i;
DBUG_ENTER("ndb_set_fragmentation");
@@ -7691,10 +7703,15 @@
node_group[0]= 0;
for (i= 1; i < no_fragments; i++)
node_group[i]= UNDEF_NODEGROUP;
- if (opt_ndb_linear_hash)
- ftype= NDBTAB::DistrKeyLin;
- else
+ switch (opt_ndb_distribution_id)
+ {
+ case ND_KEYHASH:
ftype= NDBTAB::DistrKeyHash;
+ break;
+ case ND_LINHASH:
+ ftype= NDBTAB::DistrKeyLin;
+ break;
+ }
tab.setFragmentType(ftype);
tab.setNodeGroupIds(&node_group, no_fragments);
DBUG_VOID_RETURN;
--- 1.78/sql/ha_ndbcluster.h 2005-08-09 09:49:30 +02:00
+++ 1.79/sql/ha_ndbcluster.h 2005-08-27 07:49:55 +02:00
@@ -113,6 +113,8 @@
NDB_FUNC_TYPE neg_fun;
};
+enum ndb_distribution { ND_KEYHASH= 0, ND_LINHASH= 1 };
+
/*
Define what functions can be negated in condition pushdown.
Note, these HAVE to be in the same order as in definition enum
@@ -586,7 +588,7 @@
ulonglong *engine_data);
bool check_if_incompatible_data(HA_CREATE_INFO *info,
- uint table_changes);
+ uint table_changes);
private:
int alter_table_name(const char *to);
--- 1.59/storage/innobase/trx/trx0trx.c 2005-08-09 09:49:34 +02:00
+++ 1.60/storage/innobase/trx/trx0trx.c 2005-08-27 07:49:57 +02:00
@@ -30,8 +30,9 @@
copy MUST be equal to the one in mysql/sql/ha_innodb.cc ! */
void innobase_mysql_print_thd(
- FILE* f,
- void* thd);
+ FILE* f,
+ void* thd,
+ uint max_query_len);
/* Dummy session used currently in MySQL interface */
sess_t* trx_dummy_sess = NULL;
@@ -262,7 +263,7 @@
fputs(
" InnoDB: Error: Freeing a trx which is declared to be processing\n"
"InnoDB: inside InnoDB.\n", stderr);
- trx_print(stderr, trx);
+ trx_print(stderr, trx, 600);
putc('\n', stderr);
}
@@ -277,7 +278,7 @@
(ulong)trx->n_mysql_tables_in_use,
(ulong)trx->mysql_n_tables_locked);
- trx_print(stderr, trx);
+ trx_print(stderr, trx, 600);
ut_print_buf(stderr, (byte*)trx, sizeof(trx_t));
}
@@ -1651,16 +1652,18 @@
}
/**************************************************************************
-Prints info about a transaction to the standard output. The caller must
-own the kernel mutex and must have called
-innobase_mysql_prepare_print_arbitrary_thd(), unless he knows that MySQL or
-InnoDB cannot meanwhile change the info printed here. */
+Prints info about a transaction to the given file. The caller must own the
+kernel mutex and must have called
+innobase_mysql_prepare_print_arbitrary_thd(), unless he knows that MySQL
+or InnoDB cannot meanwhile change the info printed here. */
void
trx_print(
/*======*/
- FILE* f, /* in: output stream */
- trx_t* trx) /* in: transaction */
+ FILE* f, /* in: output stream */
+ trx_t* trx, /* in: transaction */
+ uint max_query_len) /* in: max query length to print, or 0 to
+ use the default max length */
{
ibool newline;
@@ -1755,7 +1758,7 @@
}
if (trx->mysql_thd != NULL) {
- innobase_mysql_print_thd(f, trx->mysql_thd);
+ innobase_mysql_print_thd(f, trx->mysql_thd, max_query_len);
}
}
--- 1.214/sql/ha_innodb.cc 2005-08-09 09:49:30 +02:00
+++ 1.215/sql/ha_innodb.cc 2005-08-27 07:49:54 +02:00
@@ -48,6 +48,10 @@
pthread_mutex_t innobase_share_mutex, /* to protect innobase_open_files */
prepare_commit_mutex; /* to force correct commit order in
binlog */
+ulong commit_threads= 0;
+pthread_mutex_t commit_threads_m;
+pthread_cond_t commit_cond;
+pthread_mutex_t commit_cond_m;
bool innodb_inited= 0;
/*-----------------------------------------------------------------*/
@@ -550,19 +554,20 @@
}
/*****************************************************************
-Prints info of a THD object (== user session thread) to the
-standard output. NOTE that /mysql/innobase/trx/trx0trx.c must contain
-the prototype for this function! */
+Prints info of a THD object (== user session thread) to the given file.
+NOTE that /mysql/innobase/trx/trx0trx.c must contain the prototype for
+this function! */
extern "C"
void
innobase_mysql_print_thd(
/*=====================*/
- FILE* f, /* in: output stream */
- void* input_thd)/* in: pointer to a MySQL THD object */
+ FILE* f, /* in: output stream */
+ void* input_thd, /* in: pointer to a MySQL THD object */
+ uint max_query_len) /* in: max query length to print, or 0 to
+ use the default max length */
{
const THD* thd;
const char* s;
- char buf[301];
thd = (const THD*) input_thd;
@@ -589,25 +594,47 @@
}
if ((s = thd->query)) {
- /* determine the length of the query string */
- uint32 i, len;
+ /* 3100 is chosen because currently 3000 is the maximum
+ max_query_len we ever give this. */
+ char buf[3100];
+ uint len;
+
+ /* If buf is too small, we dynamically allocate storage
+ in this. */
+ char* dyn_str = NULL;
+
+ /* Points to buf or dyn_str. */
+ char* str = buf;
+
+ if (max_query_len == 0)
+ {
+ /* ADDITIONAL SAFETY: the default is to print at
+ most 300 chars to reduce the probability of a
+ seg fault if there is a race in
+ thd->query_length in MySQL; after May 14, 2004
+ probably no race any more, but better be
+ safe */
+ max_query_len = 300;
+ }
- len = thd->query_length;
+ len = min(thd->query_length, max_query_len);
- if (len > 300) {
- len = 300; /* ADDITIONAL SAFETY: print at most
- 300 chars to reduce the probability of
- a seg fault if there is a race in
- thd->query_length in MySQL; after
- May 14, 2004 probably no race any more,
- but better be safe */
+ if (len > (sizeof(buf) - 1))
+ {
+ dyn_str = my_malloc(len + 1, MYF(0));
+ str = dyn_str;
}
- /* Use strmake to reduce the timeframe
- for a race, compared to fwrite() */
- i= (uint) (strmake(buf, s, len) - buf);
+ /* Use strmake to reduce the timeframe for a race,
+ compared to fwrite() */
+ len = (uint) (strmake(str, s, len) - str);
putc('\n', f);
- fwrite(buf, 1, i, f);
+ fwrite(str, 1, len, f);
+
+ if (dyn_str)
+ {
+ my_free(dyn_str, MYF(0));
+ }
}
putc('\n', f);
@@ -948,9 +975,9 @@
trx = check_trx_exists(thd);
if (trx->has_search_latch) {
ut_print_timestamp(stderr);
- fprintf(stderr,
-" InnoDB: Error: the calling thread is holding the adaptive search\n"
-"InnoDB: latch though calling innobase_query_caching_of_table_permitted\n");
+ sql_print_error("The calling thread is holding the adaptive "
+ "search, latch though calling "
+ "innobase_query_caching_of_table_permitted.");
}
innobase_release_stat_resources(trx);
@@ -1266,9 +1293,8 @@
&srv_log_group_home_dirs);
if (ret == FALSE || innobase_mirrored_log_groups != 1) {
- fprintf(stderr,
- "InnoDB: syntax error in innodb_log_group_home_dir\n"
- "InnoDB: or a wrong number of mirrored log groups\n");
+ sql_print_error("syntax error in innodb_log_group_home_dir, or a "
+ "wrong number of mirrored log groups");
my_free(internal_innobase_data_file_path,
MYF(MY_ALLOW_ZERO_PTR));
@@ -1367,6 +1393,9 @@
(hash_get_key) innobase_get_key, 0, 0);
pthread_mutex_init(&innobase_share_mutex, MY_MUTEX_INIT_FAST);
pthread_mutex_init(&prepare_commit_mutex, MY_MUTEX_INIT_FAST);
+ pthread_mutex_init(&commit_threads_m, MY_MUTEX_INIT_FAST);
+ pthread_mutex_init(&commit_cond_m, MY_MUTEX_INIT_FAST);
+ pthread_cond_init(&commit_cond, NULL);
innodb_inited= 1;
/* If this is a replication slave and we needed to do a crash recovery,
@@ -1416,6 +1445,9 @@
MYF(MY_ALLOW_ZERO_PTR));
pthread_mutex_destroy(&innobase_share_mutex);
pthread_mutex_destroy(&prepare_commit_mutex);
+ pthread_mutex_destroy(&commit_threads_m);
+ pthread_mutex_destroy(&commit_cond_m);
+ pthread_cond_destroy(&commit_cond);
}
DBUG_RETURN(err);
@@ -1542,8 +1574,10 @@
reserve the kernel mutex, we have to release the search system latch
first to obey the latching order. */
- innobase_release_stat_resources(trx);
-
+ if (trx->has_search_latch) {
+ trx_search_latch_release_if_reserved(trx);
+ }
+
/* The flag trx->active_trans is set to 1 in
1. ::external_lock(),
@@ -1562,11 +1596,9 @@
if (trx->active_trans == 0
&& trx->conc_state != TRX_NOT_STARTED) {
- fprintf(stderr,
-"InnoDB: Error: trx->active_trans == 0\n"
-"InnoDB: but trx->conc_state != TRX_NOT_STARTED\n");
+ sql_print_error("trx->active_trans == 0, but trx->conc_state != "
+ "TRX_NOT_STARTED");
}
-
if (all
|| (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))) {
@@ -1575,18 +1607,43 @@
/* We need current binlog position for ibbackup to work.
Note, the position is current because of prepare_commit_mutex */
+retry:
+ if (srv_commit_concurrency > 0)
+ {
+ pthread_mutex_lock(&commit_cond_m);
+ commit_threads++;
+ if (commit_threads > srv_commit_concurrency)
+ {
+ commit_threads--;
+ pthread_cond_wait(&commit_cond, &commit_cond_m);
+ pthread_mutex_unlock(&commit_cond_m);
+ goto retry;
+ }
+ else
+ pthread_mutex_unlock(&commit_cond_m);
+ }
+
trx->mysql_log_file_name = mysql_bin_log.get_log_fname();
trx->mysql_log_offset =
(ib_longlong)mysql_bin_log.get_log_file()->pos_in_file;
innobase_commit_low(trx);
+ if (srv_commit_concurrency > 0)
+ {
+ pthread_mutex_lock(&commit_cond_m);
+ commit_threads--;
+ pthread_cond_signal(&commit_cond);
+ pthread_mutex_unlock(&commit_cond_m);
+ }
+
if (trx->active_trans == 2) {
pthread_mutex_unlock(&prepare_commit_mutex);
}
+
trx->active_trans = 0;
-
+
} else {
/* We just mark the SQL statement ended and do not do a
transaction commit */
@@ -1606,7 +1663,11 @@
/* Tell the InnoDB server that there might be work for utility
threads: */
+ if (trx->declared_to_be_inside_innodb) {
+ /* Release our possible ticket in the FIFO */
+ srv_conc_force_exit_innodb(trx);
+ }
srv_active_wake_master_thread();
DBUG_RETURN(0);
@@ -1813,21 +1874,23 @@
if (ret != 0) {
ut_print_timestamp(stderr);
- fprintf(stderr,
-" InnoDB: Error: MySQL synchronous replication\n"
-"InnoDB: was not able to send the binlog to the slave within the\n"
-"InnoDB: timeout %lu. We assume that the slave has become inaccessible,\n"
-"InnoDB: and switch off synchronous replication until the communication.\n"
-"InnoDB: to the slave works again.\n",
- thd->variables.sync_replication_timeout);
- fprintf(stderr,
-"InnoDB: MySQL synchronous replication has sent binlog\n"
-"InnoDB: to the slave up to file %s, position %lu\n", innobase_repl_file_name,
- (ulong)innobase_repl_pos);
- fprintf(stderr,
-"InnoDB: This transaction needs it to be sent up to\n"
-"InnoDB: file %s, position %lu\n", trx->repl_wait_binlog_name,
- (ulong)trx->repl_wait_binlog_pos);
+ sql_print_error("MySQL synchronous replication was "
+ "not able to send the binlog to the "
+ "slave within the timeout %lu. We "
+ "assume that the slave has become "
+ "inaccessible, and switch off "
+ "synchronous replication until the "
+ "communication to the slave works "
+ "again. MySQL synchronous replication "
+ "has sent binlog to the slave up to "
+ "file %s, position %lu. This "
+ "transaction needs it to be sent up "
+ "to file %s, position %lu.",
+ thd->variables.sync_replication_timeout,
+ innobase_repl_file_name,
+ (ulong) innobase_repl_pos,
+ trx->repl_wait_binlog_name,
+ (ulong) trx->repl_wait_binlog_pos);
innobase_repl_state = 0;
@@ -1878,9 +1941,9 @@
if (innobase_repl_state == 0) {
ut_print_timestamp(stderr);
- fprintf(stderr,
-" InnoDB: Switching MySQL synchronous replication on again at\n"
-"InnoDB: binlog file %s, position %lu\n", log_file_name, (ulong)end_offset);
+ sql_print_warning("Switching MySQL synchronous replication on "
+ "again at binlog file %s, position %lu",
+ log_file_name, (ulong) end_offset);
innobase_repl_state = 1;
}
@@ -1897,14 +1960,14 @@
|| (cmp == 0 && end_offset < innobase_repl_pos)) {
ut_print_timestamp(stderr);
- fprintf(stderr,
-" InnoDB: Error: MySQL synchronous replication has sent binlog\n"
-"InnoDB: to the slave up to file %s, position %lu\n", innobase_repl_file_name,
- (ulong)innobase_repl_pos);
- fprintf(stderr,
-"InnoDB: but now MySQL reports that it sent the binlog only up to\n"
-"InnoDB: file %s, position %lu\n", log_file_name, (ulong)end_offset);
-
+ sql_print_error("MySQL synchronous replication has "
+ "sent binlog to the slave up to file "
+ "%s, position %lu, but now MySQL "
+ "reports that it sent the binlog only "
+ "up to file %s, position %lu",
+ innobase_repl_file_name,
+ (ulong) innobase_repl_pos,
+ log_file_name, (ulong) end_offset);
}
}
@@ -2146,16 +2209,21 @@
ut_a(trx);
- if (trx->conc_state != TRX_NOT_STARTED) {
- ut_print_timestamp(stderr);
-
- fprintf(stderr,
-" InnoDB: Warning: MySQL is closing a connection"
-"InnoDB: that has an active InnoDB transaction. We roll back that\n"
-"InnoDB: transaction. %lu row modifications to roll back.\n",
- (ulong)trx->undo_no.low);
+ if (trx->active_trans == 0
+ && trx->conc_state != TRX_NOT_STARTED) {
+
+ sql_print_error("trx->active_trans == 0, but trx->conc_state != "
+ "TRX_NOT_STARTED");
}
+
+ if (trx->conc_state != TRX_NOT_STARTED &&
+ global_system_variables.log_warnings)
+ sql_print_warning("MySQL is closing a connection that has an active "
+ "InnoDB transaction. %lu row modifications will "
+ "roll back.",
+ (ulong)trx->undo_no.low);
+
innobase_rollback_trx(trx);
trx_free_for_mysql(trx);
@@ -2306,15 +2374,17 @@
norm_name, NULL);
if (NULL == ib_table) {
ut_print_timestamp(stderr);
- fprintf(stderr, " InnoDB error:\n"
-"Cannot find table %s from the internal data dictionary\n"
-"of InnoDB though the .frm file for the table exists. Maybe you\n"
-"have deleted and recreated InnoDB data files but have forgotten\n"
-"to delete the corresponding .frm files of InnoDB tables, or you\n"
-"have moved .frm files to another database?\n"
-"Look from section 15.1 of http://www.innodb.com/ibman.html\n"
-"how you can resolve the problem.\n",
- norm_name);
+ sql_print_error("Cannot find table %s from the internal data "
+ "dictionary\nof InnoDB though the .frm file "
+ "for the table exists. Maybe you\nhave "
+ "deleted and recreated InnoDB data files but "
+ "have forgotten\nto delete the corresponding "
+ ".frm files of InnoDB tables, or you\n"
+ "have moved .frm files to another database?\n"
+ "Look from section 15.1 of "
+ "http://www.innodb.com/ibman.html\n"
+ "how you can resolve the problem.\n",
+ norm_name);
free_share(share);
my_free((char*) upd_buff, MYF(0));
my_errno = ENOENT;
@@ -2324,14 +2394,15 @@
if (ib_table->ibd_file_missing && !thd->tablespace_op) {
ut_print_timestamp(stderr);
- fprintf(stderr, " InnoDB error:\n"
-"MySQL is trying to open a table handle but the .ibd file for\n"
-"table %s does not exist.\n"
-"Have you deleted the .ibd file from the database directory under\n"
-"the MySQL datadir, or have you used DISCARD TABLESPACE?\n"
-"Look from section 15.1 of http://www.innodb.com/ibman.html\n"
-"how you can resolve the problem.\n",
- norm_name);
+ sql_print_error("MySQL is trying to open a table handle but "
+ "the .ibd file for\ntable %s does not exist.\n"
+ "Have you deleted the .ibd file from the "
+ "database directory under\nthe MySQL datadir, "
+ "or have you used DISCARD TABLESPACE?\n"
+ "Look from section 15.1 of "
+ "http://www.innodb.com/ibman.html\n"
+ "how you can resolve the problem.\n",
+ norm_name);
free_share(share);
my_free((char*) upd_buff, MYF(0));
my_errno = ENOENT;
@@ -2357,9 +2428,8 @@
if (!row_table_got_default_clust_index(ib_table)) {
if (primary_key >= MAX_KEY) {
- fprintf(stderr,
- "InnoDB: Error: table %s has a primary key in InnoDB\n"
- "InnoDB: data dictionary, but not in MySQL!\n", name);
+ sql_print_error("Table %s has a primary key in InnoDB data "
+ "dictionary, but not in MySQL!", name);
}
((row_prebuilt_t*)innobase_prebuilt)
@@ -2373,16 +2443,15 @@
ref_length = table->key_info[primary_key].key_length;
} else {
if (primary_key != MAX_KEY) {
- fprintf(stderr,
- "InnoDB: Error: table %s has no primary key in InnoDB\n"
- "InnoDB: data dictionary, but has one in MySQL!\n"
- "InnoDB: If you created the table with a MySQL\n"
- "InnoDB: version < 3.23.54 and did not define a primary\n"
- "InnoDB: key, but defined a unique key with all non-NULL\n"
- "InnoDB: columns, then MySQL internally treats that key\n"
- "InnoDB: as the primary key. You can fix this error by\n"
- "InnoDB: dump + DROP + CREATE + reimport of the table.\n",
- name);
+ sql_print_error("Table %s has no primary key in InnoDB data "
+ "dictionary, but has one in MySQL! If you "
+ "created the table with a MySQL version < "
+ "3.23.54 and did not define a primary key, "
+ "but defined a unique key with all non-NULL "
+ "columns, then MySQL internally treats that "
+ "key as the primary key. You can fix this "
+ "error by dump + DROP + CREATE + reimport "
+ "of the table.", name);
}
((row_prebuilt_t*)innobase_prebuilt)
@@ -2399,10 +2468,9 @@
and it will never be updated anyway. */
if (key_used_on_scan != MAX_KEY) {
- fprintf(stderr,
-"InnoDB: Warning: table %s key_used_on_scan is %lu even though there is no\n"
-"InnoDB: primary key inside InnoDB.\n",
- name, (ulong)key_used_on_scan);
+ sql_print_warning("Table %s key_used_on_scan is %lu even "
+ "though there is no primary key inside "
+ "InnoDB.", name, (ulong) key_used_on_scan);
}
}
@@ -2557,9 +2625,10 @@
charset = get_charset(charset_number, MYF(MY_WME));
if (charset == NULL) {
- fprintf(stderr,
-"InnoDB: fatal error: InnoDB needs charset %lu for doing a comparison,\n"
-"InnoDB: but MySQL cannot find that charset.\n", (ulong)charset_number);
+ sql_print_error("InnoDB needs charset %lu for doing "
+ "a comparison, but MySQL cannot "
+ "find that charset.",
+ (ulong) charset_number);
ut_a(0);
}
}
@@ -3126,11 +3195,11 @@
if (prebuilt->trx !=
(trx_t*) current_thd->ha_data[innobase_hton.slot]) {
- fprintf(stderr,
-"InnoDB: Error: the transaction object for the table handle is at\n"
-"InnoDB: %p, but for the current thread it is at %p\n",
- prebuilt->trx,
- (trx_t*) current_thd->ha_data[innobase_hton.slot]);
+ sql_print_error("The transaction object for the table handle is at "
+ "%p, but for the current thread it is at %p",
+ prebuilt->trx,
+ (trx_t*) current_thd->ha_data[innobase_hton.slot]);
+
fputs("InnoDB: Dump of 200 bytes around prebuilt: ", stderr);
ut_print_buf(stderr, ((const byte*)prebuilt) - 100, 200);
fputs("\n"
@@ -3617,9 +3686,9 @@
if (last_query_id != user_thd->query_id) {
ut_print_timestamp(stderr);
- fprintf(stderr,
-" InnoDB: Error: last_query_id is %lu != user_thd_query_id is %lu\n",
- (ulong)last_query_id, (ulong)user_thd->query_id);
+ sql_print_error("last_query_id is %lu != user_thd_query_id is "
+ "%lu", (ulong) last_query_id,
+ (ulong) user_thd->query_id);
mem_analyze_corruption((byte *) prebuilt->trx);
ut_error;
}
@@ -3912,9 +3981,10 @@
}
if (!prebuilt->index) {
- sql_print_error(
-"Innodb could not find key n:o %u with name %s from dict cache for table %s",
- keynr, key ? key->name : "NULL", prebuilt->table->name);
+ sql_print_error("Innodb could not find key n:o %u with name %s "
+ "from dict cache for table %s",
+ keynr, key ? key->name : "NULL",
+ prebuilt->table->name);
DBUG_RETURN(1);
}
@@ -4280,9 +4350,8 @@
table. */
if (len != ref_length) {
- fprintf(stderr,
- "InnoDB: Error: stored ref len is %lu, but table ref len is %lu\n",
- (ulong)len, (ulong)ref_length);
+ sql_print_error("Stored ref len is %lu, but table ref len is %lu",
+ (ulong) len, (ulong) ref_length);
}
}
@@ -4487,11 +4556,13 @@
|| col_type == DATA_FLOAT
|| col_type == DATA_DOUBLE
|| col_type == DATA_DECIMAL) {
- fprintf(stderr,
-"InnoDB: error: MySQL is trying to create a column prefix index field\n"
-"InnoDB: on an inappropriate data type. Table name %s, column name %s.\n",
- table_name, key_part->field->field_name);
-
+ sql_print_error("MySQL is trying to create a column "
+ "prefix index field, on an "
+ "inappropriate data type. Table "
+ "name %s, column name %s.",
+ table_name,
+ key_part->field->field_name);
+
prefix_len = 0;
}
} else {
@@ -5282,6 +5353,7 @@
dict_table_t* ib_table;
dict_index_t* index;
ha_rows rec_per_key;
+ ib_longlong n_rows;
ulong j;
ulong i;
char path[FN_REFLEN];
@@ -5346,7 +5418,30 @@
}
if (flag & HA_STATUS_VARIABLE) {
- records = (ha_rows)ib_table->stat_n_rows;
+ n_rows = ib_table->stat_n_rows;
+
+ /* Because we do not protect stat_n_rows by any mutex in a
+ delete, it is theoretically possible that the value can be
+ smaller than zero! TODO: fix this race.
+
+ The MySQL optimizer seems to assume in a left join that n_rows
+ is an accurate estimate if it is zero. Of course, it is not,
+ since we do not have any locks on the rows yet at this phase.
+ Since SHOW TABLE STATUS seems to call this function with the
+ HA_STATUS_TIME flag set, while the left join optizer does not
+ set that flag, we add one to a zero value if the flag is not
+ set. That way SHOW TABLE STATUS will show the best estimate,
+ while the optimizer never sees the table empty. */
+
+ if (n_rows < 0) {
+ n_rows = 0;
+ }
+
+ if (n_rows == 0 && !(flag & HA_STATUS_TIME)) {
+ n_rows++;
+ }
+
+ records = (ha_rows)n_rows;
deleted = 0;
data_file_length = ((ulonglong)
ib_table->stat_clustered_index_size)
@@ -5374,12 +5469,14 @@
for (i = 0; i < table->s->keys; i++) {
if (index == NULL) {
ut_print_timestamp(stderr);
- fprintf(stderr,
-" InnoDB: Error: table %s contains less indexes inside InnoDB\n"
-"InnoDB: than are defined in the MySQL .frm file. Have you mixed up\n"
-"InnoDB: .frm files from different installations? See section\n"
-"InnoDB: 15.1 at http://www.innodb.com/ibman.html\n",
- ib_table->name);
+ sql_print_error("Table %s contains less "
+ "indexes inside InnoDB than "
+ "are defined in the MySQL "
+ ".frm file. Have you mixed up "
+ ".frm files from different "
+ "installations? See section "
+ "15.1 at http://www.innodb.com/ibman.html",
+ ib_table->name);
break;
}
@@ -5387,15 +5484,21 @@
if (j + 1 > index->n_uniq) {
ut_print_timestamp(stderr);
- fprintf(stderr,
-" InnoDB: Error: index %s of %s has %lu columns unique inside InnoDB\n"
-"InnoDB: but MySQL is asking statistics for %lu columns. Have you mixed up\n"
-"InnoDB: .frm files from different installations? See section\n"
-"InnoDB: 15.1 at http://www.innodb.com/ibman.html\n",
- index->name,
- ib_table->name,
- (unsigned long) index->n_uniq,
- j + 1);
+ sql_print_error("Index %s of %s has "
+ "%lu columns unique "
+ "inside InnoDB, but "
+ "MySQL is asking "
+ "statistics for %lu "
+ "columns. Have you "
+ "mixed up .frm files "
+ "from different "
+ "installations? See "
+ "section 15.1 at "
+ "http://www.innodb.com/ibman.html",
+ index->name,
+ ib_table->name,
+ (unsigned long)
+ index->n_uniq, j + 1);
break;
}
@@ -5943,9 +6046,9 @@
if (prebuilt->stored_select_lock_type != LOCK_S
&& prebuilt->stored_select_lock_type != LOCK_X) {
- fprintf(stderr,
-"InnoDB: Error: stored_select_lock_type is %lu inside ::start_stmt()!\n",
- prebuilt->stored_select_lock_type);
+ sql_print_error("stored_select_lock_type is %lu inside "
+ "::start_stmt()!",
+ prebuilt->stored_select_lock_type);
/* Set the value to LOCK_X: this is just fault
tolerance, we do not know what the correct value
@@ -6721,9 +6824,8 @@
error = 0;
} else {
/* This should not happen in a consistent read */
- fprintf(stderr,
-"InnoDB: Error: consistent read of auto-inc column returned %lu\n",
- (ulong)error);
+ sql_print_error("Consistent read of auto-inc column "
+ "returned %lu", (ulong) error);
auto_inc = -1;
goto func_exit;
@@ -6780,9 +6882,8 @@
initialized. */
ut_print_timestamp(stderr);
- fprintf(stderr,
- " InnoDB: Error: error %lu in ::get_auto_increment()\n",
- (ulong)error);
+ sql_print_error("Error %lu in ::get_auto_increment()",
+ (ulong) error);
return(~(ulonglong) 0);
}
@@ -6857,8 +6958,8 @@
return(result);
}
- ref1 += key_part->length;
- ref2 += key_part->length;
+ ref1 += key_part->store_length;
+ ref2 += key_part->store_length;
}
return(0);
@@ -7039,7 +7140,7 @@
return(0);
}
- trx->xid=thd->transaction.xid;
+ trx->xid=thd->transaction.xid_state.xid;
/* Release a possible FIFO ticket and search latch. Since we will
reserve the kernel mutex, we have to release the search system latch
@@ -7049,9 +7150,8 @@
if (trx->active_trans == 0 && trx->conc_state != TRX_NOT_STARTED) {
- fprintf(stderr,
-"InnoDB: Error: trx->active_trans == 0\n"
-"InnoDB: but trx->conc_state != TRX_NOT_STARTED\n");
+ sql_print_error("trx->active_trans == 0, but trx->conc_state != "
+ "TRX_NOT_STARTED");
}
if (all
--- 1.209/BitKeeper/etc/ignore 2005-08-09 11:05:02 +02:00
+++ 1.210/BitKeeper/etc/ignore 2005-08-27 07:49:38 +02:00
@@ -1267,6 +1267,7 @@
storage/ndb/test/tools/ndb_cpcc
storage/ndb/test/tools/restart
storage/ndb/test/tools/verify_index
+storage/ndb/tools/ndb_config
storage/ndb/tools/ndb_delete_all
storage/ndb/tools/ndb_desc
storage/ndb/tools/ndb_drop_index
@@ -1286,7 +1287,9 @@
support-files/MacOSX/Info.plist
support-files/MacOSX/ReadMe.txt
support-files/MacOSX/StartupParameters.plist
+support-files/MacOSX/postflight
support-files/MacOSX/postinstall
+support-files/MacOSX/preflight
support-files/MacOSX/preinstall
support-files/binary-configure
support-files/my-huge.cnf
@@ -1371,4 +1374,3 @@
vio/test-sslclient
vio/test-sslserver
vio/viotest-ssl
-storage/ndb/tools/ndb_config
--- 1.12/storage/ndb/src/kernel/Makefile.am 2005-04-29 16:30:22 +02:00
+++ 1.13/storage/ndb/src/kernel/Makefile.am 2005-08-27 07:49:57 +02:00
@@ -23,7 +23,6 @@
-Iblocks/backup \
-Iblocks/dbutil \
-Iblocks/suma \
- -Iblocks/grep \
-Iblocks/dbtux \
-Iblocks
@@ -42,7 +41,6 @@
blocks/backup/libbackup.a \
blocks/dbutil/libdbutil.a \
blocks/suma/libsuma.a \
- blocks/grep/libgrep.a \
blocks/dbtux/libdbtux.a \
blocks/libblocks.a \
vm/libkernel.a \
--- 1.10/storage/ndb/src/kernel/blocks/Makefile.am 2005-07-12 14:03:27 +02:00
+++ 1.11/storage/ndb/src/kernel/blocks/Makefile.am 2005-08-27 07:49:57 +02:00
@@ -13,7 +13,6 @@
backup \
dbutil \
suma \
- grep \
dbtux
noinst_LIBRARIES = libblocks.a
| Thread |
|---|
| • bk commit into 5.1 tree (jonas:1.1973) | jonas | 27 Aug |