Commit 65e5d9e9 authored by joreland@mysql.com's avatar joreland@mysql.com

Merge mysql.com:/home/jonas/src/mysql-5.0

into mysql.com:/home/jonas/src/mysql-5.0-ndb
parents e330bb5b b6fba9b4
...@@ -434,7 +434,7 @@ d date YES NULL ...@@ -434,7 +434,7 @@ d date YES NULL
e varchar(1) NO e varchar(1) NO
f datetime YES NULL f datetime YES NULL
g time YES NULL g time YES NULL
h varbinary(23) NO h longblob NO
dd time YES NULL dd time YES NULL
select * from t2; select * from t2;
a b c d e f g h dd a b c d e f g h dd
......
...@@ -464,3 +464,11 @@ SELECT DISTINCT html,SUM(rout)/(SUM(rin)+1) as 'prod' FROM t1 GROUP BY rin; ...@@ -464,3 +464,11 @@ SELECT DISTINCT html,SUM(rout)/(SUM(rin)+1) as 'prod' FROM t1 GROUP BY rin;
html prod html prod
1 0.0000 1 0.0000
drop table t1; drop table t1;
create table t1 (id int, dsc varchar(50));
insert into t1 values (1, "line number one"), (2, "line number two"), (3, "line number three");
select distinct id, IFNULL(dsc, '-') from t1;
id IFNULL(dsc, '-')
1 line number one
2 line number two
3 line number three
drop table t1;
...@@ -40,3 +40,22 @@ p u o ...@@ -40,3 +40,22 @@ p u o
5 5 5 5 5 5
drop table t1; drop table t1;
drop table t2; drop table t2;
create table t1 (p int not null primary key, u int not null) engine=ndb;
insert into t1 values (1,1),(2,2),(3,3);
create table t2 as
select t1.*
from t1 as t1, t1 as t2, t1 as t3, t1 as t4, t1 as t5, t1 as t6, t1 as t7, t1 as t8
where t1.u = t2.u
and t2.u = t3.u
and t3.u = t4.u
and t4.u = t5.u
and t5.u = t6.u
and t6.u = t7.u
and t7.u = t8.u;
select * from t2 order by 1;
p u
1 1
2 2
3 3
drop table t1;
drop table t2;
...@@ -672,3 +672,17 @@ select default(t30.s1) from t30; ...@@ -672,3 +672,17 @@ select default(t30.s1) from t30;
end| end|
drop procedure bug10969| drop procedure bug10969|
drop table t1| drop table t1|
prepare stmt from "select 1";
create procedure p() deallocate prepare stmt;
ERROR 0A000: DEALLOCATE is not allowed in stored procedures
create function f() returns int begin deallocate prepare stmt;
ERROR 0A000: DEALLOCATE is not allowed in stored procedures
create procedure p() prepare stmt from "select 1";
ERROR 0A000: PREPARE is not allowed in stored procedures
create function f() returns int begin prepare stmt from "select 1";
ERROR 0A000: PREPARE is not allowed in stored procedures
create procedure p() execute stmt;
ERROR 0A000: EXECUTE is not allowed in stored procedures
create function f() returns int begin execute stmt;
ERROR 0A000: EXECUTE is not allowed in stored procedures
deallocate prepare stmt;
...@@ -40,3 +40,18 @@ Id User Host db Command Time State Info ...@@ -40,3 +40,18 @@ Id User Host db Command Time State Info
unlock tables; unlock tables;
drop procedure bug9486; drop procedure bug9486;
drop table t1, t2; drop table t1, t2;
drop procedure if exists bug11158;
create procedure bug11158() delete t1 from t1, t2 where t1.id = t2.id;
create table t1 (id int, j int);
insert into t1 values (1, 1), (2, 2);
create table t2 (id int);
insert into t2 values (1);
call bug11158();
select * from t1;
id j
2 2
lock tables t2 read;
call bug11158();
unlock tables;
drop procedure bug11158;
drop table t1, t2;
...@@ -896,6 +896,8 @@ create table t1( d1 decimal(18) unsigned, d2 decimal(20) unsigned, d3 decimal (2 ...@@ -896,6 +896,8 @@ create table t1( d1 decimal(18) unsigned, d2 decimal(20) unsigned, d3 decimal (2
insert into t1 values(1,-1,-1); insert into t1 values(1,-1,-1);
ERROR 22003: Out of range value adjusted for column 'd2' at row 1 ERROR 22003: Out of range value adjusted for column 'd2' at row 1
drop table t1; drop table t1;
set sql_mode='';
set @sav_dpi= @@div_precision_increment;
set @@div_precision_increment=15; set @@div_precision_increment=15;
create table t1 (col1 int, col2 decimal(30,25), col3 numeric(30,25)); create table t1 (col1 int, col2 decimal(30,25), col3 numeric(30,25));
insert into t1 values (1,0.0123456789012345678912345,0.0123456789012345678912345); insert into t1 values (1,0.0123456789012345678912345,0.0123456789012345678912345);
...@@ -909,3 +911,12 @@ select 77777777/7777777; ...@@ -909,3 +911,12 @@ select 77777777/7777777;
77777777/7777777 77777777/7777777
10.000000900000090 10.000000900000090
drop table t1; drop table t1;
set div_precision_increment= @sav_dpi;
create table t1 (a decimal(4,2));
insert into t1 values (0.00);
select * from t1 where a > -0.00;
a
select * from t1 where a = -0.00;
a
0.00
drop table t1;
...@@ -332,3 +332,11 @@ CREATE TABLE t1 ( ...@@ -332,3 +332,11 @@ CREATE TABLE t1 (
INSERT INTO t1 VALUES ('1',1,0); INSERT INTO t1 VALUES ('1',1,0);
SELECT DISTINCT html,SUM(rout)/(SUM(rin)+1) as 'prod' FROM t1 GROUP BY rin; SELECT DISTINCT html,SUM(rout)/(SUM(rin)+1) as 'prod' FROM t1 GROUP BY rin;
drop table t1; drop table t1;
#
# Bug 9784 DISTINCT IFNULL truncates data
#
create table t1 (id int, dsc varchar(50));
insert into t1 values (1, "line number one"), (2, "line number two"), (3, "line number three");
select distinct id, IFNULL(dsc, '-') from t1;
drop table t1;
...@@ -37,3 +37,26 @@ drop table t1; ...@@ -37,3 +37,26 @@ drop table t1;
drop table t2; drop table t2;
# bug#5367 # bug#5367
########## ##########
###
# bug#11205
create table t1 (p int not null primary key, u int not null) engine=ndb;
insert into t1 values (1,1),(2,2),(3,3);
create table t2 as
select t1.*
from t1 as t1, t1 as t2, t1 as t3, t1 as t4, t1 as t5, t1 as t6, t1 as t7, t1 as t8
where t1.u = t2.u
and t2.u = t3.u
and t3.u = t4.u
and t4.u = t5.u
and t5.u = t6.u
and t6.u = t7.u
and t7.u = t8.u;
select * from t2 order by 1;
drop table t1;
drop table t2;
...@@ -965,3 +965,24 @@ drop procedure bug10969| ...@@ -965,3 +965,24 @@ drop procedure bug10969|
drop table t1| drop table t1|
delimiter ;| delimiter ;|
#
# Bug#10975, #10605, #7115: Dynamic SQL by means of
# PREPARE/EXECUTE/DEALLOCATE is not supported yet.
# Check that an error message is returned.
#
prepare stmt from "select 1";
--error ER_SP_BADSTATEMENT
create procedure p() deallocate prepare stmt;
--error ER_SP_BADSTATEMENT
create function f() returns int begin deallocate prepare stmt;
--error ER_SP_BADSTATEMENT
create procedure p() prepare stmt from "select 1";
--error ER_SP_BADSTATEMENT
create function f() returns int begin prepare stmt from "select 1";
--error ER_SP_BADSTATEMENT
create procedure p() execute stmt;
--error ER_SP_BADSTATEMENT
create function f() returns int begin execute stmt;
deallocate prepare stmt;
...@@ -84,6 +84,32 @@ reap; ...@@ -84,6 +84,32 @@ reap;
drop procedure bug9486; drop procedure bug9486;
drop table t1, t2; drop table t1, t2;
#
# BUG#11158: Can't perform multi-delete in stored procedure
#
--disable_warnings
drop procedure if exists bug11158;
--enable_warnings
create procedure bug11158() delete t1 from t1, t2 where t1.id = t2.id;
create table t1 (id int, j int);
insert into t1 values (1, 1), (2, 2);
create table t2 (id int);
insert into t2 values (1);
# Procedure should work and cause proper effect (delete only first row)
call bug11158();
select * from t1;
# Also let us test that we obtain only read (and thus non exclusive) lock
# for table from which we are not going to delete rows.
connection con2root;
lock tables t2 read;
connection con1root;
call bug11158();
connection con2root;
unlock tables;
connection con1root;
# Clean-up
drop procedure bug11158;
drop table t1, t2;
# #
# BUG#NNNN: New bug synopsis # BUG#NNNN: New bug synopsis
......
...@@ -934,10 +934,12 @@ create table t1( d1 decimal(18) unsigned, d2 decimal(20) unsigned, d3 decimal (2 ...@@ -934,10 +934,12 @@ create table t1( d1 decimal(18) unsigned, d2 decimal(20) unsigned, d3 decimal (2
--error 1264 --error 1264
insert into t1 values(1,-1,-1); insert into t1 values(1,-1,-1);
drop table t1; drop table t1;
set sql_mode='';
# #
# Bug #8425 (insufficient precision of the division) # Bug #8425 (insufficient precision of the division)
# #
set @sav_dpi= @@div_precision_increment;
set @@div_precision_increment=15; set @@div_precision_increment=15;
create table t1 (col1 int, col2 decimal(30,25), col3 numeric(30,25)); create table t1 (col1 int, col2 decimal(30,25), col3 numeric(30,25));
insert into t1 values (1,0.0123456789012345678912345,0.0123456789012345678912345); insert into t1 values (1,0.0123456789012345678912345,0.0123456789012345678912345);
...@@ -945,4 +947,13 @@ select col2/9999999999 from t1 where col1=1; ...@@ -945,4 +947,13 @@ select col2/9999999999 from t1 where col1=1;
select 9999999999/col2 from t1 where col1=1; select 9999999999/col2 from t1 where col1=1;
select 77777777/7777777; select 77777777/7777777;
drop table t1; drop table t1;
set div_precision_increment= @sav_dpi;
#
# Bug #10896 (0.00 > -0.00)
#
create table t1 (a decimal(4,2));
insert into t1 values (0.00);
select * from t1 where a > -0.00;
select * from t1 where a = -0.00;
drop table t1;
...@@ -1616,7 +1616,7 @@ private: ...@@ -1616,7 +1616,7 @@ private:
Uint32 theNoOfPreparedTransactions; Uint32 theNoOfPreparedTransactions;
Uint32 theNoOfSentTransactions; Uint32 theNoOfSentTransactions;
Uint32 theNoOfCompletedTransactions; Uint32 theNoOfCompletedTransactions;
Uint32 theNoOfAllocatedTransactions; Uint32 theRemainingStartTransactions;
Uint32 theMaxNoOfTransactions; Uint32 theMaxNoOfTransactions;
Uint32 theMinNoOfEventsToWakeUp; Uint32 theMinNoOfEventsToWakeUp;
......
...@@ -425,12 +425,20 @@ Ndb::startTransactionLocal(Uint32 aPriority, Uint32 nodeId) ...@@ -425,12 +425,20 @@ Ndb::startTransactionLocal(Uint32 aPriority, Uint32 nodeId)
DBUG_ENTER("Ndb::startTransactionLocal"); DBUG_ENTER("Ndb::startTransactionLocal");
DBUG_PRINT("enter", ("nodeid: %d", nodeId)); DBUG_PRINT("enter", ("nodeid: %d", nodeId));
if(unlikely(theRemainingStartTransactions == 0))
{
theError.code = 4006;
DBUG_RETURN(0);
}
NdbTransaction* tConnection; NdbTransaction* tConnection;
Uint64 tFirstTransId = theFirstTransId; Uint64 tFirstTransId = theFirstTransId;
tConnection = doConnect(nodeId); tConnection = doConnect(nodeId);
if (tConnection == NULL) { if (tConnection == NULL) {
DBUG_RETURN(NULL); DBUG_RETURN(NULL);
}//if }//if
theRemainingStartTransactions--;
NdbTransaction* tConNext = theTransactionList; NdbTransaction* tConNext = theTransactionList;
tConnection->init(); tConnection->init();
theTransactionList = tConnection; // into a transaction list. theTransactionList = tConnection; // into a transaction list.
...@@ -481,6 +489,7 @@ Ndb::closeTransaction(NdbTransaction* aConnection) ...@@ -481,6 +489,7 @@ Ndb::closeTransaction(NdbTransaction* aConnection)
CHECK_STATUS_MACRO_VOID; CHECK_STATUS_MACRO_VOID;
tCon = theTransactionList; tCon = theTransactionList;
theRemainingStartTransactions++;
DBUG_PRINT("info",("close trans: 0x%x transid: 0x%llx", DBUG_PRINT("info",("close trans: 0x%x transid: 0x%llx",
aConnection, aConnection->getTransactionId())); aConnection, aConnection->getTransactionId()));
......
...@@ -89,15 +89,18 @@ int ...@@ -89,15 +89,18 @@ int
NdbScanOperation::init(const NdbTableImpl* tab, NdbTransaction* myConnection) NdbScanOperation::init(const NdbTableImpl* tab, NdbTransaction* myConnection)
{ {
m_transConnection = myConnection; m_transConnection = myConnection;
//NdbTransaction* aScanConnection = theNdb->startTransaction(myConnection); //NdbConnection* aScanConnection = theNdb->startTransaction(myConnection);
theNdb->theRemainingStartTransactions++; // will be checked in hupp...
NdbTransaction* aScanConnection = theNdb->hupp(myConnection); NdbTransaction* aScanConnection = theNdb->hupp(myConnection);
if (!aScanConnection){ if (!aScanConnection){
theNdb->theRemainingStartTransactions--;
setErrorCodeAbort(theNdb->getNdbError().code); setErrorCodeAbort(theNdb->getNdbError().code);
return -1; return -1;
} }
// NOTE! The hupped trans becomes the owner of the operation // NOTE! The hupped trans becomes the owner of the operation
if(NdbOperation::init(tab, aScanConnection) != 0){ if(NdbOperation::init(tab, aScanConnection) != 0){
theNdb->theRemainingStartTransactions--;
return -1; return -1;
} }
...@@ -675,6 +678,7 @@ void NdbScanOperation::close(bool forceSend, bool releaseOp) ...@@ -675,6 +678,7 @@ void NdbScanOperation::close(bool forceSend, bool releaseOp)
tCon->theScanningOp = 0; tCon->theScanningOp = 0;
theNdb->closeTransaction(tCon); theNdb->closeTransaction(tCon);
theNdb->theRemainingStartTransactions--;
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
......
...@@ -107,12 +107,10 @@ Ndb::init(int aMaxNoOfTransactions) ...@@ -107,12 +107,10 @@ Ndb::init(int aMaxNoOfTransactions)
goto error_handler; goto error_handler;
} }
tMaxNoOfTransactions = aMaxNoOfTransactions * 3;
if (tMaxNoOfTransactions > 1024) {
tMaxNoOfTransactions = 1024;
}//if
theMaxNoOfTransactions = tMaxNoOfTransactions;
tMaxNoOfTransactions = aMaxNoOfTransactions;
theMaxNoOfTransactions = tMaxNoOfTransactions;
theRemainingStartTransactions= tMaxNoOfTransactions;
thePreparedTransactionsArray = new NdbTransaction* [tMaxNoOfTransactions]; thePreparedTransactionsArray = new NdbTransaction* [tMaxNoOfTransactions];
theSentTransactionsArray = new NdbTransaction* [tMaxNoOfTransactions]; theSentTransactionsArray = new NdbTransaction* [tMaxNoOfTransactions];
theCompletedTransactionsArray = new NdbTransaction* [tMaxNoOfTransactions]; theCompletedTransactionsArray = new NdbTransaction* [tMaxNoOfTransactions];
......
...@@ -59,7 +59,7 @@ void Ndb::setup(Ndb_cluster_connection *ndb_cluster_connection, ...@@ -59,7 +59,7 @@ void Ndb::setup(Ndb_cluster_connection *ndb_cluster_connection,
theNoOfPreparedTransactions= 0; theNoOfPreparedTransactions= 0;
theNoOfSentTransactions= 0; theNoOfSentTransactions= 0;
theNoOfCompletedTransactions= 0; theNoOfCompletedTransactions= 0;
theNoOfAllocatedTransactions= 0; theRemainingStartTransactions= 0;
theMaxNoOfTransactions= 0; theMaxNoOfTransactions= 0;
theMinNoOfEventsToWakeUp= 0; theMinNoOfEventsToWakeUp= 0;
theConIdleList= NULL; theConIdleList= NULL;
......
...@@ -93,7 +93,6 @@ Ndb::createConIdleList(int aNrOfCon) ...@@ -93,7 +93,6 @@ Ndb::createConIdleList(int aNrOfCon)
} }
tNdbCon->Status(NdbTransaction::NotConnected); tNdbCon->Status(NdbTransaction::NotConnected);
} }
theNoOfAllocatedTransactions = aNrOfCon;
return aNrOfCon; return aNrOfCon;
} }
...@@ -193,16 +192,10 @@ Ndb::getNdbCon() ...@@ -193,16 +192,10 @@ Ndb::getNdbCon()
{ {
NdbTransaction* tNdbCon; NdbTransaction* tNdbCon;
if ( theConIdleList == NULL ) { if ( theConIdleList == NULL ) {
if (theNoOfAllocatedTransactions < theMaxNoOfTransactions) {
tNdbCon = new NdbTransaction(this); tNdbCon = new NdbTransaction(this);
if (tNdbCon == NULL) { if (tNdbCon == NULL) {
return NULL; return NULL;
}//if }//if
theNoOfAllocatedTransactions++;
} else {
ndbout << "theNoOfAllocatedTransactions = " << theNoOfAllocatedTransactions << " theMaxNoOfTransactions = " << theMaxNoOfTransactions << endl;
return NULL;
}//if
tNdbCon->next(NULL); tNdbCon->next(NULL);
} else } else
{ {
......
...@@ -1269,6 +1269,101 @@ int runBug_11133(NDBT_Context* ctx, NDBT_Step* step){ ...@@ -1269,6 +1269,101 @@ int runBug_11133(NDBT_Context* ctx, NDBT_Step* step){
return result; return result;
} }
int runScan_4006(NDBT_Context* ctx, NDBT_Step* step){
int result = NDBT_OK;
const Uint32 max= 5;
const NdbDictionary::Table* pTab = ctx->getTab();
Ndb* pNdb = new Ndb(&ctx->m_cluster_connection, "TEST_DB");
if (pNdb == NULL){
ndbout << "pNdb == NULL" << endl;
return NDBT_FAILED;
}
if (pNdb->init(max)){
ERR(pNdb->getNdbError());
delete pNdb;
return NDBT_FAILED;
}
NdbConnection* pCon = pNdb->startTransaction();
if (pCon == NULL){
pNdb->closeTransaction(pCon);
delete pNdb;
return NDBT_FAILED;
}
Uint32 i;
Vector<NdbScanOperation*> scans;
for(i = 0; i<10*max; i++)
{
NdbScanOperation* pOp = pCon->getNdbScanOperation(pTab->getName());
if (pOp == NULL){
ERR(pCon->getNdbError());
pNdb->closeTransaction(pCon);
delete pNdb;
return NDBT_FAILED;
}
if (pOp->readTuples() != 0){
pNdb->closeTransaction(pCon);
ERR(pOp->getNdbError());
delete pNdb;
return NDBT_FAILED;
}
scans.push_back(pOp);
}
// Dont' call any equal or setValues
// Execute should not work
int check = pCon->execute(NoCommit);
if (check == 0){
ndbout << "execute worked" << endl;
} else {
ERR(pCon->getNdbError());
}
for(i= 0; i<scans.size(); i++)
{
NdbScanOperation* pOp= scans[i];
while((check= pOp->nextResult()) == 0);
if(check != 1)
{
ERR(pOp->getNdbError());
pNdb->closeTransaction(pCon);
delete pNdb;
return NDBT_FAILED;
}
}
pNdb->closeTransaction(pCon);
Vector<NdbConnection*> cons;
for(i= 0; i<10*max; i++)
{
pCon= pNdb->startTransaction();
if(pCon)
cons.push_back(pCon);
else
break;
}
for(i= 0; i<cons.size(); i++)
{
cons[i]->close();
}
if(cons.size() != max)
{
result= NDBT_FAILED;
}
delete pNdb;
return result;
}
template class Vector<NdbScanOperation*>;
NDBT_TESTSUITE(testNdbApi); NDBT_TESTSUITE(testNdbApi);
...@@ -1351,6 +1446,12 @@ TESTCASE("Bug_11133", ...@@ -1351,6 +1446,12 @@ TESTCASE("Bug_11133",
INITIALIZER(runBug_11133); INITIALIZER(runBug_11133);
FINALIZER(runClearTable); FINALIZER(runClearTable);
} }
TESTCASE("Scan_4006",
"Check that getNdbScanOperation does not get 4006\n"){
INITIALIZER(runLoadTable);
INITIALIZER(runScan_4006);
FINALIZER(runClearTable);
}
NDBT_TESTSUITE_END(testNdbApi); NDBT_TESTSUITE_END(testNdbApi);
int main(int argc, const char** argv){ int main(int argc, const char** argv){
......
...@@ -520,6 +520,10 @@ max-time: 500 ...@@ -520,6 +520,10 @@ max-time: 500
cmd: testNdbApi cmd: testNdbApi
args: -n Bug_11133 T1 args: -n Bug_11133 T1
max-time: 500
cmd: testNdbApi
args: -n Scan_4006 T1
#max-time: 500 #max-time: 500
#cmd: testInterpreter #cmd: testInterpreter
#args: T1 #args: T1
......
...@@ -13,7 +13,7 @@ save_args=$* ...@@ -13,7 +13,7 @@ save_args=$*
VERSION="ndb-autotest.sh version 1.04" VERSION="ndb-autotest.sh version 1.04"
DATE=`date '+%Y-%m-%d'` DATE=`date '+%Y-%m-%d'`
HOST=`hostname -s` HOST=`hostname`
export DATE HOST export DATE HOST
set -e set -e
...@@ -330,8 +330,11 @@ start(){ ...@@ -330,8 +330,11 @@ start(){
tar cfz /tmp/res.$2.$$.tgz `basename $p2`/$DATE tar cfz /tmp/res.$2.$$.tgz `basename $p2`/$DATE
scp /tmp/res.$2.$$.tgz \ scp /tmp/res.$2.$$.tgz \
$result_host:$result_path/res.$DATE.$HOST.$2.$$.tgz $result_host:$result_path/res.$DATE.$HOST.$2.$$.tgz
if [ $? -eq 0 ]
then
rm -f /tmp/res.$2.$$.tgz rm -f /tmp/res.$2.$$.tgz
fi fi
fi
} }
######################################### #########################################
......
...@@ -41,7 +41,7 @@ static const int parallelism= 0; ...@@ -41,7 +41,7 @@ static const int parallelism= 0;
// Default value for max number of transactions // Default value for max number of transactions
// createable against NDB from this handler // createable against NDB from this handler
static const int max_transactions= 256; static const int max_transactions= 2;
static const char *ha_ndb_ext=".ndb"; static const char *ha_ndb_ext=".ndb";
......
...@@ -1109,12 +1109,14 @@ void Item_func_between::print(String *str) ...@@ -1109,12 +1109,14 @@ void Item_func_between::print(String *str)
void void
Item_func_ifnull::fix_length_and_dec() Item_func_ifnull::fix_length_and_dec()
{ {
agg_result_type(&hybrid_type, args, 2);
maybe_null=args[1]->maybe_null; maybe_null=args[1]->maybe_null;
decimals= max(args[0]->decimals, args[1]->decimals); decimals= max(args[0]->decimals, args[1]->decimals);
max_length= (max(args[0]->max_length - args[0]->decimals, max_length= (hybrid_type == DECIMAL_RESULT || hybrid_type == INT_RESULT) ?
args[1]->max_length - args[1]->decimals) + (max(args[0]->max_length - args[0]->decimals,
decimals); args[1]->max_length - args[1]->decimals) + decimals) :
agg_result_type(&hybrid_type, args, 2); max(args[0]->max_length, args[1]->max_length);
switch (hybrid_type) { switch (hybrid_type) {
case STRING_RESULT: case STRING_RESULT:
agg_arg_charsets(collation, args, arg_count, MY_COLL_CMP_CONV); agg_arg_charsets(collation, args, arg_count, MY_COLL_CMP_CONV);
...@@ -1225,16 +1227,7 @@ Item_func_if::fix_length_and_dec() ...@@ -1225,16 +1227,7 @@ Item_func_if::fix_length_and_dec()
{ {
maybe_null=args[1]->maybe_null || args[2]->maybe_null; maybe_null=args[1]->maybe_null || args[2]->maybe_null;
decimals= max(args[1]->decimals, args[2]->decimals); decimals= max(args[1]->decimals, args[2]->decimals);
if (decimals == NOT_FIXED_DEC)
{
max_length= max(args[1]->max_length, args[2]->max_length);
}
else
{
max_length= (max(args[1]->max_length - args[1]->decimals,
args[2]->max_length - args[2]->decimals) +
decimals);
}
enum Item_result arg1_type=args[1]->result_type(); enum Item_result arg1_type=args[1]->result_type();
enum Item_result arg2_type=args[2]->result_type(); enum Item_result arg2_type=args[2]->result_type();
bool null1=args[1]->const_item() && args[1]->null_value; bool null1=args[1]->const_item() && args[1]->null_value;
...@@ -1263,6 +1256,11 @@ Item_func_if::fix_length_and_dec() ...@@ -1263,6 +1256,11 @@ Item_func_if::fix_length_and_dec()
collation.set(&my_charset_bin); // Number collation.set(&my_charset_bin); // Number
} }
} }
max_length=
(cached_result_type == DECIMAL_RESULT || cached_result_type == INT_RESULT) ?
(max(args[1]->max_length - args[1]->decimals,
args[2]->max_length - args[2]->decimals) + decimals) :
max(args[1]->max_length, args[2]->max_length);
} }
......
...@@ -290,6 +290,11 @@ int int2my_decimal(uint mask, longlong i, my_bool unsigned_flag, my_decimal *d) ...@@ -290,6 +290,11 @@ int int2my_decimal(uint mask, longlong i, my_bool unsigned_flag, my_decimal *d)
inline inline
void my_decimal_neg(decimal_t *arg) void my_decimal_neg(decimal_t *arg)
{ {
if (decimal_is_zero(arg))
{
arg->sign= 0;
return;
}
decimal_neg(arg); decimal_neg(arg);
} }
......
...@@ -482,7 +482,7 @@ bool check_merge_table_access(THD *thd, char *db, ...@@ -482,7 +482,7 @@ bool check_merge_table_access(THD *thd, char *db,
TABLE_LIST *table_list); TABLE_LIST *table_list);
bool check_some_routine_access(THD *thd, const char *db, const char *name, bool is_proc); bool check_some_routine_access(THD *thd, const char *db, const char *name, bool is_proc);
bool multi_update_precheck(THD *thd, TABLE_LIST *tables); bool multi_update_precheck(THD *thd, TABLE_LIST *tables);
bool multi_delete_precheck(THD *thd, TABLE_LIST *tables, uint *table_count); bool multi_delete_precheck(THD *thd, TABLE_LIST *tables);
bool mysql_multi_update_prepare(THD *thd); bool mysql_multi_update_prepare(THD *thd);
bool mysql_multi_delete_prepare(THD *thd); bool mysql_multi_delete_prepare(THD *thd);
bool mysql_insert_select_prepare(THD *thd); bool mysql_insert_select_prepare(THD *thd);
...@@ -577,6 +577,7 @@ void mysql_init_query(THD *thd, uchar *buf, uint length); ...@@ -577,6 +577,7 @@ void mysql_init_query(THD *thd, uchar *buf, uint length);
bool mysql_new_select(LEX *lex, bool move_down); bool mysql_new_select(LEX *lex, bool move_down);
void create_select_for_variable(const char *var_name); void create_select_for_variable(const char *var_name);
void mysql_init_multi_delete(LEX *lex); void mysql_init_multi_delete(LEX *lex);
bool multi_delete_set_locks_and_link_aux_tables(LEX *lex);
void init_max_user_conn(void); void init_max_user_conn(void);
void init_update_queries(void); void init_update_queries(void);
void free_max_user_conn(void); void free_max_user_conn(void);
......
...@@ -42,7 +42,6 @@ static my_bool open_new_frm(const char *path, const char *alias, ...@@ -42,7 +42,6 @@ static my_bool open_new_frm(const char *path, const char *alias,
uint db_stat, uint prgflag, uint db_stat, uint prgflag,
uint ha_open_flags, TABLE *outparam, uint ha_open_flags, TABLE *outparam,
TABLE_LIST *table_desc, MEM_ROOT *mem_root); TABLE_LIST *table_desc, MEM_ROOT *mem_root);
static void relink_tables_for_multidelete(THD *thd);
extern "C" byte *table_cache_key(const byte *record,uint *length, extern "C" byte *table_cache_key(const byte *record,uint *length,
my_bool not_used __attribute__((unused))) my_bool not_used __attribute__((unused)))
...@@ -2089,7 +2088,6 @@ bool open_and_lock_tables(THD *thd, TABLE_LIST *tables) ...@@ -2089,7 +2088,6 @@ bool open_and_lock_tables(THD *thd, TABLE_LIST *tables)
(thd->fill_derived_tables() && (thd->fill_derived_tables() &&
mysql_handle_derived(thd->lex, &mysql_derived_filling))) mysql_handle_derived(thd->lex, &mysql_derived_filling)))
DBUG_RETURN(TRUE); /* purecov: inspected */ DBUG_RETURN(TRUE); /* purecov: inspected */
relink_tables_for_multidelete(thd);
DBUG_RETURN(0); DBUG_RETURN(0);
} }
...@@ -2119,36 +2117,10 @@ bool open_normal_and_derived_tables(THD *thd, TABLE_LIST *tables) ...@@ -2119,36 +2117,10 @@ bool open_normal_and_derived_tables(THD *thd, TABLE_LIST *tables)
if (open_tables(thd, &tables, &counter) || if (open_tables(thd, &tables, &counter) ||
mysql_handle_derived(thd->lex, &mysql_derived_prepare)) mysql_handle_derived(thd->lex, &mysql_derived_prepare))
DBUG_RETURN(TRUE); /* purecov: inspected */ DBUG_RETURN(TRUE); /* purecov: inspected */
relink_tables_for_multidelete(thd); // Not really needed, but
DBUG_RETURN(0); DBUG_RETURN(0);
} }
/*
Let us propagate pointers to open tables from global table list
to table lists for multi-delete
*/
static void relink_tables_for_multidelete(THD *thd)
{
if (thd->lex->all_selects_list->next_select_in_list())
{
for (SELECT_LEX *sl= thd->lex->all_selects_list;
sl;
sl= sl->next_select_in_list())
{
for (TABLE_LIST *cursor= (TABLE_LIST *) sl->table_list.first;
cursor;
cursor=cursor->next_local)
{
if (cursor->correspondent_table)
cursor->table= cursor->correspondent_table->table;
}
}
}
}
/* /*
Mark all real tables in the list as free for reuse. Mark all real tables in the list as free for reuse.
......
...@@ -751,7 +751,12 @@ typedef struct st_lex ...@@ -751,7 +751,12 @@ typedef struct st_lex
uint grant, grant_tot_col, which_columns; uint grant, grant_tot_col, which_columns;
uint fk_delete_opt, fk_update_opt, fk_match_option; uint fk_delete_opt, fk_update_opt, fk_match_option;
uint slave_thd_opt, start_transaction_opt; uint slave_thd_opt, start_transaction_opt;
uint table_count; /* used when usual update transformed in multiupdate */ /*
In LEX representing update which were transformed to multi-update
stores total number of tables. For LEX representing multi-delete
holds number of tables from which we will delete records.
*/
uint table_count;
uint8 describe; uint8 describe;
uint8 derived_tables; uint8 derived_tables;
uint8 create_view_algorithm; uint8 create_view_algorithm;
......
...@@ -3291,10 +3291,9 @@ mysql_execute_command(THD *thd) ...@@ -3291,10 +3291,9 @@ mysql_execute_command(THD *thd)
DBUG_ASSERT(first_table == all_tables && first_table != 0); DBUG_ASSERT(first_table == all_tables && first_table != 0);
TABLE_LIST *aux_tables= TABLE_LIST *aux_tables=
(TABLE_LIST *)thd->lex->auxilliary_table_list.first; (TABLE_LIST *)thd->lex->auxilliary_table_list.first;
uint table_count;
multi_delete *result; multi_delete *result;
if ((res= multi_delete_precheck(thd, all_tables, &table_count))) if ((res= multi_delete_precheck(thd, all_tables)))
break; break;
/* condition will be TRUE on SP re-excuting */ /* condition will be TRUE on SP re-excuting */
...@@ -3311,7 +3310,7 @@ mysql_execute_command(THD *thd) ...@@ -3311,7 +3310,7 @@ mysql_execute_command(THD *thd)
goto error; goto error;
if (!thd->is_fatal_error && (result= new multi_delete(thd,aux_tables, if (!thd->is_fatal_error && (result= new multi_delete(thd,aux_tables,
table_count))) lex->table_count)))
{ {
res= mysql_select(thd, &select_lex->ref_pointer_array, res= mysql_select(thd, &select_lex->ref_pointer_array,
select_lex->get_table_list(), select_lex->get_table_list(),
...@@ -6801,23 +6800,19 @@ bool multi_update_precheck(THD *thd, TABLE_LIST *tables) ...@@ -6801,23 +6800,19 @@ bool multi_update_precheck(THD *thd, TABLE_LIST *tables)
multi_delete_precheck() multi_delete_precheck()
thd Thread handler thd Thread handler
tables Global/local table list tables Global/local table list
table_count Pointer to table counter
RETURN VALUE RETURN VALUE
FALSE OK FALSE OK
TRUE error TRUE error
*/ */
bool multi_delete_precheck(THD *thd, TABLE_LIST *tables, uint *table_count) bool multi_delete_precheck(THD *thd, TABLE_LIST *tables)
{ {
SELECT_LEX *select_lex= &thd->lex->select_lex; SELECT_LEX *select_lex= &thd->lex->select_lex;
TABLE_LIST *aux_tables= TABLE_LIST *aux_tables=
(TABLE_LIST *)thd->lex->auxilliary_table_list.first; (TABLE_LIST *)thd->lex->auxilliary_table_list.first;
TABLE_LIST *target_tbl;
DBUG_ENTER("multi_delete_precheck"); DBUG_ENTER("multi_delete_precheck");
*table_count= 0;
/* sql_yacc guarantees that tables and aux_tables are not zero */ /* sql_yacc guarantees that tables and aux_tables are not zero */
DBUG_ASSERT(aux_tables != 0); DBUG_ASSERT(aux_tables != 0);
if (check_db_used(thd, tables) || check_db_used(thd,aux_tables) || if (check_db_used(thd, tables) || check_db_used(thd,aux_tables) ||
...@@ -6830,9 +6825,35 @@ bool multi_delete_precheck(THD *thd, TABLE_LIST *tables, uint *table_count) ...@@ -6830,9 +6825,35 @@ bool multi_delete_precheck(THD *thd, TABLE_LIST *tables, uint *table_count)
ER(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE), MYF(0)); ER(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE), MYF(0));
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
} }
for (target_tbl= aux_tables; target_tbl; target_tbl= target_tbl->next_local) DBUG_RETURN(FALSE);
}
/*
Link tables in auxilary table list of multi-delete with corresponding
elements in main table list, and set proper locks for them.
SYNOPSIS
multi_delete_set_locks_and_link_aux_tables()
lex - pointer to LEX representing multi-delete
RETURN VALUE
FALSE - success
TRUE - error
*/
bool multi_delete_set_locks_and_link_aux_tables(LEX *lex)
{
TABLE_LIST *tables= (TABLE_LIST*)lex->select_lex.table_list.first;
TABLE_LIST *target_tbl;
DBUG_ENTER("multi_delete_set_locks_and_link_aux_tables");
lex->table_count= 0;
for (target_tbl= (TABLE_LIST *)lex->auxilliary_table_list.first;
target_tbl; target_tbl= target_tbl->next_local)
{ {
(*table_count)++; lex->table_count++;
/* All tables in aux_tables must be found in FROM PART */ /* All tables in aux_tables must be found in FROM PART */
TABLE_LIST *walk; TABLE_LIST *walk;
for (walk= tables; walk; walk= walk->next_local) for (walk= tables; walk; walk= walk->next_local)
...@@ -6850,14 +6871,6 @@ bool multi_delete_precheck(THD *thd, TABLE_LIST *tables, uint *table_count) ...@@ -6850,14 +6871,6 @@ bool multi_delete_precheck(THD *thd, TABLE_LIST *tables, uint *table_count)
} }
walk->lock_type= target_tbl->lock_type; walk->lock_type= target_tbl->lock_type;
target_tbl->correspondent_table= walk; // Remember corresponding table target_tbl->correspondent_table= walk; // Remember corresponding table
/* in case of subselects, we need to set lock_type in
* corresponding table in list of all tables */
if (walk->correspondent_table)
{
target_tbl->correspondent_table= walk->correspondent_table;
walk->correspondent_table->lock_type= walk->lock_type;
}
} }
DBUG_RETURN(FALSE); DBUG_RETURN(FALSE);
} }
......
This diff is collapsed.
...@@ -919,6 +919,11 @@ deallocate: ...@@ -919,6 +919,11 @@ deallocate:
yyerror(ER(ER_SYNTAX_ERROR)); yyerror(ER(ER_SYNTAX_ERROR));
YYABORT; YYABORT;
} }
if (lex->sphead)
{
my_error(ER_SP_BADSTATEMENT, MYF(0), "DEALLOCATE");
YYABORT;
}
lex->sql_command= SQLCOM_DEALLOCATE_PREPARE; lex->sql_command= SQLCOM_DEALLOCATE_PREPARE;
lex->prepared_stmt_name= $3; lex->prepared_stmt_name= $3;
}; };
...@@ -939,6 +944,11 @@ prepare: ...@@ -939,6 +944,11 @@ prepare:
yyerror(ER(ER_SYNTAX_ERROR)); yyerror(ER(ER_SYNTAX_ERROR));
YYABORT; YYABORT;
} }
if (lex->sphead)
{
my_error(ER_SP_BADSTATEMENT, MYF(0), "PREPARE");
YYABORT;
}
lex->sql_command= SQLCOM_PREPARE; lex->sql_command= SQLCOM_PREPARE;
lex->prepared_stmt_name= $2; lex->prepared_stmt_name= $2;
}; };
...@@ -969,6 +979,11 @@ execute: ...@@ -969,6 +979,11 @@ execute:
yyerror(ER(ER_SYNTAX_ERROR)); yyerror(ER(ER_SYNTAX_ERROR));
YYABORT; YYABORT;
} }
if (lex->sphead)
{
my_error(ER_SP_BADSTATEMENT, MYF(0), "EXECUTE");
YYABORT;
}
lex->sql_command= SQLCOM_EXECUTE; lex->sql_command= SQLCOM_EXECUTE;
lex->prepared_stmt_name= $2; lex->prepared_stmt_name= $2;
} }
...@@ -6132,10 +6147,17 @@ single_multi: ...@@ -6132,10 +6147,17 @@ single_multi:
| table_wild_list | table_wild_list
{ mysql_init_multi_delete(Lex); } { mysql_init_multi_delete(Lex); }
FROM join_table_list where_clause FROM join_table_list where_clause
{
if (multi_delete_set_locks_and_link_aux_tables(Lex))
YYABORT;
}
| FROM table_wild_list | FROM table_wild_list
{ mysql_init_multi_delete(Lex); } { mysql_init_multi_delete(Lex); }
USING join_table_list where_clause USING join_table_list where_clause
{} {
if (multi_delete_set_locks_and_link_aux_tables(Lex))
YYABORT;
}
; ;
table_wild_list: table_wild_list:
......
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