Commit ddd19c66 authored by unknown's avatar unknown

Merge bk@192.168.21.1:mysql-4.1

into  mysql.com:/d2/hf/mrg/mysql-4.1-opt
parents 31f4583a 92447690
......@@ -170,3 +170,21 @@ ROW(2,10) <=> ROW(3,4)
SELECT ROW(NULL,10) <=> ROW(3,NULL);
ROW(NULL,10) <=> ROW(3,NULL)
0
SELECT ROW(1,ROW(2,3)) IN (ROW(1,ROW(2,3)),ROW(1,1));
ERROR 21000: Operand should contain 2 column(s)
SELECT ROW(1,ROW(2,3)) IN (ROW(1,ROW(2,3)),ROW(1,1),ROW(1,ROW(2,3)));
ERROR 21000: Operand should contain 2 column(s)
SELECT ROW(1,ROW(2,3)) IN (ROW(1,ROW(2,3)),ROW(1,ROW(2,2,2)));
ERROR 21000: Operand should contain 2 column(s)
SELECT ROW(1,ROW(2,3,4)) IN (ROW(1,ROW(2,3,4)),ROW(1,ROW(2,2)));
ERROR 21000: Operand should contain 3 column(s)
SELECT ROW(1,ROW(2,3)) IN (ROW(1,ROW(2,3)),(SELECT 1,1));
ERROR 21000: Operand should contain 2 column(s)
SELECT ROW(1,ROW(2,3)) IN (ROW(1,ROW(2,3)),(SELECT 1,1),ROW(1,ROW(2,4)));
ERROR 21000: Operand should contain 2 column(s)
SELECT ROW(1,ROW(2,3)) IN ((SELECT 1,1),ROW(1,ROW(2,3)));
ERROR 21000: Operand should contain 2 column(s)
SELECT ROW(2,1) IN (ROW(21,2),ROW(ROW(1,1,3),0));
ERROR 21000: Operand should contain 1 column(s)
SELECT ROW(2,1) IN (ROW(ROW(1,1,3),0),ROW(21,2));
ERROR 21000: Operand should contain 1 column(s)
......@@ -83,4 +83,29 @@ drop table t1;
SELECT ROW(2,10) <=> ROW(3,4);
SELECT ROW(NULL,10) <=> ROW(3,NULL);
#
# Bug #27484: nested row expressions in IN predicate
#
--error 1241
SELECT ROW(1,ROW(2,3)) IN (ROW(1,ROW(2,3)),ROW(1,1));
--error 1241
SELECT ROW(1,ROW(2,3)) IN (ROW(1,ROW(2,3)),ROW(1,1),ROW(1,ROW(2,3)));
--error 1241
SELECT ROW(1,ROW(2,3)) IN (ROW(1,ROW(2,3)),ROW(1,ROW(2,2,2)));
--error 1241
SELECT ROW(1,ROW(2,3,4)) IN (ROW(1,ROW(2,3,4)),ROW(1,ROW(2,2)));
--error 1241
SELECT ROW(1,ROW(2,3)) IN (ROW(1,ROW(2,3)),(SELECT 1,1));
--error 1241
SELECT ROW(1,ROW(2,3)) IN (ROW(1,ROW(2,3)),(SELECT 1,1),ROW(1,ROW(2,4)));
--error 1241
SELECT ROW(1,ROW(2,3)) IN ((SELECT 1,1),ROW(1,ROW(2,3)));
--error 1241
SELECT ROW(2,1) IN (ROW(21,2),ROW(ROW(1,1,3),0));
--error 1241
SELECT ROW(2,1) IN (ROW(ROW(1,1,3),0),ROW(21,2));
# End of 4.1 tests
......@@ -6,7 +6,7 @@ Next DBTUP 4014
Next DBLQH 5043
Next DBDICT 6006
Next DBDIH 7178
Next DBTC 8038
Next DBTC 8039
Next CMVMI 9000
Next BACKUP 10022
Next DBUTIL 11002
......@@ -285,6 +285,11 @@ ABORT OF TCKEYREQ
8037 : Invalid schema version in TCINDXREQ
------
8038 : Simulate API disconnect just after SCAN_TAB_REQ
CMVMI
-----
9000 Set RestartOnErrorInsert to restart -n
......
......@@ -311,6 +311,16 @@ void Cmvmi::execSTTOR(Signal* signal)
jamEntry();
if (theStartPhase == 1){
jam();
if(theConfig.lockPagesInMainMemory())
{
int res = NdbMem_MemLockAll();
if(res != 0){
g_eventLogger.warning("Failed to memlock pages");
warningEvent("Failed to memlock pages");
}
}
sendSTTORRY(signal);
return;
} else if (theStartPhase == 3) {
......@@ -330,18 +340,6 @@ void Cmvmi::execSTTOR(Signal* signal)
signal->theData[2] = NodeInfo::REP;
execOPEN_COMREQ(signal);
globalData.theStartLevel = NodeState::SL_STARTED;
sendSTTORRY(signal);
} else {
jam();
if(theConfig.lockPagesInMainMemory()){
int res = NdbMem_MemLockAll();
if(res != 0){
g_eventLogger.warning("Failed to memlock pages");
warningEvent("Failed to memlock pages");
}
}
sendSTTORRY(signal);
}
}
......
......@@ -8619,6 +8619,20 @@ void Dbtc::execSCAN_TABREQ(Signal* signal)
* IF ANY TO RECEIVE.
**********************************************************/
scanptr.p->scanState = ScanRecord::WAIT_AI;
if (ERROR_INSERTED(8038))
{
/**
* Force API_FAILREQ
*/
DisconnectRep * const rep = (DisconnectRep *)signal->getDataPtrSend();
rep->nodeId = refToNode(apiConnectptr.p->ndbapiBlockref);
rep->err = 8038;
EXECUTE_DIRECT(CMVMI, GSN_DISCONNECT_REP, signal, 2);
CLEAR_ERROR_INSERT_VALUE;
}
return;
SCAN_error_check:
......@@ -8706,6 +8720,7 @@ void Dbtc::initScanrec(ScanRecordPtr scanptr,
jam();
ScanFragRecPtr ptr;
ndbrequire(list.seize(ptr));
ptr.p->scanFragState = ScanFragRec::IDLE;
ptr.p->scanRec = scanptr.i;
ptr.p->scanFragId = 0;
ptr.p->m_apiPtr = cdata[i];
......@@ -9457,9 +9472,17 @@ Dbtc::close_scan_req(Signal* signal, ScanRecordPtr scanPtr, bool req_received){
ScanRecord* scanP = scanPtr.p;
ndbrequire(scanPtr.p->scanState != ScanRecord::IDLE);
ScanRecord::ScanState old = scanPtr.p->scanState;
scanPtr.p->scanState = ScanRecord::CLOSING_SCAN;
scanPtr.p->m_close_scan_req = req_received;
if (old == ScanRecord::WAIT_FRAGMENT_COUNT)
{
jam();
scanPtr.p->scanState = old;
return; // Will continue on execDI_FCOUNTCONF
}
/**
* Queue : Action
* ============= : =================
......@@ -9487,11 +9510,22 @@ Dbtc::close_scan_req(Signal* signal, ScanRecordPtr scanPtr, bool req_received){
ScanFragRecPtr curr = ptr; // Remove while iterating...
running.next(ptr);
if(curr.p->scanFragState == ScanFragRec::WAIT_GET_PRIMCONF){
switch(curr.p->scanFragState){
case ScanFragRec::IDLE:
jam(); // real early abort
ndbrequire(old == ScanRecord::WAIT_AI);
running.release(curr);
continue;
case ScanFragRec::WAIT_GET_PRIMCONF:
jam();
continue;
case ScanFragRec::LQH_ACTIVE:
jam();
break;
default:
jamLine(curr.p->scanFragState);
ndbrequire(false);
}
ndbrequire(curr.p->scanFragState == ScanFragRec::LQH_ACTIVE);
curr.p->startFragTimer(ctcTimer);
curr.p->scanFragState = ScanFragRec::LQH_ACTIVE;
......
......@@ -390,6 +390,7 @@ Dbtup::commitRecord(Signal* signal,
fragptr.p = regFragPtr;
tabptr.p = regTabPtr;
Uint32 hashValue = firstOpPtr.p->hashValue;
if (opType == ZINSERT_DELETE) {
ljam();
......@@ -412,6 +413,7 @@ Dbtup::commitRecord(Signal* signal,
//--------------------------------------------------------------------
Uint32 saveOpType = regOperPtr->optype;
regOperPtr->optype = ZINSERT;
regOperPtr->hashValue = hashValue;
operPtr.p = regOperPtr;
checkDetachedTriggers(signal,
......@@ -444,6 +446,8 @@ Dbtup::commitRecord(Signal* signal,
befOpPtr.p->changeMask.clear();
befOpPtr.p->changeMask.bitOR(attributeMask);
befOpPtr.p->gci = regOperPtr->gci;
befOpPtr.p->optype = ZUPDATE;
befOpPtr.p->hashValue = hashValue;
befOpPtr.p->optype = opType;
operPtr.p = befOpPtr.p;
......@@ -478,11 +482,13 @@ Dbtup::commitRecord(Signal* signal,
Uint32 fragPageId = befOpPtr.p->fragPageId;
Uint32 pageIndex = befOpPtr.p->pageIndex;
befOpPtr.p->optype = ZDELETE;
befOpPtr.p->realPageId = befOpPtr.p->realPageIdC;
befOpPtr.p->pageOffset = befOpPtr.p->pageOffsetC;
befOpPtr.p->fragPageId = befOpPtr.p->fragPageIdC;
befOpPtr.p->pageIndex = befOpPtr.p->pageIndexC;
befOpPtr.p->gci = regOperPtr->gci;
befOpPtr.p->hashValue = hashValue;
befOpPtr.p->optype = opType;
operPtr.p = befOpPtr.p;
......
......@@ -622,7 +622,7 @@ int runRestarter(NDBT_Context* ctx, NDBT_Step* step){
int nodeId = restarter.getDbNodeId(lastId);
lastId = (lastId + 1) % restarter.getNumDbNodes();
if(restarter.restartOneDbNode(nodeId) != 0){
if(restarter.restartOneDbNode(nodeId, false, false, true) != 0){
g_err << "Failed to restartNextDbNode" << endl;
result = NDBT_FAILED;
break;
......@@ -1080,6 +1080,39 @@ int runScanRestart(NDBT_Context* ctx, NDBT_Step* step){
}
int
runBug24447(NDBT_Context* ctx, NDBT_Step* step){
int loops = 1; //ctx->getNumLoops();
int records = ctx->getNumRecords();
int abort = ctx->getProperty("AbortProb", 15);
NdbRestarter restarter;
HugoTransactions hugoTrans(*ctx->getTab());
int i = 0;
while (i<loops && !ctx->isTestStopped())
{
g_info << i++ << ": ";
int nodeId = restarter.getRandomNotMasterNodeId(rand());
if (nodeId == -1)
nodeId = restarter.getMasterNodeId();
if (restarter.insertErrorInNode(nodeId, 8038) != 0)
{
ndbout << "Could not insert error in node="<<nodeId<<endl;
return NDBT_FAILED;
}
for (Uint32 j = 0; i<10; i++)
{
hugoTrans.scanReadRecords(GETNDB(step), records, abort, 0,
NdbOperation::LM_CommittedRead);
}
}
restarter.insertErrorInAllNodes(0);
return NDBT_OK;
}
NDBT_TESTSUITE(testScan);
TESTCASE("ScanRead",
"Verify scan requirement: It should be possible "\
......@@ -1540,6 +1573,12 @@ TESTCASE("ScanRestart",
STEP(runScanRestart);
FINALIZER(runClearTable);
}
TESTCASE("Bug24447",
""){
INITIALIZER(runLoadTable);
STEP(runBug24447);
FINALIZER(runClearTable);
}
NDBT_TESTSUITE_END(testScan);
int main(int argc, const char** argv){
......
......@@ -438,6 +438,10 @@ max-time: 500
cmd: testScan
args: -l 100 -n Scan-bug8262 T7
max-time: 500
cmd: testScan
args: -n Bug24447 T1
max-time: 500
cmd: testNodeRestart
args: -n Bug15587 T1
......
......@@ -61,6 +61,42 @@ static void agg_result_type(Item_result *type, Item **items, uint nitems)
}
/*
Compare row signature of two expressions
SYNOPSIS:
cmp_row_type()
item1 the first expression
item2 the second expression
DESCRIPTION
The function checks that two expressions have compatible row signatures
i.e. that the number of columns they return are the same and that if they
are both row expressions then each component from the first expression has
a row signature compatible with the signature of the corresponding component
of the second expression.
RETURN VALUES
1 type incompatibility has been detected
0 otherwise
*/
static int cmp_row_type(Item* item1, Item* item2)
{
uint n= item1->cols();
if (item2->check_cols(n))
return 1;
for (uint i=0; i<n; i++)
{
if (item2->el(i)->check_cols(item1->el(i)->cols()) ||
(item1->el(i)->result_type() == ROW_RESULT &&
cmp_row_type(item1->el(i), item2->el(i))))
return 1;
}
return 0;
}
/*
Aggregates result types from the array of items.
......@@ -75,14 +111,32 @@ static void agg_result_type(Item_result *type, Item **items, uint nitems)
This function aggregates result types from the array of items. Found type
supposed to be used later for comparison of values of these items.
Aggregation itself is performed by the item_cmp_type() function.
The function also checks compatibility of row signatures for the
submitted items (see the spec for the cmp_row_type function).
RETURN VALUES
1 type incompatibility has been detected
0 otherwise
*/
static void agg_cmp_type(THD *thd, Item_result *type, Item **items, uint nitems)
static int agg_cmp_type(THD *thd, Item_result *type, Item **items, uint nitems)
{
uint i;
type[0]= items[0]->result_type();
for (i= 1 ; i < nitems ; i++)
{
type[0]= item_cmp_type(type[0], items[i]->result_type());
/*
When aggregating types of two row expressions we have to check
that they have the same cardinality and that each component
of the first row expression has a compatible row signature with
the signature of the corresponding component of the second row
expression.
*/
if (type[0] == ROW_RESULT && cmp_row_type(items[0], items[i]))
return 1; // error found: invalid usage of rows
}
return 0;
}
static void my_coll_agg_error(DTCollation &c1, DTCollation &c2,
......@@ -984,7 +1038,8 @@ void Item_func_between::fix_length_and_dec()
*/
if (!args[0] || !args[1] || !args[2])
return;
agg_cmp_type(thd, &cmp_type, args, 3);
if ( agg_cmp_type(thd, &cmp_type, args, 3))
return;
if (cmp_type == STRING_RESULT &&
agg_arg_charsets(cmp_collation, args, 3, MY_COLL_CMP_CONV))
return;
......@@ -1532,7 +1587,8 @@ void Item_func_case::fix_length_and_dec()
for (nagg= 0; nagg < ncases/2 ; nagg++)
agg[nagg+1]= args[nagg*2];
nagg++;
agg_cmp_type(current_thd, &cmp_type, agg, nagg);
if (agg_cmp_type(current_thd, &cmp_type, agg, nagg))
return;
if ((cmp_type == STRING_RESULT) &&
agg_arg_charsets(cmp_collation, agg, nagg, MY_COLL_CMP_CONV))
return;
......@@ -2013,7 +2069,8 @@ void Item_func_in::fix_length_and_dec()
uint const_itm= 1;
THD *thd= current_thd;
agg_cmp_type(thd, &cmp_type, args, arg_count);
if (agg_cmp_type(thd, &cmp_type, args, arg_count))
return;
if (cmp_type == STRING_RESULT &&
agg_arg_charsets(cmp_collation, args, arg_count, MY_COLL_CMP_CONV))
......
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