mirror of
https://github.com/MariaDB/server.git
synced 2025-01-20 22:12:30 +01:00
Merge mysql.com:/home/jonas/src/mysql-5.0
into mysql.com:/home/jonas/src/mysql-5.0-ndb
This commit is contained in:
commit
bf6e779b84
16 changed files with 275 additions and 87 deletions
|
@ -186,6 +186,7 @@ mysqldev@build.mysql2.com
|
|||
mysqldev@melody.local
|
||||
mysqldev@mysql.com
|
||||
mysqldev@o2k.irixworld.net
|
||||
ndbdev@dl145b.mysql.com
|
||||
ndbdev@eel.hemma.oreland.se
|
||||
ndbdev@ndbmaster.mysql.com
|
||||
ndbdev@shark.
|
||||
|
@ -268,6 +269,7 @@ tonu@x153.internalnet
|
|||
tonu@x3.internalnet
|
||||
tsmith@build.mysql.com
|
||||
tulin@build.mysql.com
|
||||
tulin@dl145b.mysql.com
|
||||
tulin@mysql.com
|
||||
ulli@morbus.(none)
|
||||
venu@hundin.mysql.fi
|
||||
|
|
|
@ -247,3 +247,4 @@ count(*)
|
|||
3
|
||||
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
|
||||
drop table if exists t1_c,t2_c,t3_c,t4_c,t5_c,t6_c,t7_c,t8_c,t9_c;
|
||||
520093696,1
|
||||
|
|
|
@ -570,3 +570,28 @@ id
|
|||
deallocate prepare stmt|
|
||||
drop procedure p1|
|
||||
drop table t1|
|
||||
drop table if exists t1;
|
||||
Warnings:
|
||||
Note 1051 Unknown table 't1'
|
||||
create table t1 (c1 int(11) not null, c2 int(11) not null,
|
||||
primary key (c1,c2), key c2 (c2), key c1 (c1));
|
||||
insert into t1 values (200887, 860);
|
||||
insert into t1 values (200887, 200887);
|
||||
select * from t1 where (c1=200887 and c2=200887) or c2=860;
|
||||
c1 c2
|
||||
200887 860
|
||||
200887 200887
|
||||
prepare stmt from
|
||||
"select * from t1 where (c1=200887 and c2=200887) or c2=860";
|
||||
execute stmt;
|
||||
c1 c2
|
||||
200887 860
|
||||
200887 200887
|
||||
prepare stmt from
|
||||
"select * from t1 where (c1=200887 and c2=?) or c2=?";
|
||||
set @a=200887, @b=860;
|
||||
execute stmt using @a, @b;
|
||||
c1 c2
|
||||
200887 860
|
||||
200887 200887
|
||||
deallocate prepare stmt;
|
||||
|
|
|
@ -88,7 +88,7 @@ date numfacture expedition
|
|||
0000-00-00 00:00:00 1212 0001-00-00 00:00:00
|
||||
EXPLAIN SELECT * FROM t1 WHERE expedition='0001-00-00 00:00:00';
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 ref expedition expedition 8 const 1 Using where
|
||||
1 SIMPLE t1 ref expedition expedition 8 const 1
|
||||
drop table t1;
|
||||
create table t1 (a datetime not null, b datetime not null);
|
||||
insert into t1 values (now(), now());
|
||||
|
|
|
@ -209,3 +209,9 @@ select count(*)
|
|||
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
|
||||
drop table if exists t1_c,t2_c,t3_c,t4_c,t5_c,t6_c,t7_c,t8_c,t9_c;
|
||||
--enable_warnings
|
||||
|
||||
#
|
||||
# Test BUG#10287
|
||||
#
|
||||
|
||||
--exec $NDB_TOOLS_DIR/ndb_select_all -d sys -D , SYSTAB_0 | grep 520093696
|
||||
|
|
|
@ -587,3 +587,30 @@ deallocate prepare stmt|
|
|||
drop procedure p1|
|
||||
drop table t1|
|
||||
delimiter ;|
|
||||
|
||||
#
|
||||
# Bug#9096 "select doesn't return all matched records if prepared statements
|
||||
# is used"
|
||||
# The bug was is bad co-operation of the optimizer's algorithm which determines
|
||||
# which keys can be used to execute a query, constants propagation
|
||||
# part of the optimizer and parameter markers used by prepared statements.
|
||||
|
||||
drop table if exists t1;
|
||||
create table t1 (c1 int(11) not null, c2 int(11) not null,
|
||||
primary key (c1,c2), key c2 (c2), key c1 (c1));
|
||||
|
||||
insert into t1 values (200887, 860);
|
||||
insert into t1 values (200887, 200887);
|
||||
|
||||
select * from t1 where (c1=200887 and c2=200887) or c2=860;
|
||||
|
||||
prepare stmt from
|
||||
"select * from t1 where (c1=200887 and c2=200887) or c2=860";
|
||||
execute stmt;
|
||||
prepare stmt from
|
||||
"select * from t1 where (c1=200887 and c2=?) or c2=?";
|
||||
set @a=200887, @b=860;
|
||||
# this query did not return all matching rows
|
||||
execute stmt using @a, @b;
|
||||
deallocate prepare stmt;
|
||||
|
||||
|
|
|
@ -585,34 +585,8 @@ public:
|
|||
*/
|
||||
ArrayPool<TcIndexOperation> c_theIndexOperationPool;
|
||||
|
||||
/**
|
||||
* The list of index operations
|
||||
*/
|
||||
ArrayList<TcIndexOperation> c_theIndexOperations;
|
||||
|
||||
UintR c_maxNumberOfIndexOperations;
|
||||
|
||||
struct TcSeizedIndexOperation {
|
||||
/**
|
||||
* Next ptr (used in pool/list)
|
||||
*/
|
||||
union {
|
||||
Uint32 nextPool;
|
||||
Uint32 nextList;
|
||||
};
|
||||
/**
|
||||
* Prev pointer (used in list)
|
||||
*/
|
||||
Uint32 prevList;
|
||||
};
|
||||
|
||||
/**
|
||||
* Pool of seized index operations
|
||||
*/
|
||||
ArrayPool<TcSeizedIndexOperation> c_theSeizedIndexOperationPool;
|
||||
|
||||
typedef Ptr<TcSeizedIndexOperation> TcSeizedIndexOperationPtr;
|
||||
|
||||
/************************** API CONNECT RECORD ***********************
|
||||
* The API connect record contains the connection record to which the
|
||||
* application connects.
|
||||
|
@ -650,7 +624,7 @@ public:
|
|||
|
||||
struct ApiConnectRecord {
|
||||
ApiConnectRecord(ArrayPool<TcFiredTriggerData> & firedTriggerPool,
|
||||
ArrayPool<TcSeizedIndexOperation> & seizedIndexOpPool):
|
||||
ArrayPool<TcIndexOperation> & seizedIndexOpPool):
|
||||
theFiredTriggers(firedTriggerPool),
|
||||
isIndexOp(false),
|
||||
theSeizedIndexOperations(seizedIndexOpPool)
|
||||
|
@ -763,7 +737,7 @@ public:
|
|||
UintR accumulatingIndexOp;
|
||||
UintR executingIndexOp;
|
||||
UintR tcIndxSendArray[6];
|
||||
ArrayList<TcSeizedIndexOperation> theSeizedIndexOperations;
|
||||
ArrayList<TcIndexOperation> theSeizedIndexOperations;
|
||||
};
|
||||
|
||||
typedef Ptr<ApiConnectRecord> ApiConnectRecordPtr;
|
||||
|
|
|
@ -65,7 +65,6 @@ void Dbtc::initData()
|
|||
c_theFiredTriggerPool.setSize(c_maxNumberOfFiredTriggers);
|
||||
c_theIndexPool.setSize(c_maxNumberOfIndexes);
|
||||
c_theIndexOperationPool.setSize(c_maxNumberOfIndexOperations);
|
||||
c_theSeizedIndexOperationPool.setSize(c_maxNumberOfIndexOperations);
|
||||
c_theAttributeBufferPool.setSize(c_transactionBufferSpace);
|
||||
c_firedTriggerHash.setSize((c_maxNumberOfFiredTriggers+10)/10);
|
||||
}//Dbtc::initData()
|
||||
|
@ -85,7 +84,7 @@ void Dbtc::initRecords()
|
|||
for(unsigned i = 0; i<capiConnectFilesize; i++) {
|
||||
p = &apiConnectRecord[i];
|
||||
new (p) ApiConnectRecord(c_theFiredTriggerPool,
|
||||
c_theSeizedIndexOperationPool);
|
||||
c_theIndexOperationPool);
|
||||
}
|
||||
// Init all fired triggers
|
||||
DLFifoList<TcFiredTriggerData> triggers(c_theFiredTriggerPool);
|
||||
|
@ -177,7 +176,6 @@ Dbtc::Dbtc(const class Configuration & conf):
|
|||
c_maxNumberOfFiredTriggers(0),
|
||||
c_theIndexes(c_theIndexPool),
|
||||
c_maxNumberOfIndexes(0),
|
||||
c_theIndexOperations(c_theIndexOperationPool),
|
||||
c_maxNumberOfIndexOperations(0),
|
||||
m_commitAckMarkerHash(m_commitAckMarkerPool)
|
||||
{
|
||||
|
|
|
@ -11371,16 +11371,21 @@ void Dbtc::execTCINDXREQ(Signal* signal)
|
|||
jam();
|
||||
// This is a newly started transaction, clean-up
|
||||
releaseAllSeizedIndexOperations(regApiPtr);
|
||||
|
||||
regApiPtr->transid[0] = tcIndxReq->transId1;
|
||||
regApiPtr->transid[1] = tcIndxReq->transId2;
|
||||
}//if
|
||||
if (!seizeIndexOperation(regApiPtr, indexOpPtr)) {
|
||||
ndbout_c("here");
|
||||
|
||||
if (ERROR_INSERTED(8036) || !seizeIndexOperation(regApiPtr, indexOpPtr)) {
|
||||
jam();
|
||||
// Failed to allocate index operation
|
||||
TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
|
||||
|
||||
|
||||
tcIndxRef->connectPtr = tcIndxReq->senderData;
|
||||
tcIndxRef->transId[0] = regApiPtr->transid[0];
|
||||
tcIndxRef->transId[1] = regApiPtr->transid[1];
|
||||
tcIndxRef->errorCode = 4000;
|
||||
tcIndxRef->errorCode = 288;
|
||||
sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
|
||||
TcKeyRef::SignalLength, JBB);
|
||||
return;
|
||||
|
@ -11517,15 +11522,17 @@ void Dbtc::execINDXKEYINFO(Signal* signal)
|
|||
TcIndexOperationPtr indexOpPtr;
|
||||
TcIndexOperation* indexOp;
|
||||
|
||||
indexOpPtr.i = regApiPtr->accumulatingIndexOp;
|
||||
indexOp = c_theIndexOperations.getPtr(indexOpPtr.i);
|
||||
if (saveINDXKEYINFO(signal,
|
||||
indexOp,
|
||||
src,
|
||||
keyInfoLength)) {
|
||||
jam();
|
||||
// We have received all we need
|
||||
readIndexTable(signal, regApiPtr, indexOp);
|
||||
if((indexOpPtr.i = regApiPtr->accumulatingIndexOp) != RNIL)
|
||||
{
|
||||
indexOp = c_theIndexOperationPool.getPtr(indexOpPtr.i);
|
||||
if (saveINDXKEYINFO(signal,
|
||||
indexOp,
|
||||
src,
|
||||
keyInfoLength)) {
|
||||
jam();
|
||||
// We have received all we need
|
||||
readIndexTable(signal, regApiPtr, indexOp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11548,15 +11555,17 @@ void Dbtc::execINDXATTRINFO(Signal* signal)
|
|||
TcIndexOperationPtr indexOpPtr;
|
||||
TcIndexOperation* indexOp;
|
||||
|
||||
indexOpPtr.i = regApiPtr->accumulatingIndexOp;
|
||||
indexOp = c_theIndexOperations.getPtr(indexOpPtr.i);
|
||||
if (saveINDXATTRINFO(signal,
|
||||
indexOp,
|
||||
src,
|
||||
attrInfoLength)) {
|
||||
jam();
|
||||
// We have received all we need
|
||||
readIndexTable(signal, regApiPtr, indexOp);
|
||||
if((indexOpPtr.i = regApiPtr->accumulatingIndexOp) != RNIL)
|
||||
{
|
||||
indexOp = c_theIndexOperationPool.getPtr(indexOpPtr.i);
|
||||
if (saveINDXATTRINFO(signal,
|
||||
indexOp,
|
||||
src,
|
||||
attrInfoLength)) {
|
||||
jam();
|
||||
// We have received all we need
|
||||
readIndexTable(signal, regApiPtr, indexOp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11581,7 +11590,7 @@ bool Dbtc::saveINDXKEYINFO(Signal* signal,
|
|||
releaseIndexOperation(apiConnectptr.p, indexOp);
|
||||
terrorCode = 4000;
|
||||
abortErrorLab(signal);
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
if (receivedAllINDXKEYINFO(indexOp) && receivedAllINDXATTRINFO(indexOp)) {
|
||||
jam();
|
||||
|
@ -11614,7 +11623,7 @@ bool Dbtc::saveINDXATTRINFO(Signal* signal,
|
|||
releaseIndexOperation(apiConnectptr.p, indexOp);
|
||||
terrorCode = 4000;
|
||||
abortErrorLab(signal);
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
if (receivedAllINDXKEYINFO(indexOp) && receivedAllINDXATTRINFO(indexOp)) {
|
||||
jam();
|
||||
|
@ -11674,7 +11683,7 @@ void Dbtc::execTCKEYCONF(Signal* signal)
|
|||
|
||||
jamEntry();
|
||||
indexOpPtr.i = tcKeyConf->apiConnectPtr;
|
||||
TcIndexOperation* indexOp = c_theIndexOperations.getPtr(indexOpPtr.i);
|
||||
TcIndexOperation* indexOp = c_theIndexOperationPool.getPtr(indexOpPtr.i);
|
||||
Uint32 confInfo = tcKeyConf->confInfo;
|
||||
|
||||
/**
|
||||
|
@ -11763,7 +11772,7 @@ void Dbtc::execTCKEYREF(Signal* signal)
|
|||
|
||||
jamEntry();
|
||||
indexOpPtr.i = tcKeyRef->connectPtr;
|
||||
TcIndexOperation* indexOp = c_theIndexOperations.getPtr(indexOpPtr.i);
|
||||
TcIndexOperation* indexOp = c_theIndexOperationPool.getPtr(indexOpPtr.i);
|
||||
indexOpPtr.p = indexOp;
|
||||
if (!indexOp) {
|
||||
jam();
|
||||
|
@ -11864,7 +11873,7 @@ void Dbtc::execTRANSID_AI(Signal* signal)
|
|||
jamEntry();
|
||||
TcIndexOperationPtr indexOpPtr;
|
||||
indexOpPtr.i = transIdAI->connectPtr;
|
||||
TcIndexOperation* indexOp = c_theIndexOperations.getPtr(indexOpPtr.i);
|
||||
TcIndexOperation* indexOp = c_theIndexOperationPool.getPtr(indexOpPtr.i);
|
||||
indexOpPtr.p = indexOp;
|
||||
if (!indexOp) {
|
||||
jam();
|
||||
|
@ -11972,7 +11981,7 @@ void Dbtc::execTCROLLBACKREP(Signal* signal)
|
|||
jamEntry();
|
||||
TcIndexOperationPtr indexOpPtr;
|
||||
indexOpPtr.i = tcRollbackRep->connectPtr;
|
||||
TcIndexOperation* indexOp = c_theIndexOperations.getPtr(indexOpPtr.i);
|
||||
TcIndexOperation* indexOp = c_theIndexOperationPool.getPtr(indexOpPtr.i);
|
||||
indexOpPtr.p = indexOp;
|
||||
tcRollbackRep = (TcRollbackRep *)signal->getDataPtrSend();
|
||||
tcRollbackRep->connectPtr = indexOp->tcIndxReq.senderData;
|
||||
|
@ -12300,16 +12309,7 @@ void Dbtc::executeIndexOperation(Signal* signal,
|
|||
bool Dbtc::seizeIndexOperation(ApiConnectRecord* regApiPtr,
|
||||
TcIndexOperationPtr& indexOpPtr)
|
||||
{
|
||||
bool seizeOk;
|
||||
|
||||
seizeOk = c_theIndexOperations.seize(indexOpPtr);
|
||||
if (seizeOk) {
|
||||
jam();
|
||||
TcSeizedIndexOperationPtr seizedIndexOpPtr;
|
||||
seizeOk &= regApiPtr->theSeizedIndexOperations.seizeId(seizedIndexOpPtr,
|
||||
indexOpPtr.i);
|
||||
}
|
||||
return seizeOk;
|
||||
return regApiPtr->theSeizedIndexOperations.seize(indexOpPtr);
|
||||
}
|
||||
|
||||
void Dbtc::releaseIndexOperation(ApiConnectRecord* regApiPtr,
|
||||
|
@ -12323,18 +12323,16 @@ void Dbtc::releaseIndexOperation(ApiConnectRecord* regApiPtr,
|
|||
indexOp->expectedTransIdAI = 0;
|
||||
indexOp->transIdAI.release();
|
||||
regApiPtr->theSeizedIndexOperations.release(indexOp->indexOpId);
|
||||
c_theIndexOperations.release(indexOp->indexOpId);
|
||||
}
|
||||
|
||||
void Dbtc::releaseAllSeizedIndexOperations(ApiConnectRecord* regApiPtr)
|
||||
{
|
||||
TcSeizedIndexOperationPtr seizedIndexOpPtr;
|
||||
TcIndexOperationPtr seizedIndexOpPtr;
|
||||
|
||||
regApiPtr->theSeizedIndexOperations.first(seizedIndexOpPtr);
|
||||
while(seizedIndexOpPtr.i != RNIL) {
|
||||
jam();
|
||||
TcIndexOperation* indexOp =
|
||||
c_theIndexOperations.getPtr(seizedIndexOpPtr.i);
|
||||
TcIndexOperation* indexOp = seizedIndexOpPtr.p;
|
||||
|
||||
indexOp->indexOpState = IOS_NOOP;
|
||||
indexOp->expectedKeyInfo = 0;
|
||||
|
@ -12343,7 +12341,6 @@ void Dbtc::releaseAllSeizedIndexOperations(ApiConnectRecord* regApiPtr)
|
|||
indexOp->attrInfo.release();
|
||||
indexOp->expectedTransIdAI = 0;
|
||||
indexOp->transIdAI.release();
|
||||
c_theIndexOperations.release(seizedIndexOpPtr.i);
|
||||
regApiPtr->theSeizedIndexOperations.next(seizedIndexOpPtr);
|
||||
}
|
||||
regApiPtr->theSeizedIndexOperations.release();
|
||||
|
|
|
@ -130,7 +130,7 @@ ErrorReporter::formatMessage(ErrorCategory type,
|
|||
"Date/Time: %s\nType of error: %s\n"
|
||||
"Message: %s\nFault ID: %d\nProblem data: %s"
|
||||
"\nObject of reference: %s\nProgramName: %s\n"
|
||||
"ProcessID: %d\nTraceFile: %s\n***EOM***\n",
|
||||
"ProcessID: %d\nTraceFile: %s\n%s\n***EOM***\n",
|
||||
formatTimeStampString() ,
|
||||
errorType[type],
|
||||
lookupErrorMessage(faultID),
|
||||
|
@ -139,7 +139,8 @@ ErrorReporter::formatMessage(ErrorCategory type,
|
|||
objRef,
|
||||
my_progname,
|
||||
processId,
|
||||
theNameOfTheTraceFile ? theNameOfTheTraceFile : "<no tracefile>");
|
||||
theNameOfTheTraceFile ? theNameOfTheTraceFile : "<no tracefile>",
|
||||
NDB_VERSION_STRING);
|
||||
|
||||
// Add trailing blanks to get a fixed lenght of the message
|
||||
while (strlen(messptr) <= MESSAGE_LENGTH-3){
|
||||
|
|
|
@ -173,7 +173,7 @@ ErrorBundle ErrorCodes[] = {
|
|||
{ 4021, TR, "Out of Send Buffer space in NDB API" },
|
||||
{ 4022, TR, "Out of Send Buffer space in NDB API" },
|
||||
{ 4032, TR, "Out of Send Buffer space in NDB API" },
|
||||
|
||||
{ 288, TR, "Out of index operations in transaction coordinator (increase MaxNoOfConcurrentIndexOperations)" },
|
||||
/**
|
||||
* InsufficientSpace
|
||||
*/
|
||||
|
|
|
@ -116,8 +116,12 @@ BaseString NDBT_ResultRow::c_str() const {
|
|||
|
||||
NdbOut &
|
||||
operator << (NdbOut& ndbout, const NDBT_ResultRow & res) {
|
||||
for(int i = 0; i<res.cols; i++)
|
||||
ndbout << *(res.data[i]) << "\t";
|
||||
if (res.cols != 0)
|
||||
{
|
||||
ndbout << *(res.data[0]);
|
||||
for(int i = 1; i<res.cols; i++)
|
||||
ndbout << res.ad << *(res.data[i]);
|
||||
}
|
||||
return ndbout;
|
||||
}
|
||||
|
||||
|
|
133
sql/item.cc
133
sql/item.cc
|
@ -558,6 +558,11 @@ void Item::set_name(const char *str, uint length, CHARSET_INFO *cs)
|
|||
|
||||
bool Item::eq(const Item *item, bool binary_cmp) const
|
||||
{
|
||||
/*
|
||||
Note, that this is never TRUE if item is a Item_param:
|
||||
for all basic constants we have special checks, and Item_param's
|
||||
type() can be only among basic constant types.
|
||||
*/
|
||||
return type() == item->type() && name && item->name &&
|
||||
!my_strcasecmp(system_charset_info,name,item->name);
|
||||
}
|
||||
|
@ -602,7 +607,7 @@ Item *Item_string::safe_charset_converter(CHARSET_INFO *tocs)
|
|||
|
||||
bool Item_string::eq(const Item *item, bool binary_cmp) const
|
||||
{
|
||||
if (type() == item->type())
|
||||
if (type() == item->type() && item->basic_const_item())
|
||||
{
|
||||
if (binary_cmp)
|
||||
return !stringcmp(&str_value, &item->str_value);
|
||||
|
@ -1444,6 +1449,24 @@ void Item_decimal::print(String *str)
|
|||
}
|
||||
|
||||
|
||||
bool Item_decimal::eq(const Item *item, bool binary_cmp) const
|
||||
{
|
||||
if (type() == item->type() && item->basic_const_item())
|
||||
{
|
||||
/*
|
||||
We need to cast off const to call val_decimal(). This should
|
||||
be OK for a basic constant. Additionally, we can pass 0 as
|
||||
a true decimal constant will return its internal decimal
|
||||
storage and ignore the argument.
|
||||
*/
|
||||
Item *arg= (Item*) item;
|
||||
my_decimal *value= arg->val_decimal(0);
|
||||
return !my_decimal_cmp(&decimal_value, value);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
String *Item_float::val_str(String *str)
|
||||
{
|
||||
// following assert is redundant, because fixed=1 assigned in constructor
|
||||
|
@ -2195,6 +2218,72 @@ bool Item_param::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
|||
}
|
||||
|
||||
|
||||
bool Item_param::basic_const_item() const
|
||||
{
|
||||
if (state == NO_VALUE || state == TIME_VALUE)
|
||||
return FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
Item *
|
||||
Item_param::new_item()
|
||||
{
|
||||
/* see comments in the header file */
|
||||
switch (state) {
|
||||
case NULL_VALUE:
|
||||
return new Item_null(name);
|
||||
case INT_VALUE:
|
||||
return new Item_int(name, value.integer, max_length);
|
||||
case REAL_VALUE:
|
||||
return new Item_float(name, value.real, decimals, max_length);
|
||||
case STRING_VALUE:
|
||||
case LONG_DATA_VALUE:
|
||||
return new Item_string(name, str_value.c_ptr_quick(), str_value.length(),
|
||||
str_value.charset());
|
||||
case TIME_VALUE:
|
||||
break;
|
||||
case NO_VALUE:
|
||||
default:
|
||||
DBUG_ASSERT(0);
|
||||
};
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Item_param::eq(const Item *arg, bool binary_cmp) const
|
||||
{
|
||||
Item *item;
|
||||
if (!basic_const_item() || !arg->basic_const_item() || arg->type() != type())
|
||||
return FALSE;
|
||||
/*
|
||||
We need to cast off const to call val_int(). This should be OK for
|
||||
a basic constant.
|
||||
*/
|
||||
item= (Item*) arg;
|
||||
|
||||
switch (state) {
|
||||
case NULL_VALUE:
|
||||
return TRUE;
|
||||
case INT_VALUE:
|
||||
return value.integer == item->val_int() &&
|
||||
unsigned_flag == item->unsigned_flag;
|
||||
case REAL_VALUE:
|
||||
return value.real == item->val_real();
|
||||
case STRING_VALUE:
|
||||
case LONG_DATA_VALUE:
|
||||
if (binary_cmp)
|
||||
return !stringcmp(&str_value, &item->str_value);
|
||||
return !sortcmp(&str_value, &item->str_value, collation.collation);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* End of Item_param related */
|
||||
|
||||
void Item_param::print(String *str)
|
||||
{
|
||||
if (state == NO_VALUE)
|
||||
|
@ -3412,6 +3501,22 @@ int Item_decimal::save_in_field(Field *field, bool no_conversions)
|
|||
}
|
||||
|
||||
|
||||
bool Item_int::eq(const Item *arg, bool binary_cmp) const
|
||||
{
|
||||
/* No need to check for null value as basic constant can't be NULL */
|
||||
if (arg->basic_const_item() && arg->type() == type())
|
||||
{
|
||||
/*
|
||||
We need to cast off const to call val_int(). This should be OK for
|
||||
a basic constant.
|
||||
*/
|
||||
Item *item= (Item*) arg;
|
||||
return item->val_int() == value && item->unsigned_flag == unsigned_flag;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
Item_num *Item_uint::neg()
|
||||
{
|
||||
Item_decimal *item= new Item_decimal(value, 0);
|
||||
|
@ -3499,6 +3604,21 @@ void Item_float::print(String *str)
|
|||
In number context this is a longlong value.
|
||||
*/
|
||||
|
||||
bool Item_float::eq(const Item *arg, bool binary_cmp) const
|
||||
{
|
||||
if (arg->basic_const_item() && arg->type() == type())
|
||||
{
|
||||
/*
|
||||
We need to cast off const to call val_int(). This should be OK for
|
||||
a basic constant.
|
||||
*/
|
||||
Item *item= (Item*) arg;
|
||||
return item->val_real() == value;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
inline uint char_val(char X)
|
||||
{
|
||||
return (uint) (X >= '0' && X <= '9' ? X-'0' :
|
||||
|
@ -3569,6 +3689,17 @@ int Item_hex_string::save_in_field(Field *field, bool no_conversions)
|
|||
}
|
||||
|
||||
|
||||
bool Item_hex_string::eq(const Item *arg, bool binary_cmp) const
|
||||
{
|
||||
if (arg->basic_const_item() && arg->type() == type())
|
||||
{
|
||||
if (binary_cmp)
|
||||
return !stringcmp(&str_value, &arg->str_value);
|
||||
return !sortcmp(&str_value, &arg->str_value, collation.collation);
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
bin item.
|
||||
In string context this is a binary string.
|
||||
|
|
29
sql/item.h
29
sql/item.h
|
@ -434,7 +434,7 @@ public:
|
|||
virtual table_map not_null_tables() const { return used_tables(); }
|
||||
/*
|
||||
Returns true if this is a simple constant item like an integer, not
|
||||
a constant expression
|
||||
a constant expression. Used in the optimizer to propagate basic constants.
|
||||
*/
|
||||
virtual bool basic_const_item() const { return 0; }
|
||||
/* cloning of constant items (0 if it is not const) */
|
||||
|
@ -914,7 +914,6 @@ public:
|
|||
|
||||
bool convert_str_value(THD *thd);
|
||||
|
||||
Item *new_item() { return new Item_param(pos_in_query); }
|
||||
/*
|
||||
If value for parameter was not set we treat it as non-const
|
||||
so noone will use parameters value in fix_fields still
|
||||
|
@ -923,12 +922,29 @@ public:
|
|||
virtual table_map used_tables() const
|
||||
{ return state != NO_VALUE ? (table_map)0 : PARAM_TABLE_BIT; }
|
||||
void print(String *str);
|
||||
/* parameter never equal to other parameter of other item */
|
||||
bool eq(const Item *item, bool binary_cmp) const { return 0; }
|
||||
bool is_null()
|
||||
{ DBUG_ASSERT(state != NO_VALUE); return state == NULL_VALUE; }
|
||||
bool basic_const_item() const;
|
||||
/*
|
||||
This method is used to make a copy of a basic constant item when
|
||||
propagating constants in the optimizer. The reason to create a new
|
||||
item and not use the existing one is not precisely known (2005/04/16).
|
||||
Probably we are trying to preserve tree structure of items, in other
|
||||
words, avoid pointing at one item from two different nodes of the tree.
|
||||
Return a new basic constant item if parameter value is a basic
|
||||
constant, assert otherwise. This method is called only if
|
||||
basic_const_item returned TRUE.
|
||||
*/
|
||||
Item *new_item();
|
||||
/*
|
||||
Implement by-value equality evaluation if parameter value
|
||||
is set and is a basic constant (integer, real or string).
|
||||
Otherwise return FALSE.
|
||||
*/
|
||||
bool eq(const Item *item, bool binary_cmp) const;
|
||||
};
|
||||
|
||||
|
||||
class Item_int :public Item_num
|
||||
{
|
||||
public:
|
||||
|
@ -956,6 +972,7 @@ public:
|
|||
void cleanup() {}
|
||||
void print(String *str);
|
||||
Item_num *neg() { value= -value; return this; }
|
||||
bool eq(const Item *, bool binary_cmp) const;
|
||||
};
|
||||
|
||||
|
||||
|
@ -1022,8 +1039,10 @@ public:
|
|||
unsigned_flag= !decimal_value.sign();
|
||||
return this;
|
||||
}
|
||||
bool eq(const Item *, bool binary_cmp) const;
|
||||
};
|
||||
|
||||
|
||||
class Item_float :public Item_num
|
||||
{
|
||||
char *presentation;
|
||||
|
@ -1059,6 +1078,7 @@ public:
|
|||
{ return new Item_float(name, value, decimals, max_length); }
|
||||
Item_num *neg() { value= -value; return this; }
|
||||
void print(String *str);
|
||||
bool eq(const Item *, bool binary_cmp) const;
|
||||
};
|
||||
|
||||
|
||||
|
@ -1198,6 +1218,7 @@ public:
|
|||
enum_field_types field_type() const { return MYSQL_TYPE_VARCHAR; }
|
||||
// to prevent drop fixed flag (no need parent cleanup call)
|
||||
void cleanup() {}
|
||||
bool eq(const Item *item, bool binary_cmp) const;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -1395,11 +1395,12 @@ void Item_func_neg::fix_length_and_dec()
|
|||
/*
|
||||
If this is in integer context keep the context as integer if possible
|
||||
(This is how multiplication and other integer functions works)
|
||||
Use val() to get value as arg_type doesn't mean that item is
|
||||
Item_int or Item_real due to existence of Item_param.
|
||||
*/
|
||||
if (hybrid_type == INT_RESULT &&
|
||||
args[0]->type() == INT_ITEM &&
|
||||
((ulonglong) ((Item_uint*) args[0])->value >=
|
||||
(ulonglong) LONGLONG_MIN))
|
||||
((ulonglong) args[0]->val_int() >= (ulonglong) LONGLONG_MIN))
|
||||
{
|
||||
/*
|
||||
Ensure that result is converted to DECIMAL, as longlong can't hold
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
# started and shut down when the systems goes down.
|
||||
|
||||
# Comments to support chkconfig on RedHat Linux
|
||||
# chkconfig: 2345 90 20
|
||||
# chkconfig: 2345 64 36
|
||||
# description: A very fast and reliable SQL database engine.
|
||||
|
||||
# Comments to support LSB init script conventions
|
||||
|
|
Loading…
Reference in a new issue