mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
Merge spetrunia@bk-internal.mysql.com:/home/bk/mysql-4.1
into mysql.com:/home/psergey/mysql-4.1-bug9103
This commit is contained in:
@ -51,14 +51,19 @@ innobase_invalidate_query_cache(
|
|||||||
chars count */
|
chars count */
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
This function returns true if SQL-query in the current thread
|
This function returns true if
|
||||||
|
|
||||||
|
1) SQL-query in the current thread
|
||||||
is either REPLACE or LOAD DATA INFILE REPLACE.
|
is either REPLACE or LOAD DATA INFILE REPLACE.
|
||||||
|
|
||||||
|
2) SQL-query in the current thread
|
||||||
|
is INSERT ON DUPLICATE KEY UPDATE.
|
||||||
|
|
||||||
NOTE that /mysql/innobase/row/row0ins.c must contain the
|
NOTE that /mysql/innobase/row/row0ins.c must contain the
|
||||||
prototype for this function ! */
|
prototype for this function ! */
|
||||||
|
|
||||||
ibool
|
ibool
|
||||||
innobase_query_is_replace(void);
|
innobase_query_is_update(void);
|
||||||
/*===========================*/
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
Creates an insert node struct. */
|
Creates an insert node struct. */
|
||||||
@ -1562,12 +1567,12 @@ row_ins_scan_sec_index_for_duplicate(
|
|||||||
trx = thr_get_trx(thr);
|
trx = thr_get_trx(thr);
|
||||||
ut_ad(trx);
|
ut_ad(trx);
|
||||||
|
|
||||||
if (innobase_query_is_replace()) {
|
if (innobase_query_is_update()) {
|
||||||
|
|
||||||
/* The manual defines the REPLACE semantics that it
|
/* If the SQL-query will update or replace
|
||||||
is either an INSERT or DELETE(s) for duplicate key
|
duplicate key we will take X-lock for
|
||||||
+ INSERT. Therefore, we should take X-lock for
|
duplicates ( REPLACE, LOAD DATAFILE REPLACE,
|
||||||
duplicates */
|
INSERT ON DUPLICATE KEY UPDATE). */
|
||||||
|
|
||||||
err = row_ins_set_exclusive_rec_lock(
|
err = row_ins_set_exclusive_rec_lock(
|
||||||
LOCK_ORDINARY,rec,index,thr);
|
LOCK_ORDINARY,rec,index,thr);
|
||||||
@ -1675,12 +1680,12 @@ row_ins_duplicate_error_in_clust(
|
|||||||
sure that in roll-forward we get the same duplicate
|
sure that in roll-forward we get the same duplicate
|
||||||
errors as in original execution */
|
errors as in original execution */
|
||||||
|
|
||||||
if (innobase_query_is_replace()) {
|
if (innobase_query_is_update()) {
|
||||||
|
|
||||||
/* The manual defines the REPLACE semantics
|
/* If the SQL-query will update or replace
|
||||||
that it is either an INSERT or DELETE(s)
|
duplicate key we will take X-lock for
|
||||||
for duplicate key + INSERT. Therefore, we
|
duplicates ( REPLACE, LOAD DATAFILE REPLACE,
|
||||||
should take X-lock for duplicates */
|
INSERT ON DUPLICATE KEY UPDATE). */
|
||||||
|
|
||||||
err = row_ins_set_exclusive_rec_lock(
|
err = row_ins_set_exclusive_rec_lock(
|
||||||
LOCK_REC_NOT_GAP,rec,cursor->index,
|
LOCK_REC_NOT_GAP,rec,cursor->index,
|
||||||
@ -1713,12 +1718,12 @@ row_ins_duplicate_error_in_clust(
|
|||||||
if (rec != page_get_supremum_rec(page)) {
|
if (rec != page_get_supremum_rec(page)) {
|
||||||
|
|
||||||
|
|
||||||
/* The manual defines the REPLACE semantics that it
|
if (innobase_query_is_update()) {
|
||||||
is either an INSERT or DELETE(s) for duplicate key
|
|
||||||
+ INSERT. Therefore, we should take X-lock for
|
|
||||||
duplicates. */
|
|
||||||
|
|
||||||
if (innobase_query_is_replace()) {
|
/* If the SQL-query will update or replace
|
||||||
|
duplicate key we will take X-lock for
|
||||||
|
duplicates ( REPLACE, LOAD DATAFILE REPLACE,
|
||||||
|
INSERT ON DUPLICATE KEY UPDATE). */
|
||||||
|
|
||||||
err = row_ins_set_exclusive_rec_lock(
|
err = row_ins_set_exclusive_rec_lock(
|
||||||
LOCK_REC_NOT_GAP,
|
LOCK_REC_NOT_GAP,
|
||||||
|
@ -185,6 +185,7 @@ insert into test values
|
|||||||
('2001-01-01 01:01:01', '-01:01:01', '-23:59:59', "1997-12-31 23:59:59.000001"),
|
('2001-01-01 01:01:01', '-01:01:01', '-23:59:59', "1997-12-31 23:59:59.000001"),
|
||||||
('1997-12-31 23:59:59.000001', '-23:59:59', '-01:01:01', '2001-01-01 01:01:01'),
|
('1997-12-31 23:59:59.000001', '-23:59:59', '-01:01:01', '2001-01-01 01:01:01'),
|
||||||
('2001-01-01 01:01:01', '01:01:01', '-1 01:01:01', null),
|
('2001-01-01 01:01:01', '01:01:01', '-1 01:01:01', null),
|
||||||
|
('2001-01-01 01:01:01', '-01:01:01', '1 01:01:01', '2001-01-01 01:01:01'),
|
||||||
('2001-01-01 01:01:01', null, '-1 01:01:01', null),
|
('2001-01-01 01:01:01', null, '-1 01:01:01', null),
|
||||||
(null, null, null, null),
|
(null, null, null, null),
|
||||||
('2001-01-01 01:01:01', '01:01:01', '1 01:01:01', '2001-01-01 01:01:01');
|
('2001-01-01 01:01:01', '01:01:01', '1 01:01:01', '2001-01-01 01:01:01');
|
||||||
@ -194,6 +195,7 @@ ttt qqq
|
|||||||
2001-01-01 00:00:00 -25:01:00
|
2001-01-01 00:00:00 -25:01:00
|
||||||
1997-12-31 00:00:00 -25:01:00
|
1997-12-31 00:00:00 -25:01:00
|
||||||
2001-01-01 02:02:02 -24:00:00
|
2001-01-01 02:02:02 -24:00:00
|
||||||
|
2001-01-01 00:00:00 24:00:00
|
||||||
NULL NULL
|
NULL NULL
|
||||||
NULL NULL
|
NULL NULL
|
||||||
2001-01-01 02:02:02 26:02:02
|
2001-01-01 02:02:02 26:02:02
|
||||||
@ -203,6 +205,7 @@ ttt qqq
|
|||||||
26305:01:02 22:58:58
|
26305:01:02 22:58:58
|
||||||
-26305:01:02 -22:58:58
|
-26305:01:02 -22:58:58
|
||||||
NULL 26:02:02
|
NULL 26:02:02
|
||||||
|
00:00:00 -26:02:02
|
||||||
NULL NULL
|
NULL NULL
|
||||||
NULL NULL
|
NULL NULL
|
||||||
00:00:00 -24:00:00
|
00:00:00 -24:00:00
|
||||||
|
@ -100,6 +100,7 @@ insert into test values
|
|||||||
('2001-01-01 01:01:01', '-01:01:01', '-23:59:59', "1997-12-31 23:59:59.000001"),
|
('2001-01-01 01:01:01', '-01:01:01', '-23:59:59', "1997-12-31 23:59:59.000001"),
|
||||||
('1997-12-31 23:59:59.000001', '-23:59:59', '-01:01:01', '2001-01-01 01:01:01'),
|
('1997-12-31 23:59:59.000001', '-23:59:59', '-01:01:01', '2001-01-01 01:01:01'),
|
||||||
('2001-01-01 01:01:01', '01:01:01', '-1 01:01:01', null),
|
('2001-01-01 01:01:01', '01:01:01', '-1 01:01:01', null),
|
||||||
|
('2001-01-01 01:01:01', '-01:01:01', '1 01:01:01', '2001-01-01 01:01:01'),
|
||||||
('2001-01-01 01:01:01', null, '-1 01:01:01', null),
|
('2001-01-01 01:01:01', null, '-1 01:01:01', null),
|
||||||
(null, null, null, null),
|
(null, null, null, null),
|
||||||
('2001-01-01 01:01:01', '01:01:01', '1 01:01:01', '2001-01-01 01:01:01');
|
('2001-01-01 01:01:01', '01:01:01', '1 01:01:01', '2001-01-01 01:01:01');
|
||||||
|
@ -70,8 +70,8 @@ test_event_SOURCES = test_event.cpp
|
|||||||
ndbapi_slow_select_SOURCES = slow_select.cpp
|
ndbapi_slow_select_SOURCES = slow_select.cpp
|
||||||
testReadPerf_SOURCES = testReadPerf.cpp
|
testReadPerf_SOURCES = testReadPerf.cpp
|
||||||
testLcp_SOURCES = testLcp.cpp
|
testLcp_SOURCES = testLcp.cpp
|
||||||
DbCreate_SOURCES= bench/mainPopulate.cpp bench/dbPopulate.cpp bench/userInterface.cpp
|
DbCreate_SOURCES= bench/mainPopulate.cpp bench/dbPopulate.cpp bench/userInterface.cpp bench/dbPopulate.h bench/userInterface.h bench/testData.h bench/testDefinitions.h bench/ndb_schema.hpp bench/ndb_error.hpp
|
||||||
DbAsyncGenerator_SOURCES= bench/mainAsyncGenerator.cpp bench/asyncGenerator.cpp bench/ndb_async2.cpp
|
DbAsyncGenerator_SOURCES= bench/mainAsyncGenerator.cpp bench/asyncGenerator.cpp bench/ndb_async2.cpp bench/dbGenerator.h bench/macros.h bench/userInterface.h bench/testData.h bench/testDefinitions.h bench/ndb_schema.hpp bench/ndb_error.hpp
|
||||||
|
|
||||||
INCLUDES_LOC = -I$(top_srcdir)/ndb/include/kernel
|
INCLUDES_LOC = -I$(top_srcdir)/ndb/include/kernel
|
||||||
|
|
||||||
|
@ -5653,14 +5653,20 @@ innobase_get_at_most_n_mbchars(
|
|||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
This function returns true if SQL-query in the current thread
|
This function returns true if
|
||||||
|
|
||||||
|
1) SQL-query in the current thread
|
||||||
is either REPLACE or LOAD DATA INFILE REPLACE.
|
is either REPLACE or LOAD DATA INFILE REPLACE.
|
||||||
|
|
||||||
|
2) SQL-query in the current thread
|
||||||
|
is INSERT ON DUPLICATE KEY UPDATE.
|
||||||
|
|
||||||
NOTE that /mysql/innobase/row/row0ins.c must contain the
|
NOTE that /mysql/innobase/row/row0ins.c must contain the
|
||||||
prototype for this function ! */
|
prototype for this function ! */
|
||||||
|
|
||||||
ibool
|
ibool
|
||||||
innobase_query_is_replace(void)
|
innobase_query_is_update(void)
|
||||||
/*===========================*/
|
/*==========================*/
|
||||||
{
|
{
|
||||||
THD* thd;
|
THD* thd;
|
||||||
|
|
||||||
@ -5670,10 +5676,15 @@ innobase_query_is_replace(void)
|
|||||||
thd->lex->sql_command == SQLCOM_REPLACE_SELECT ||
|
thd->lex->sql_command == SQLCOM_REPLACE_SELECT ||
|
||||||
( thd->lex->sql_command == SQLCOM_LOAD &&
|
( thd->lex->sql_command == SQLCOM_LOAD &&
|
||||||
thd->lex->duplicates == DUP_REPLACE )) {
|
thd->lex->duplicates == DUP_REPLACE )) {
|
||||||
return true;
|
return(1);
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( thd->lex->sql_command == SQLCOM_INSERT &&
|
||||||
|
thd->lex->duplicates == DUP_UPDATE ) {
|
||||||
|
return(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -761,6 +761,81 @@ static bool get_interval_info(const char *str,uint length,CHARSET_INFO *cs,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Calculate difference between two datetime values as seconds + microseconds.
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
calc_time_diff()
|
||||||
|
l_time1 - TIME/DATE/DATETIME value
|
||||||
|
l_time2 - TIME/DATE/DATETIME value
|
||||||
|
l_sign - 1 absolute values are substracted,
|
||||||
|
-1 absolute values are added.
|
||||||
|
seconds_out - Out parameter where difference between
|
||||||
|
l_time1 and l_time2 in seconds is stored.
|
||||||
|
microseconds_out- Out parameter where microsecond part of difference
|
||||||
|
between l_time1 and l_time2 is stored.
|
||||||
|
|
||||||
|
NOTE
|
||||||
|
This function calculates difference between l_time1 and l_time2 absolute
|
||||||
|
values. So one should set l_sign and correct result if he want to take
|
||||||
|
signs into account (i.e. for TIME values).
|
||||||
|
|
||||||
|
RETURN VALUES
|
||||||
|
Returns sign of difference.
|
||||||
|
1 means negative result
|
||||||
|
0 means positive result
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
static bool calc_time_diff(TIME *l_time1, TIME *l_time2, int l_sign,
|
||||||
|
longlong *seconds_out, long *microseconds_out)
|
||||||
|
{
|
||||||
|
long days;
|
||||||
|
bool neg;
|
||||||
|
longlong microseconds;
|
||||||
|
|
||||||
|
/*
|
||||||
|
We suppose that if first argument is MYSQL_TIMESTAMP_TIME
|
||||||
|
the second argument should be TIMESTAMP_TIME also.
|
||||||
|
We should check it before calc_time_diff call.
|
||||||
|
*/
|
||||||
|
if (l_time1->time_type == MYSQL_TIMESTAMP_TIME) // Time value
|
||||||
|
days= l_time1->day - l_sign*l_time2->day;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
days= calc_daynr((uint) l_time1->year,
|
||||||
|
(uint) l_time1->month,
|
||||||
|
(uint) l_time1->day);
|
||||||
|
if (l_time2->time_type == MYSQL_TIMESTAMP_TIME)
|
||||||
|
days-= l_sign*l_time2->day;
|
||||||
|
else
|
||||||
|
days-= l_sign*calc_daynr((uint) l_time2->year,
|
||||||
|
(uint) l_time2->month,
|
||||||
|
(uint) l_time2->day);
|
||||||
|
}
|
||||||
|
|
||||||
|
microseconds= ((longlong)days*LL(86400) +
|
||||||
|
(longlong)(l_time1->hour*3600L +
|
||||||
|
l_time1->minute*60L +
|
||||||
|
l_time1->second) -
|
||||||
|
l_sign*(longlong)(l_time2->hour*3600L +
|
||||||
|
l_time2->minute*60L +
|
||||||
|
l_time2->second)) * LL(1000000) +
|
||||||
|
(longlong)l_time1->second_part -
|
||||||
|
l_sign*(longlong)l_time2->second_part;
|
||||||
|
|
||||||
|
neg= 0;
|
||||||
|
if (microseconds < 0)
|
||||||
|
{
|
||||||
|
microseconds= -microseconds;
|
||||||
|
neg= 1;
|
||||||
|
}
|
||||||
|
*seconds_out= microseconds/1000000L;
|
||||||
|
*microseconds_out= (long) (microseconds%1000000L);
|
||||||
|
return neg;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
longlong Item_func_period_add::val_int()
|
longlong Item_func_period_add::val_int()
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(fixed == 1);
|
DBUG_ASSERT(fixed == 1);
|
||||||
@ -2332,11 +2407,11 @@ String *Item_func_add_time::val_str(String *str)
|
|||||||
DBUG_ASSERT(fixed == 1);
|
DBUG_ASSERT(fixed == 1);
|
||||||
TIME l_time1, l_time2, l_time3;
|
TIME l_time1, l_time2, l_time3;
|
||||||
bool is_time= 0;
|
bool is_time= 0;
|
||||||
long microseconds, seconds, days= 0;
|
long days, microseconds;
|
||||||
|
longlong seconds;
|
||||||
int l_sign= sign;
|
int l_sign= sign;
|
||||||
|
|
||||||
null_value=0;
|
null_value=0;
|
||||||
l_time3.neg= 0;
|
|
||||||
if (is_date) // TIMESTAMP function
|
if (is_date) // TIMESTAMP function
|
||||||
{
|
{
|
||||||
if (get_arg0_date(&l_time1,1) ||
|
if (get_arg0_date(&l_time1,1) ||
|
||||||
@ -2352,51 +2427,26 @@ String *Item_func_add_time::val_str(String *str)
|
|||||||
l_time2.time_type == MYSQL_TIMESTAMP_DATETIME)
|
l_time2.time_type == MYSQL_TIMESTAMP_DATETIME)
|
||||||
goto null_date;
|
goto null_date;
|
||||||
is_time= (l_time1.time_type == MYSQL_TIMESTAMP_TIME);
|
is_time= (l_time1.time_type == MYSQL_TIMESTAMP_TIME);
|
||||||
if (is_time && (l_time2.neg == l_time1.neg && l_time1.neg))
|
|
||||||
l_time3.neg= 1;
|
|
||||||
}
|
}
|
||||||
if (l_time1.neg != l_time2.neg)
|
if (l_time1.neg != l_time2.neg)
|
||||||
l_sign= -l_sign;
|
l_sign= -l_sign;
|
||||||
|
|
||||||
microseconds= l_time1.second_part + l_sign*l_time2.second_part;
|
l_time3.neg= calc_time_diff(&l_time1, &l_time2, -l_sign,
|
||||||
seconds= (l_time1.hour*3600L + l_time1.minute*60L + l_time1.second +
|
&seconds, µseconds);
|
||||||
(l_time2.day*86400L + l_time2.hour*3600L +
|
|
||||||
l_time2.minute*60L + l_time2.second)*l_sign);
|
|
||||||
if (is_time)
|
|
||||||
seconds+= l_time1.day*86400L;
|
|
||||||
else
|
|
||||||
days+= calc_daynr((uint) l_time1.year,(uint) l_time1.month,
|
|
||||||
(uint) l_time1.day);
|
|
||||||
seconds= seconds + microseconds/1000000L;
|
|
||||||
microseconds= microseconds%1000000L;
|
|
||||||
days+= seconds/86400L;
|
|
||||||
seconds= seconds%86400L;
|
|
||||||
|
|
||||||
if (microseconds < 0)
|
/*
|
||||||
{
|
If first argument was negative and diff between arguments
|
||||||
microseconds+= 1000000L;
|
is non-zero we need to swap sign to get proper result.
|
||||||
seconds--;
|
*/
|
||||||
}
|
if (l_time1.neg && (seconds || microseconds))
|
||||||
if (seconds < 0)
|
l_time3.neg= 1-l_time3.neg; // Swap sign of result
|
||||||
{
|
|
||||||
days+= seconds/86400L - 1;
|
|
||||||
seconds+= 86400L;
|
|
||||||
}
|
|
||||||
if (days < 0)
|
|
||||||
{
|
|
||||||
if (!is_time)
|
|
||||||
goto null_date;
|
|
||||||
if (microseconds)
|
|
||||||
{
|
|
||||||
microseconds= 1000000L - microseconds;
|
|
||||||
seconds++;
|
|
||||||
}
|
|
||||||
seconds= 86400L - seconds;
|
|
||||||
days= -(++days);
|
|
||||||
l_time3.neg= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
calc_time_from_sec(&l_time3, seconds, microseconds);
|
if (!is_time && l_time3.neg)
|
||||||
|
goto null_date;
|
||||||
|
|
||||||
|
days= (long)(seconds/86400L);
|
||||||
|
|
||||||
|
calc_time_from_sec(&l_time3, (long)(seconds%86400L), microseconds);
|
||||||
if (!is_time)
|
if (!is_time)
|
||||||
{
|
{
|
||||||
get_date_from_daynr(days,&l_time3.year,&l_time3.month,&l_time3.day);
|
get_date_from_daynr(days,&l_time3.year,&l_time3.month,&l_time3.day);
|
||||||
@ -2452,8 +2502,8 @@ void Item_func_add_time::print(String *str)
|
|||||||
String *Item_func_timediff::val_str(String *str)
|
String *Item_func_timediff::val_str(String *str)
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(fixed == 1);
|
DBUG_ASSERT(fixed == 1);
|
||||||
longlong microseconds;
|
longlong seconds;
|
||||||
long days;
|
long microseconds;
|
||||||
int l_sign= 1;
|
int l_sign= 1;
|
||||||
TIME l_time1 ,l_time2, l_time3;
|
TIME l_time1 ,l_time2, l_time3;
|
||||||
|
|
||||||
@ -2466,33 +2516,18 @@ String *Item_func_timediff::val_str(String *str)
|
|||||||
if (l_time1.neg != l_time2.neg)
|
if (l_time1.neg != l_time2.neg)
|
||||||
l_sign= -l_sign;
|
l_sign= -l_sign;
|
||||||
|
|
||||||
if (l_time1.time_type == MYSQL_TIMESTAMP_TIME) // Time value
|
l_time3.neg= calc_time_diff(&l_time1, &l_time2, l_sign,
|
||||||
days= l_time1.day - l_sign*l_time2.day;
|
&seconds, µseconds);
|
||||||
else // DateTime value
|
|
||||||
days= (calc_daynr((uint) l_time1.year,
|
|
||||||
(uint) l_time1.month,
|
|
||||||
(uint) l_time1.day) -
|
|
||||||
l_sign*calc_daynr((uint) l_time2.year,
|
|
||||||
(uint) l_time2.month,
|
|
||||||
(uint) l_time2.day));
|
|
||||||
|
|
||||||
microseconds= ((longlong)days*86400L +
|
/*
|
||||||
l_time1.hour*3600L + l_time1.minute*60L + l_time1.second -
|
For MYSQL_TIMESTAMP_TIME only:
|
||||||
(longlong)l_sign*(l_time2.hour*3600L + l_time2.minute*60L +
|
If first argument was negative and diff between arguments
|
||||||
l_time2.second))*1000000 +
|
is non-zero we need to swap sign to get proper result.
|
||||||
l_time1.second_part - l_sign*l_time2.second_part;
|
*/
|
||||||
|
if (l_time1.neg && (seconds || microseconds))
|
||||||
|
l_time3.neg= 1-l_time3.neg; // Swap sign of result
|
||||||
|
|
||||||
l_time3.neg= 0;
|
calc_time_from_sec(&l_time3, (long) seconds, microseconds);
|
||||||
if (microseconds < 0)
|
|
||||||
{
|
|
||||||
microseconds= -microseconds;
|
|
||||||
l_time3.neg= 1;
|
|
||||||
}
|
|
||||||
if ((l_time2.neg == l_time1.neg) && l_time1.neg && microseconds)
|
|
||||||
l_time3.neg= l_time3.neg ? 0 : 1;
|
|
||||||
|
|
||||||
calc_time_from_sec(&l_time3, (long)(microseconds/1000000),
|
|
||||||
(long)(microseconds%1000000));
|
|
||||||
|
|
||||||
if (!make_datetime(l_time1.second_part || l_time2.second_part ?
|
if (!make_datetime(l_time1.second_part || l_time2.second_part ?
|
||||||
TIME_MICROSECOND : TIME_ONLY,
|
TIME_MICROSECOND : TIME_ONLY,
|
||||||
|
Reference in New Issue
Block a user