summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--BitKeeper/etc/logging_ok2
-rw-r--r--include/my_sys.h1
-rw-r--r--myisam/myisampack.c9
-rw-r--r--myisammrg/myrg_open.c2
-rw-r--r--mysql-test/r/group_by.result9
-rw-r--r--mysql-test/r/ndb_multi.result22
-rw-r--r--mysql-test/t/group_by.test7
-rw-r--r--mysql-test/t/ndb_multi.test24
-rw-r--r--mysys/my_getwd.c22
-rw-r--r--ndb/include/ndbapi/NdbDictionary.hpp5
-rw-r--r--ndb/src/ndbapi/NdbDictionaryImpl.cpp11
-rw-r--r--sql/ha_myisammrg.cc28
-rw-r--r--sql/ha_ndbcluster.cc97
-rw-r--r--sql/ha_ndbcluster.h4
-rw-r--r--sql/protocol.cc2
-rw-r--r--sql/sql_select.cc5
16 files changed, 214 insertions, 36 deletions
diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok
index e4de8c6ebf2..330d28daf52 100644
--- a/BitKeeper/etc/logging_ok
+++ b/BitKeeper/etc/logging_ok
@@ -45,6 +45,8 @@ dlenev@build.mysql.com
dlenev@jabberwock.localdomain
dlenev@mysql.com
ejonore@mc03.ndb.mysql.com
+evgen@moonbone.(none)
+evgen@moonbone.local
gbichot@quadita2.mysql.com
gbichot@quadxeon.mysql.com
georg@beethoven.local
diff --git a/include/my_sys.h b/include/my_sys.h
index b54e2581bd4..7ead643a9c6 100644
--- a/include/my_sys.h
+++ b/include/my_sys.h
@@ -609,6 +609,7 @@ extern uint dirname_part(my_string to,const char *name);
extern uint dirname_length(const char *name);
#define base_name(A) (A+dirname_length(A))
extern int test_if_hard_path(const char *dir_name);
+extern my_bool has_path(const char *name);
extern char *convert_dirname(char *to, const char *from, const char *from_end);
extern void to_unix_path(my_string name);
extern my_string fn_ext(const char *name);
diff --git a/myisam/myisampack.c b/myisam/myisampack.c
index 263a468d96d..88f38be3c54 100644
--- a/myisam/myisampack.c
+++ b/myisam/myisampack.c
@@ -31,6 +31,7 @@
#define __GNU_LIBRARY__ /* Skip warnings in getopt.h */
#endif
#include <my_getopt.h>
+#include <assert.h>
#if INT_MAX > 32767
#define BITS_SAVED 32
@@ -1991,7 +1992,9 @@ static void write_bits (register ulong value, register uint bits)
{
reg3 uint byte_buff;
bits= (uint) -file_buffer.bits;
- byte_buff=file_buffer.current_byte | (uint) (value >> bits);
+ DBUG_ASSERT(bits <= 8 * sizeof(value));
+ byte_buff= (file_buffer.current_byte |
+ ((bits != 8 * sizeof(value)) ? (uint) (value >> bits) : 0));
#if BITS_SAVED == 32
*file_buffer.pos++= (byte) (byte_buff >> 24) ;
*file_buffer.pos++= (byte) (byte_buff >> 16) ;
@@ -1999,7 +2002,9 @@ static void write_bits (register ulong value, register uint bits)
*file_buffer.pos++= (byte) (byte_buff >> 8) ;
*file_buffer.pos++= (byte) byte_buff;
- value&=(1 << bits)-1;
+ DBUG_ASSERT(bits <= 8 * sizeof(ulong));
+ if (bits != 8 * sizeof(value))
+ value&= (((ulong) 1) << bits) - 1;
#if BITS_SAVED == 16
if (bits >= sizeof(uint))
{
diff --git a/myisammrg/myrg_open.c b/myisammrg/myrg_open.c
index a59ccb7d966..0dc2f4f9768 100644
--- a/myisammrg/myrg_open.c
+++ b/myisammrg/myrg_open.c
@@ -80,7 +80,7 @@ MYRG_INFO *myrg_open(const char *name, int mode, int handle_locking)
continue; /* Skip comments */
}
- if (!test_if_hard_path(buff))
+ if (!has_path(buff))
{
VOID(strmake(name_buff+dir_length,buff,
sizeof(name_buff)-1-dir_length));
diff --git a/mysql-test/r/group_by.result b/mysql-test/r/group_by.result
index a8766907fa5..b0c00a51722 100644
--- a/mysql-test/r/group_by.result
+++ b/mysql-test/r/group_by.result
@@ -702,3 +702,12 @@ c
val-74
val-98
drop table t1,t2;
+create table t1 (b int4 unsigned not null);
+insert into t1 values(3000000000);
+select * from t1;
+b
+3000000000
+select min(b) from t1;
+min(b)
+3000000000
+drop table t1;
diff --git a/mysql-test/r/ndb_multi.result b/mysql-test/r/ndb_multi.result
index 5696fda1c07..2080be241e8 100644
--- a/mysql-test/r/ndb_multi.result
+++ b/mysql-test/r/ndb_multi.result
@@ -13,6 +13,26 @@ a
show status like 'handler_discover%';
Variable_name Value
Handler_discover 0
+select * from t1;
+a
+2
+drop table t1;
+create table t1 (a int) engine=ndbcluster;
+insert into t1 value (2);
+select * from t1;
+a
+2
+show status like 'handler_discover%';
+Variable_name Value
+Handler_discover 0
+drop table t1;
+create table t1 (a int) engine=ndbcluster;
+insert into t1 value (2);
+select * from t1;
+ERROR HY000: Got error 241 'Invalid schema object version' from ndbcluster
+select * from t1;
+a
+2
flush status;
select * from t1;
a
@@ -20,7 +40,7 @@ a
update t1 set a=3 where a=2;
show status like 'handler_discover%';
Variable_name Value
-Handler_discover 1
+Handler_discover 0
create table t3 (a int not null primary key, b varchar(22),
c int, last_col text) engine=ndb;
insert into t3 values(1, 'Hi!', 89, 'Longtext column');
diff --git a/mysql-test/t/group_by.test b/mysql-test/t/group_by.test
index 46e58cd00fd..fbd39019e6d 100644
--- a/mysql-test/t/group_by.test
+++ b/mysql-test/t/group_by.test
@@ -515,3 +515,10 @@ explain select c from t2 where a = 2 and b = 'val-2' group by c;
select c from t2 where a = 2 and b = 'val-2' group by c;
drop table t1,t2;
+# Test for BUG#9298 "Wrong handling of int4 unsigned columns in GROUP functions"
+# (the actual problem was with protocol code, not GROUP BY)
+create table t1 (b int4 unsigned not null);
+insert into t1 values(3000000000);
+select * from t1;
+select min(b) from t1;
+drop table t1;
diff --git a/mysql-test/t/ndb_multi.test b/mysql-test/t/ndb_multi.test
index 24651913a79..85950c72cf9 100644
--- a/mysql-test/t/ndb_multi.test
+++ b/mysql-test/t/ndb_multi.test
@@ -18,6 +18,30 @@ select * from t1;
select * from t2;
show status like 'handler_discover%';
+# Check dropping and recreating table on same server
+connect (con1,localhost,,,test);
+connect (con2,localhost,,,test);
+connection con1;
+select * from t1;
+connection con2;
+drop table t1;
+create table t1 (a int) engine=ndbcluster;
+insert into t1 value (2);
+connection con1;
+select * from t1;
+
+# Check dropping and recreating table on different server
+connection server2;
+show status like 'handler_discover%';
+drop table t1;
+create table t1 (a int) engine=ndbcluster;
+insert into t1 value (2);
+connection server1;
+# Currently a retry is required remotely
+--error 1296
+select * from t1;
+select * from t1;
+
# Connect to server2 and use the tables from there
connection server2;
flush status;
diff --git a/mysys/my_getwd.c b/mysys/my_getwd.c
index d6f647254e8..89f949eca27 100644
--- a/mysys/my_getwd.c
+++ b/mysys/my_getwd.c
@@ -192,3 +192,25 @@ int test_if_hard_path(register const char *dir_name)
return FALSE;
#endif
} /* test_if_hard_path */
+
+
+/*
+ Test if a name contains an (absolute or relative) path.
+
+ SYNOPSIS
+ has_path()
+ name The name to test.
+
+ RETURN
+ TRUE name contains a path.
+ FALSE name does not contain a path.
+*/
+
+my_bool has_path(const char *name)
+{
+ return test(strchr(name, FN_LIBCHAR))
+#ifdef FN_DEVCHAR
+ || test(strchr(name, FN_DEVCHAR))
+#endif
+ ;
+}
diff --git a/ndb/include/ndbapi/NdbDictionary.hpp b/ndb/include/ndbapi/NdbDictionary.hpp
index 6aa675a2319..0e4f506c604 100644
--- a/ndb/include/ndbapi/NdbDictionary.hpp
+++ b/ndb/include/ndbapi/NdbDictionary.hpp
@@ -75,8 +75,11 @@ public:
Changed, ///< The object has been modified in memory
///< and has to be commited in NDB Kernel for
///< changes to take effect
- Retrieved ///< The object exist and has been read
+ Retrieved, ///< The object exist and has been read
///< into main memory from NDB Kernel
+ Invalid ///< The object has been invalidated
+ ///< and should not be used
+
};
/**
diff --git a/ndb/src/ndbapi/NdbDictionaryImpl.cpp b/ndb/src/ndbapi/NdbDictionaryImpl.cpp
index fb2e0d673cd..4523ae2c261 100644
--- a/ndb/src/ndbapi/NdbDictionaryImpl.cpp
+++ b/ndb/src/ndbapi/NdbDictionaryImpl.cpp
@@ -1448,6 +1448,7 @@ int NdbDictionaryImpl::alterTable(NdbTableImpl &impl)
// 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();
}
@@ -1747,8 +1748,8 @@ NdbDictionaryImpl::dropTable(const char * name)
DBUG_PRINT("info",("INCOMPATIBLE_VERSION internal_name: %s", internalTableName));
m_localHash.drop(internalTableName);
-
m_globalHash->lock();
+ tab->m_status = NdbDictionary::Object::Invalid;
m_globalHash->drop(tab);
m_globalHash->unlock();
DBUG_RETURN(dropTable(name));
@@ -1792,10 +1793,11 @@ NdbDictionaryImpl::dropTable(NdbTableImpl & impl)
int ret = m_receiver.dropTable(impl);
if(ret == 0 || m_error.code == 709){
const char * internalTableName = impl.m_internalName.c_str();
+
m_localHash.drop(internalTableName);
-
m_globalHash->lock();
+ impl.m_status = NdbDictionary::Object::Invalid;
m_globalHash->drop(&impl);
m_globalHash->unlock();
@@ -1889,6 +1891,7 @@ NdbDictionaryImpl::invalidateObject(NdbTableImpl & impl)
m_localHash.drop(internalTableName);
m_globalHash->lock();
+ impl.m_status = NdbDictionary::Object::Invalid;
m_globalHash->drop(&impl);
m_globalHash->unlock();
return 0;
@@ -2152,8 +2155,8 @@ NdbDictionaryImpl::dropIndex(const char * indexName,
m_ndb.internalizeTableName(indexName); // Index is also a table
m_localHash.drop(internalIndexName);
-
m_globalHash->lock();
+ idx->m_table->m_status = NdbDictionary::Object::Invalid;
m_globalHash->drop(idx->m_table);
m_globalHash->unlock();
return dropIndex(indexName, tableName);
@@ -2187,8 +2190,8 @@ NdbDictionaryImpl::dropIndex(NdbIndexImpl & impl, const char * tableName)
int ret = m_receiver.dropIndex(impl, *timpl);
if(ret == 0){
m_localHash.drop(internalIndexName);
-
m_globalHash->lock();
+ impl.m_table->m_status = NdbDictionary::Object::Invalid;
m_globalHash->drop(impl.m_table);
m_globalHash->unlock();
}
diff --git a/sql/ha_myisammrg.cc b/sql/ha_myisammrg.cc
index bf47b4625e0..7a5d4fcf0a1 100644
--- a/sql/ha_myisammrg.cc
+++ b/sql/ha_myisammrg.cc
@@ -381,6 +381,7 @@ int ha_myisammrg::create(const char *name, register TABLE *form,
char buff[FN_REFLEN],**table_names,**pos;
TABLE_LIST *tables= (TABLE_LIST*) create_info->merge_list.first;
THD *thd= current_thd;
+ uint dirlgt= dirname_length(name);
DBUG_ENTER("ha_myisammrg::create");
if (!(table_names= (char**) thd->alloc((create_info->merge_list.elements+1)*
@@ -394,11 +395,30 @@ int ha_myisammrg::create(const char *name, register TABLE *form,
tbl= find_temporary_table(thd, tables->db, tables->real_name);
if (!tbl)
{
- uint length= my_snprintf(buff,FN_REFLEN,"%s%s/%s",
- mysql_real_data_home,
+ /*
+ Construct the path to the MyISAM table. Try to meet two conditions:
+ 1.) Allow to include MyISAM tables from different databases, and
+ 2.) allow for moving DATADIR around in the file system.
+ The first means that we need paths in the .MRG file. The second
+ means that we should not have absolute paths in the .MRG file.
+ The best, we can do, is to use 'mysql_data_home', which is '.'
+ in mysqld and may be an absolute path in an embedded server.
+ This means that it might not be possible to move the DATADIR of
+ an embedded server without changing the paths in the .MRG file.
+ */
+ uint length= my_snprintf(buff, FN_REFLEN, "%s/%s/%s", mysql_data_home,
tables->db, tables->real_name);
- if (!(table_name= thd->strmake(buff, length)))
- DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ /*
+ If a MyISAM table is in the same directory as the MERGE table,
+ we use the table name without a path. This means that the
+ DATADIR can easily be moved even for an embedded server as long
+ as the MyISAM tables are from the same database as the MERGE table.
+ */
+ if ((dirname_length(buff) == dirlgt) && ! memcmp(buff, name, dirlgt))
+ table_name= tables->real_name;
+ else
+ if (! (table_name= thd->strmake(buff, length)))
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
}
else
table_name=(*tbl)->path;
diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc
index 230ca2826b2..a1166641f7d 100644
--- a/sql/ha_ndbcluster.cc
+++ b/sql/ha_ndbcluster.cc
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000-2003 MySQL AB
+ /* Copyright (C) 2000-2003 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -331,11 +331,28 @@ void ha_ndbcluster::no_uncommitted_rows_reset(THD *thd)
# The mapped error code
*/
-void ha_ndbcluster::invalidateDictionaryCache()
+void ha_ndbcluster::invalidate_dictionary_cache(bool global)
{
NDBDICT *dict= get_ndb()->getDictionary();
+ DBUG_ENTER("invalidate_dictionary_cache");
DBUG_PRINT("info", ("invalidating %s", m_tabname));
- dict->invalidateTable(m_tabname);
+
+ if (global)
+ {
+ const NDBTAB *tab= dict->getTable(m_tabname);
+ if (!tab)
+ DBUG_VOID_RETURN;
+ if (tab->getObjectStatus() == NdbDictionary::Object::Invalid)
+ {
+ // Global cache has already been invalidated
+ dict->removeCachedTable(m_tabname);
+ global= FALSE;
+ }
+ else
+ dict->invalidateTable(m_tabname);
+ }
+ else
+ dict->removeCachedTable(m_tabname);
table->version=0L; /* Free when thread is ready */
/* Invalidate indexes */
for (uint i= 0; i < table->keys; i++)
@@ -347,18 +364,28 @@ void ha_ndbcluster::invalidateDictionaryCache()
switch(idx_type) {
case(PRIMARY_KEY_ORDERED_INDEX):
case(ORDERED_INDEX):
- dict->invalidateIndex(index->getName(), m_tabname);
+ if (global)
+ dict->invalidateIndex(index->getName(), m_tabname);
+ else
+ dict->removeCachedIndex(index->getName(), m_tabname);
break;
case(UNIQUE_ORDERED_INDEX):
- dict->invalidateIndex(index->getName(), m_tabname);
+ if (global)
+ dict->invalidateIndex(index->getName(), m_tabname);
+ else
+ dict->removeCachedIndex(index->getName(), m_tabname);
case(UNIQUE_INDEX):
- dict->invalidateIndex(unique_index->getName(), m_tabname);
+ if (global)
+ dict->invalidateIndex(unique_index->getName(), m_tabname);
+ else
+ dict->removeCachedIndex(unique_index->getName(), m_tabname);
break;
case(PRIMARY_KEY_INDEX):
case(UNDEFINED_INDEX):
break;
}
}
+ DBUG_VOID_RETURN;
}
int ha_ndbcluster::ndb_err(NdbConnection *trans)
@@ -371,7 +398,7 @@ int ha_ndbcluster::ndb_err(NdbConnection *trans)
switch (err.classification) {
case NdbError::SchemaError:
{
- invalidateDictionaryCache();
+ invalidate_dictionary_cache(TRUE);
if (err.code==284)
{
@@ -767,7 +794,14 @@ int ha_ndbcluster::get_metadata(const char *path)
if (!(tab= dict->getTable(m_tabname)))
ERR_RETURN(dict->getNdbError());
- DBUG_PRINT("info", ("Table schema version: %d", tab->getObjectVersion()));
+ // Check if thread has stale local cache
+ if (tab->getObjectStatus() == NdbDictionary::Object::Invalid)
+ {
+ invalidate_dictionary_cache(FALSE);
+ if (!(tab= dict->getTable(m_tabname)))
+ ERR_RETURN(dict->getNdbError());
+ DBUG_PRINT("info", ("Table schema version: %d", tab->getObjectVersion()));
+ }
/*
Compare FrmData in NDB with frm file from disk.
*/
@@ -786,7 +820,7 @@ int ha_ndbcluster::get_metadata(const char *path)
if (!invalidating_ndb_table)
{
DBUG_PRINT("info", ("Invalidating table"));
- invalidateDictionaryCache();
+ invalidate_dictionary_cache(TRUE);
invalidating_ndb_table= TRUE;
}
else
@@ -812,7 +846,7 @@ int ha_ndbcluster::get_metadata(const char *path)
if (error)
DBUG_RETURN(error);
- m_tableVersion= tab->getObjectVersion();
+ m_table_version= tab->getObjectVersion();
m_table= (void *)tab;
m_table_info= NULL; // Set in external lock
@@ -3226,15 +3260,25 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type)
void *tab_info;
if (!(tab= dict->getTable(m_tabname, &tab_info)))
ERR_RETURN(dict->getNdbError());
- DBUG_PRINT("info", ("Table schema version: %d", tab->getObjectVersion()));
- if (m_table != (void *)tab || m_tableVersion != tab->getObjectVersion())
+ DBUG_PRINT("info", ("Table schema version: %d",
+ tab->getObjectVersion()));
+ // Check if thread has stale local cache
+ if (tab->getObjectStatus() == NdbDictionary::Object::Invalid)
+ {
+ invalidate_dictionary_cache(FALSE);
+ if (!(tab= dict->getTable(m_tabname, &tab_info)))
+ ERR_RETURN(dict->getNdbError());
+ DBUG_PRINT("info", ("Table schema version: %d",
+ tab->getObjectVersion()));
+ }
+ if (m_table != (void *)tab || m_table_version < tab->getObjectVersion())
{
/*
The table has been altered, refresh the index list
*/
build_index_list(ndb, table, ILBP_OPEN);
m_table= (void *)tab;
- m_tableVersion = tab->getObjectVersion();
+ m_table_version = tab->getObjectVersion();
}
m_table_info= tab_info;
}
@@ -3260,7 +3304,6 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type)
thd->transaction.stmt.ndb_tid= 0;
}
}
- m_table= NULL;
m_table_info= NULL;
/*
This is the place to make sure this handler instance
@@ -3882,7 +3925,13 @@ int ha_ndbcluster::rename_table(const char *from, const char *to)
dict= ndb->getDictionary();
if (!(orig_tab= dict->getTable(m_tabname)))
ERR_RETURN(dict->getNdbError());
-
+ // Check if thread has stale local cache
+ if (orig_tab->getObjectStatus() == NdbDictionary::Object::Invalid)
+ {
+ dict->removeCachedTable(m_tabname);
+ if (!(orig_tab= dict->getTable(m_tabname)))
+ ERR_RETURN(dict->getNdbError());
+ }
m_table= (void *)orig_tab;
// Change current database to that of target table
set_dbname(to);
@@ -4006,7 +4055,7 @@ ha_ndbcluster::ha_ndbcluster(TABLE *table_arg):
m_active_trans(NULL),
m_active_cursor(NULL),
m_table(NULL),
- m_tableVersion(-1),
+ m_table_version(-1),
m_table_info(NULL),
m_table_flags(HA_REC_NOT_IN_SEQ |
HA_NULL_IN_KEY |
@@ -4250,7 +4299,6 @@ int ndbcluster_discover(THD* thd, const char *db, const char *name,
DBUG_RETURN(1);
ERR_RETURN(err);
}
-
DBUG_PRINT("info", ("Found table %s", tab->getName()));
len= tab->getFrmLength();
@@ -4327,6 +4375,7 @@ int ndbcluster_drop_database(const char *path)
uint i;
char *tabname;
List<char> drop_list;
+ int ret= 0;
ha_ndbcluster::set_dbname(path, (char *)&dbname);
DBUG_PRINT("enter", ("db: %s", dbname));
@@ -4353,10 +4402,18 @@ int ndbcluster_drop_database(const char *path)
ndb->setDatabaseName(dbname);
List_iterator_fast<char> it(drop_list);
while ((tabname=it++))
+ {
if (dict->dropTable(tabname))
- ERR_RETURN(dict->getNdbError());
-
- DBUG_RETURN(0);
+ {
+ const NdbError err= dict->getNdbError();
+ if (err.code != 709)
+ {
+ ERR_PRINT(err);
+ ret= ndb_to_mysql_error(&err);
+ }
+ }
+ }
+ DBUG_RETURN(ret);
}
diff --git a/sql/ha_ndbcluster.h b/sql/ha_ndbcluster.h
index ac2d27b9ec7..7de5dd503e7 100644
--- a/sql/ha_ndbcluster.h
+++ b/sql/ha_ndbcluster.h
@@ -203,7 +203,7 @@ class ha_ndbcluster: public handler
void print_results();
longlong get_auto_increment();
- void invalidateDictionaryCache();
+ void invalidate_dictionary_cache(bool global);
int ndb_err(NdbConnection*);
bool uses_blob_value(bool all_fields);
@@ -215,7 +215,7 @@ class ha_ndbcluster: public handler
NdbConnection *m_active_trans;
NdbResultSet *m_active_cursor;
void *m_table;
- int m_tableVersion;
+ int m_table_version;
void *m_table_info;
char m_dbname[FN_HEADLEN];
//char m_schemaname[FN_HEADLEN];
diff --git a/sql/protocol.cc b/sql/protocol.cc
index 773bbe697a3..485605ce8cd 100644
--- a/sql/protocol.cc
+++ b/sql/protocol.cc
@@ -810,7 +810,7 @@ bool Protocol_simple::store_long(longlong from)
#endif
char buff[20];
return net_store_data((char*) buff,
- (uint) (int10_to_str((int) from,buff, -10)-buff));
+ (uint) (int10_to_str((int)from,buff, (from <0)?-10:10)-buff));
}
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index e7f968df396..aeb52a39982 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -6893,6 +6893,11 @@ end_write_group(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
&join->tmp_table_param,
error, 0))
DBUG_RETURN(-1);
+ /*
+ If table->file->write_row() was failed because of 'out of memory'
+ and tmp table succesfully created, reset error.
+ */
+ error=0;
}
if (join->rollup.state != ROLLUP::STATE_NONE && error <= 0)
{