Commit 5627416c authored by cmiller@zippy.(none)'s avatar cmiller@zippy.(none)

Merge zippy.(none):/home/cmiller/work/mysql/merge/tmp_merge

into  zippy.(none):/home/cmiller/work/mysql/merge/mysql-5.1-new
parents 399a1b84 63da6af2
...@@ -15,8 +15,9 @@ AC_DEFUN([MYSQL_FIND_OPENSSL], [ ...@@ -15,8 +15,9 @@ AC_DEFUN([MYSQL_FIND_OPENSSL], [
for d in /usr/ssl/lib /usr/local/ssl/lib /usr/lib/openssl \ for d in /usr/ssl/lib /usr/local/ssl/lib /usr/lib/openssl \
/usr/lib /usr/lib64 /opt/ssl/lib /opt/openssl/lib \ /usr/lib /usr/lib64 /opt/ssl/lib /opt/openssl/lib \
/usr/freeware/lib32 /usr/local/lib/ ; do /usr/freeware/lib32 /usr/local/lib/ ; do
# Just to be safe, we test for ".so" anyway # Test for libssl using all known library file endings
if test -f $d/libssl.a || test -f $d/libssl.so || test -f $d/libssl$shrext ; then if test -f $d/libssl.a || test -f $d/libssl.so || \
test -f $d/libssl.sl || test -f $d/libssl.dylib ; then
OPENSSL_LIB=$d OPENSSL_LIB=$d
fi fi
done done
...@@ -28,8 +29,9 @@ AC_DEFUN([MYSQL_FIND_OPENSSL], [ ...@@ -28,8 +29,9 @@ AC_DEFUN([MYSQL_FIND_OPENSSL], [
if test -f $incs/openssl/ssl.h ; then if test -f $incs/openssl/ssl.h ; then
OPENSSL_INCLUDE=-I$incs OPENSSL_INCLUDE=-I$incs
fi fi
# Just to be safe, we test for ".so" anyway # Test for libssl using all known library file endings
if test -f $libs/libssl.a || test -f $libs/libssl.so || test -f $libs/libssl$shrext ; then if test -f $d/libssl.a || test -f $d/libssl.so || \
test -f $d/libssl.sl || test -f $d/libssl.dylib ; then
OPENSSL_LIB=$libs OPENSSL_LIB=$libs
fi fi
;; ;;
......
...@@ -89,10 +89,11 @@ case $SYSTEM_TYPE in ...@@ -89,10 +89,11 @@ case $SYSTEM_TYPE in
fi fi
;; ;;
*) *)
# Just to be safe, we test for ".so" anyway # Test for libz using all known library file endings
eval shrexts=\"$shrext_cmds\" if test \( -f "$mysql_zlib_dir/lib/libz.a" -o \
if test \( -f "$mysql_zlib_dir/lib/libz.a" -o -f "$mysql_zlib_dir/lib/libz.so" -o \ -f "$mysql_zlib_dir/lib/libz.so" -o \
-f "$mysql_zlib_dir/lib/libz$shrext" \) \ -f "$mysql_zlib_dir/lib/libz.sl" -o \
-f "$mysql_zlib_dir/lib/libz.dylib" \) \
-a -f "$mysql_zlib_dir/include/zlib.h"; then -a -f "$mysql_zlib_dir/include/zlib.h"; then
ZLIB_INCLUDES="-I$mysql_zlib_dir/include" ZLIB_INCLUDES="-I$mysql_zlib_dir/include"
ZLIB_LIBS="-L$mysql_zlib_dir/lib -lz" ZLIB_LIBS="-L$mysql_zlib_dir/lib -lz"
......
...@@ -326,3 +326,20 @@ deallocate prepare s; ...@@ -326,3 +326,20 @@ deallocate prepare s;
set @str=NULL; set @str=NULL;
drop table t2; drop table t2;
drop table t1; drop table t1;
create table t1 (
some_id smallint(5) unsigned,
key (some_id)
);
insert into t1 values (1),(2);
select some_id from t1 where some_id not in(2,-1);
some_id
1
select some_id from t1 where some_id not in(-4,-1,-4);
some_id
1
2
select some_id from t1 where some_id not in(-4,-1,3423534,2342342);
some_id
1
2
drop table t1;
...@@ -220,3 +220,15 @@ set @str=NULL; ...@@ -220,3 +220,15 @@ set @str=NULL;
drop table t2; drop table t2;
drop table t1; drop table t1;
# BUG#19618: Crash in range optimizer for
# "unsigned_keypart NOT IN(negative_number,...)"
# (introduced in fix BUG#15872)
create table t1 (
some_id smallint(5) unsigned,
key (some_id)
);
insert into t1 values (1),(2);
select some_id from t1 where some_id not in(2,-1);
select some_id from t1 where some_id not in(-4,-1,-4);
select some_id from t1 where some_id not in(-4,-1,3423534,2342342);
drop table t1;
...@@ -194,7 +194,7 @@ drop table t1; ...@@ -194,7 +194,7 @@ drop table t1;
# #
#14157: utf8 encoding in binlog without set character_set_client #14157: utf8 encoding in binlog without set character_set_client
# #
--exec $MYSQL --character-sets-dir=../sql/share/charsets/ --default-character-set=koi8r test -e 'create table t1 (a int); set names koi8r; create temporary table `ÑÝÉË` (a int); insert into `ÑÝÉË` values (1); insert into t1 select * from `ÑÝÉË`' --exec $MYSQL --character-sets-dir=../sql/share/charsets/ --default-character-set=latin1 test -e 'create table t1 (a int); set names latin1; create temporary table `äöüÄÖÜ` (a int); insert into `äöüÄÖÜ` values (1); insert into t1 select * from `äöüÄÖÜ`'
sync_slave_with_master; sync_slave_with_master;
#connection slave; #connection slave;
......
...@@ -5413,7 +5413,7 @@ bool Item_trigger_field::eq(const Item *item, bool binary_cmp) const ...@@ -5413,7 +5413,7 @@ bool Item_trigger_field::eq(const Item *item, bool binary_cmp) const
} }
void Item_trigger_field::set_required_privilege(const bool rw) void Item_trigger_field::set_required_privilege(bool rw)
{ {
/* /*
Require SELECT and UPDATE privilege if this field will be read and Require SELECT and UPDATE privilege if this field will be read and
......
...@@ -2233,7 +2233,7 @@ public: ...@@ -2233,7 +2233,7 @@ public:
void cleanup(); void cleanup();
private: private:
void set_required_privilege(const bool rw); void set_required_privilege(bool rw);
bool set_value(THD *thd, sp_rcontext *ctx, Item **it); bool set_value(THD *thd, sp_rcontext *ctx, Item **it);
public: public:
......
...@@ -4698,17 +4698,46 @@ static SEL_TREE *get_func_mm_tree(RANGE_OPT_PARAM *param, Item_func *cond_func, ...@@ -4698,17 +4698,46 @@ static SEL_TREE *get_func_mm_tree(RANGE_OPT_PARAM *param, Item_func *cond_func,
if (inv) if (inv)
{ {
/*
We get here for conditions like "t.keypart NOT IN (....)".
If the IN-list contains only constants (and func->array is an ordered
array of them), we construct the appropriate SEL_ARG tree manually,
because constructing it using the range analyzer (as
AND_i( t.keypart != c_i)) will cause lots of memory to be consumed
(see BUG#15872).
*/
if (func->array && func->cmp_type != ROW_RESULT) if (func->array && func->cmp_type != ROW_RESULT)
{ {
/*
We get here for conditions in form "t.key NOT IN (c1, c2, ...)"
(where c{i} are constants).
Our goal is to produce a SEL_ARG graph that represents intervals:
($MIN<t.key<c1) OR (c1<t.key<c2) OR (c2<t.key<c3) OR ... (*)
where $MIN is either "-inf" or NULL.
The most straightforward way to handle NOT IN would be to convert
it to "(t.key != c1) AND (t.key != c2) AND ..." and let the range
optimizer to build SEL_ARG graph from that. However that will cause
the range optimizer to use O(N^2) memory (it's a bug, not filed),
and people do use big NOT IN lists (see BUG#15872). Also, for big
NOT IN lists constructing/using graph (*) does not make the query
faster.
So, we will handle NOT IN manually in the following way:
* if the number of entries in the NOT IN list is less then
NOT_IN_IGNORE_THRESHOLD, we will construct SEL_ARG graph (*)
manually.
* Otherwise, we will construct a smaller graph: for
"t.key NOT IN (c1,...cN)" we construct a graph representing
($MIN < t.key) OR (cN < t.key) // here sequence of c_i is
// ordered.
A note about partially-covering indexes: for those (e.g. for
"a CHAR(10), KEY(a(5))") the handling is correct (albeit not very
efficient):
Instead of "t.key < c1" we get "t.key <= prefix-val(c1)".
Combining the intervals in (*) together, we get:
(-inf<=t.key<=c1) OR (c1<=t.key<=c2) OR (c2<=t.key<=c3) OR ...
i.e. actually we get intervals combined into one interval:
(-inf<=t.key<=+inf). This doesn't make much sense but it doesn't
cause any problems.
*/
MEM_ROOT *tmp_root= param->mem_root;
param->thd->mem_root= param->old_root;
/* /*
Create one Item_type constant object. We'll need it as Create one Item_type constant object. We'll need it as
get_mm_parts only accepts constant values wrapped in Item_Type get_mm_parts only accepts constant values wrapped in Item_Type
...@@ -4717,25 +4746,35 @@ static SEL_TREE *get_func_mm_tree(RANGE_OPT_PARAM *param, Item_func *cond_func, ...@@ -4717,25 +4746,35 @@ static SEL_TREE *get_func_mm_tree(RANGE_OPT_PARAM *param, Item_func *cond_func,
per-statement mem_root (while thd->mem_root is currently pointing per-statement mem_root (while thd->mem_root is currently pointing
to mem_root local to range optimizer). to mem_root local to range optimizer).
*/ */
MEM_ROOT *tmp_root= param->mem_root;
param->thd->mem_root= param->old_root;
Item *value_item= func->array->create_item(); Item *value_item= func->array->create_item();
param->thd->mem_root= tmp_root; param->thd->mem_root= tmp_root;
if (!value_item) if (!value_item)
break; break;
/* Get a SEL_TREE for "-inf < X < c_0" interval */ /* Get a SEL_TREE for "(-inf|NULL) < X < c_0" interval. */
func->array->value_to_item(0, value_item); uint i=0;
do
{
func->array->value_to_item(i, value_item);
tree= get_mm_parts(param, cond_func, field, Item_func::LT_FUNC, tree= get_mm_parts(param, cond_func, field, Item_func::LT_FUNC,
value_item, cmp_type); value_item, cmp_type);
if (!tree) if (!tree)
break; break;
i++;
} while (i < func->array->count && tree->type == SEL_TREE::IMPOSSIBLE);
if (!tree || tree->type == SEL_TREE::IMPOSSIBLE)
{
/* We get here in cases like "t.unsigned NOT IN (-1,-2,-3) */
tree= NULL;
break;
}
#define NOT_IN_IGNORE_THRESHOLD 1000 #define NOT_IN_IGNORE_THRESHOLD 1000
SEL_TREE *tree2; SEL_TREE *tree2;
if (func->array->count < NOT_IN_IGNORE_THRESHOLD) if (func->array->count < NOT_IN_IGNORE_THRESHOLD)
{ {
for (uint i=1; i < func->array->count; i++) for (; i < func->array->count; i++)
{ {
if (func->array->compare_elems(i, i-1)) if (func->array->compare_elems(i, i-1))
{ {
...@@ -4743,18 +4782,27 @@ static SEL_TREE *get_func_mm_tree(RANGE_OPT_PARAM *param, Item_func *cond_func, ...@@ -4743,18 +4782,27 @@ static SEL_TREE *get_func_mm_tree(RANGE_OPT_PARAM *param, Item_func *cond_func,
func->array->value_to_item(i, value_item); func->array->value_to_item(i, value_item);
tree2= get_mm_parts(param, cond_func, field, Item_func::LT_FUNC, tree2= get_mm_parts(param, cond_func, field, Item_func::LT_FUNC,
value_item, cmp_type); value_item, cmp_type);
if (!tree2)
{
tree= NULL;
break;
}
/* Change all intervals to be "c_{i-1} < X < c_i" */ /* Change all intervals to be "c_{i-1} < X < c_i" */
for (uint idx= 0; idx < param->keys; idx++) for (uint idx= 0; idx < param->keys; idx++)
{ {
SEL_ARG *new_interval; SEL_ARG *new_interval, *last_val;
if ((new_interval= tree2->keys[idx])) if (((new_interval= tree2->keys[idx])) &&
((last_val= tree->keys[idx]->last())))
{ {
SEL_ARG *last_val= tree->keys[idx]->last();
new_interval->min_value= last_val->max_value; new_interval->min_value= last_val->max_value;
new_interval->min_flag= NEAR_MIN; new_interval->min_flag= NEAR_MIN;
} }
} }
/*
The following doesn't try to allocate memory so no need to
check for NULL.
*/
tree= tree_or(param, tree, tree2); tree= tree_or(param, tree, tree2);
} }
} }
...@@ -4762,6 +4810,8 @@ static SEL_TREE *get_func_mm_tree(RANGE_OPT_PARAM *param, Item_func *cond_func, ...@@ -4762,6 +4810,8 @@ static SEL_TREE *get_func_mm_tree(RANGE_OPT_PARAM *param, Item_func *cond_func,
else else
func->array->value_to_item(func->array->count - 1, value_item); func->array->value_to_item(func->array->count - 1, value_item);
if (tree && tree->type != SEL_TREE::IMPOSSIBLE)
{
/* /*
Get the SEL_TREE for the last "c_last < X < +inf" interval Get the SEL_TREE for the last "c_last < X < +inf" interval
(value_item cotains c_last already) (value_item cotains c_last already)
...@@ -4770,6 +4820,7 @@ static SEL_TREE *get_func_mm_tree(RANGE_OPT_PARAM *param, Item_func *cond_func, ...@@ -4770,6 +4820,7 @@ static SEL_TREE *get_func_mm_tree(RANGE_OPT_PARAM *param, Item_func *cond_func,
value_item, cmp_type); value_item, cmp_type);
tree= tree_or(param, tree, tree2); tree= tree_or(param, tree, tree2);
} }
}
else else
{ {
tree= get_ne_mm_tree(param, cond_func, field, tree= get_ne_mm_tree(param, cond_func, field,
......
...@@ -6154,20 +6154,21 @@ void fill_effective_table_privileges(THD *thd, GRANT_INFO *grant, ...@@ -6154,20 +6154,21 @@ void fill_effective_table_privileges(THD *thd, GRANT_INFO *grant,
} }
/* table privileges */ /* table privileges */
rw_rdlock(&LOCK_grant);
if (grant->version != grant_version) if (grant->version != grant_version)
{ {
rw_rdlock(&LOCK_grant);
grant->grant_table= grant->grant_table=
table_hash_search(sctx->host, sctx->ip, db, table_hash_search(sctx->host, sctx->ip, db,
sctx->priv_user, sctx->priv_user,
table, 0); /* purecov: inspected */ table, 0); /* purecov: inspected */
grant->version= grant_version; /* purecov: inspected */ grant->version= grant_version; /* purecov: inspected */
rw_unlock(&LOCK_grant);
} }
if (grant->grant_table != 0) if (grant->grant_table != 0)
{ {
grant->privilege|= grant->grant_table->privs; grant->privilege|= grant->grant_table->privs;
} }
rw_unlock(&LOCK_grant);
DBUG_PRINT("info", ("privilege 0x%lx", grant->privilege)); DBUG_PRINT("info", ("privilege 0x%lx", grant->privilege));
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
......
...@@ -1926,8 +1926,8 @@ int Dbtup::interpreterNextLab(Signal* signal, ...@@ -1926,8 +1926,8 @@ int Dbtup::interpreterNextLab(Signal* signal,
// word read. Thus we set the register to be a 32 bit register. // word read. Thus we set the register to be a 32 bit register.
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
TregMemBuffer[theRegister]= 0x50; TregMemBuffer[theRegister]= 0x50;
* (Int64*)(TregMemBuffer+theRegister+2)= // arithmetic conversion if big-endian
TregMemBuffer[theRegister+1]; * (Int64*)(TregMemBuffer+theRegister+2)= TregMemBuffer[theRegister+1];
} else if (TnoDataRW == 3) { } else if (TnoDataRW == 3) {
/* ------------------------------------------------------------- */ /* ------------------------------------------------------------- */
// Three words read means that we get the instruction plus two // Three words read means that we get the instruction plus two
...@@ -1985,6 +1985,11 @@ int Dbtup::interpreterNextLab(Signal* signal, ...@@ -1985,6 +1985,11 @@ int Dbtup::interpreterNextLab(Signal* signal,
Tlen= TattrNoOfWords + 1; Tlen= TattrNoOfWords + 1;
if (Toptype == ZUPDATE) { if (Toptype == ZUPDATE) {
if (TattrNoOfWords <= 2) { if (TattrNoOfWords <= 2) {
if (TattrNoOfWords == 1) {
// arithmetic conversion if big-endian
TdataForUpdate[1] = *(Int64*)&TregMemBuffer[theRegister + 2];
TdataForUpdate[2] = 0;
}
if (TregType == 0) { if (TregType == 0) {
/* --------------------------------------------------------- */ /* --------------------------------------------------------- */
// Write a NULL value into the attribute // Write a NULL value into the attribute
......
...@@ -24,6 +24,7 @@ testOIBasic \ ...@@ -24,6 +24,7 @@ testOIBasic \
testOperations \ testOperations \
testRestartGci \ testRestartGci \
testScan \ testScan \
testInterpreter \
testScanInterpreter \ testScanInterpreter \
testScanPerf \ testScanPerf \
testSystemRestart \ testSystemRestart \
...@@ -64,6 +65,7 @@ testOIBasic_SOURCES = testOIBasic.cpp ...@@ -64,6 +65,7 @@ testOIBasic_SOURCES = testOIBasic.cpp
testOperations_SOURCES = testOperations.cpp testOperations_SOURCES = testOperations.cpp
testRestartGci_SOURCES = testRestartGci.cpp testRestartGci_SOURCES = testRestartGci.cpp
testScan_SOURCES = testScan.cpp ScanFunctions.hpp testScan_SOURCES = testScan.cpp ScanFunctions.hpp
testInterpreter_SOURCES = testInterpreter.cpp
testScanInterpreter_SOURCES = testScanInterpreter.cpp ScanFilter.hpp ScanInterpretTest.hpp testScanInterpreter_SOURCES = testScanInterpreter.cpp ScanFilter.hpp ScanInterpretTest.hpp
testScanPerf_SOURCES = testScanPerf.cpp testScanPerf_SOURCES = testScanPerf.cpp
testSystemRestart_SOURCES = testSystemRestart.cpp testSystemRestart_SOURCES = testSystemRestart.cpp
......
...@@ -142,6 +142,122 @@ int runTestIncValue32(NDBT_Context* ctx, NDBT_Step* step){ ...@@ -142,6 +142,122 @@ int runTestIncValue32(NDBT_Context* ctx, NDBT_Step* step){
return NDBT_OK; return NDBT_OK;
} }
int runTestBug19537(NDBT_Context* ctx, NDBT_Step* step){
int result = NDBT_OK;
const NdbDictionary::Table * pTab = ctx->getTab();
Ndb* pNdb = GETNDB(step);
if (strcmp(pTab->getName(), "T1") != 0) {
g_err << "runTestBug19537: skip, table != T1" << endl;
return NDBT_OK;
}
NdbConnection* pTrans = pNdb->startTransaction();
if (pTrans == NULL){
ERR(pNdb->getNdbError());
return NDBT_FAILED;
}
NdbOperation* pOp = pTrans->getNdbOperation(pTab->getName());
if (pOp == NULL) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
return NDBT_FAILED;
}
if (pOp->interpretedUpdateTuple() == -1) {
ERR(pOp->getNdbError());
pNdb->closeTransaction(pTrans);
return NDBT_FAILED;
}
// Primary keys
const Uint32 pkVal = 1;
if (pOp->equal("KOL1", pkVal) == -1) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
return NDBT_FAILED;
}
// Load 64-bit constant into register 1 and
// write from register 1 to 32-bit column KOL2
const Uint64 reg_val = 0x0102030405060708ULL;
const Uint32* reg_ptr32 = (const Uint32*)&reg_val;
if (reg_ptr32[0] == 0x05060708 && reg_ptr32[1] == 0x01020304) {
g_err << "runTestBug19537: platform is LITTLE endian" << endl;
} else if (reg_ptr32[0] == 0x01020304 && reg_ptr32[1] == 0x05060708) {
g_err << "runTestBug19537: platform is BIG endian" << endl;
} else {
g_err << "runTestBug19537: impossible platform"
<< hex << " [0]=" << reg_ptr32[0] << " [1]=" <<reg_ptr32[1] << endl;
pNdb->closeTransaction(pTrans);
return NDBT_FAILED;
}
if (pOp->load_const_u64(1, reg_val) == -1 ||
pOp->write_attr("KOL2", 1) == -1) {
ERR(pOp->getNdbError());
pNdb->closeTransaction(pTrans);
return NDBT_FAILED;
}
if (pTrans->execute(Commit) == -1) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
return NDBT_FAILED;
}
// Read value via a new transaction
pTrans = pNdb->startTransaction();
if (pTrans == NULL){
ERR(pNdb->getNdbError());
return NDBT_FAILED;
}
pOp = pTrans->getNdbOperation(pTab->getName());
if (pOp == NULL) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
return NDBT_FAILED;
}
Uint32 kol2 = 0x09090909;
if (pOp->readTuple() == -1 ||
pOp->equal("KOL1", pkVal) == -1 ||
pOp->getValue("KOL2", (char*)&kol2) == 0) {
ERR(pOp->getNdbError());
pNdb->closeTransaction(pTrans);
return NDBT_FAILED;
}
if (pTrans->execute(Commit) == -1) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
return NDBT_FAILED;
}
// Expected conversion as in C - truncate to lower (logical) word
if (kol2 == 0x01020304) {
g_err << "runTestBug19537: the bug manifests itself !" << endl;
pNdb->closeTransaction(pTrans);
return NDBT_FAILED;
}
if (kol2 != 0x05060708) {
g_err << "runTestBug19537: impossible KOL2 " << hex << kol2 << endl;
pNdb->closeTransaction(pTrans);
return NDBT_FAILED;
}
pNdb->closeTransaction(pTrans);
return NDBT_OK;
}
NDBT_TESTSUITE(testInterpreter); NDBT_TESTSUITE(testInterpreter);
TESTCASE("IncValue32", TESTCASE("IncValue32",
...@@ -156,6 +272,12 @@ TESTCASE("IncValue64", ...@@ -156,6 +272,12 @@ TESTCASE("IncValue64",
INITIALIZER(runTestIncValue64); INITIALIZER(runTestIncValue64);
FINALIZER(runClearTable); FINALIZER(runClearTable);
} }
TESTCASE("Bug19537",
"Test big-endian write_attr of 32 bit integer\n"){
INITIALIZER(runLoadTable);
INITIALIZER(runTestBug19537);
FINALIZER(runClearTable);
}
#if 0 #if 0
TESTCASE("MaxTransactions", TESTCASE("MaxTransactions",
"Start transactions until no more can be created\n"){ "Start transactions until no more can be created\n"){
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment