From: Adriano d. S. F. <asf...@us...> - 2007-07-31 01:23:18
|
Build Version : T2.1.0.16198 Firebird 2.1 Beta 1 (writeBuildNum.sh,v 1.16355 2007/07/31 01:23:00 asfernandes ) Update of /cvsroot/firebird/firebird2/src/jrd In directory sc8-pr-cvs17:/tmp/cvs-serv31555/src/jrd Modified Files: SysFunction.cpp blr.h cmp.cpp evl.cpp Log Message: Improvements: 1) CORE-1387 - Add MILLISECONDS handling to EXTRACT, DATEADD and DATEDIFF functions 2) CORE-663 - EXTRACT(WEEK FROM DATE) Index: SysFunction.cpp =================================================================== RCS file: /cvsroot/firebird/firebird2/src/jrd/SysFunction.cpp,v retrieving revision 1.12 retrieving revision 1.13 diff -b -U3 -r1.12 -r1.13 --- SysFunction.cpp 3 Jul 2007 00:09:34 -0000 1.12 +++ SysFunction.cpp 31 Jul 2007 01:22:58 -0000 1.13 @@ -1120,7 +1120,8 @@ if (part != blr_extract_hour && part != blr_extract_minute && - part != blr_extract_second) + part != blr_extract_second && + part != blr_extract_millisecond) { status_exception::raise(isc_expression_eval_err, 0); } @@ -1131,7 +1132,8 @@ if (part == blr_extract_hour || part == blr_extract_minute || - part == blr_extract_second) + part == blr_extract_second || + part == blr_extract_millisecond) { status_exception::raise(isc_expression_eval_err, 0); } @@ -1225,6 +1227,10 @@ add10msec(×tamp.value(), quantity, ISC_TIME_SECONDS_PRECISION); break; + case blr_extract_millisecond: + add10msec(×tamp.value(), quantity, ISC_TIME_SECONDS_PRECISION / 1000); + break; + default: status_exception::raise(isc_expression_eval_err, 0); break; @@ -1335,6 +1341,7 @@ case blr_extract_hour: case blr_extract_minute: case blr_extract_second: + case blr_extract_millisecond: if (value1Dsc->dsc_dtype == dtype_sql_date || value2Dsc->dsc_dtype == dtype_sql_date) status_exception::raise(isc_expression_eval_err, 0); @@ -1387,6 +1394,13 @@ ISC_TIME_SECONDS_PRECISION; break; + case blr_extract_millisecond: + result = oneDay * (timestamp2.value().timestamp_date - timestamp1.value().timestamp_date) * 1000; + result += ((SINT64) timestamp2.value().timestamp_time - + (SINT64) timestamp1.value().timestamp_time) / + (ISC_TIME_SECONDS_PRECISION / 1000); + break; + default: status_exception::raise(isc_expression_eval_err, 0); break; Index: blr.h =================================================================== RCS file: /cvsroot/firebird/firebird2/src/jrd/blr.h,v retrieving revision 1.32 retrieving revision 1.33 diff -b -U3 -r1.32 -r1.33 --- blr.h 13 Apr 2007 01:37:39 -0000 1.32 +++ blr.h 31 Jul 2007 01:22:58 -0000 1.33 @@ -276,6 +276,8 @@ #define blr_extract_second (unsigned char)5 #define blr_extract_weekday (unsigned char)6 #define blr_extract_yearday (unsigned char)7 +#define blr_extract_millisecond (unsigned char)8 +#define blr_extract_week (unsigned char)9 #define blr_current_date (unsigned char)160 #define blr_current_timestamp (unsigned char)161 Index: cmp.cpp =================================================================== RCS file: /cvsroot/firebird/firebird2/src/jrd/cmp.cpp,v retrieving revision 1.261 retrieving revision 1.262 diff -b -U3 -r1.261 -r1.262 --- cmp.cpp 21 Jul 2007 21:28:55 -0000 1.261 +++ cmp.cpp 31 Jul 2007 01:22:58 -0000 1.262 @@ -1645,21 +1645,22 @@ return; case nod_extract: - if ((IPTR) node->nod_arg[e_extract_part] == blr_extract_second) { + switch ((IPTR) node->nod_arg[e_extract_part]) + { + case blr_extract_second: // QUADDATE - SECOND returns a float, or scaled! - desc->dsc_dtype = dtype_long; - desc->dsc_length = sizeof(ULONG); - desc->dsc_scale = ISC_TIME_SECONDS_PRECISION_SCALE; - desc->dsc_sub_type = 0; - desc->dsc_flags = 0; - } - else { - desc->dsc_dtype = dtype_short; - desc->dsc_length = sizeof(SSHORT); - desc->dsc_scale = 0; - desc->dsc_sub_type = 0; - desc->dsc_flags = 0; + desc->makeLong(ISC_TIME_SECONDS_PRECISION_SCALE); + break; + + case blr_extract_millisecond: + desc->makeLong(0); + break; + + default: + desc->makeShort(0); + break; } + return; case nod_strlen: Index: evl.cpp =================================================================== RCS file: /cvsroot/firebird/firebird2/src/jrd/evl.cpp,v retrieving revision 1.231 retrieving revision 1.232 diff -b -U3 -r1.231 -r1.232 --- evl.cpp 5 Jul 2007 15:39:01 -0000 1.231 +++ evl.cpp 31 Jul 2007 01:22:59 -0000 1.232 @@ -3502,7 +3502,8 @@ timestamp.decode(×); if (extract_part != blr_extract_hour && extract_part != blr_extract_minute && - extract_part != blr_extract_second) + extract_part != blr_extract_second && + extract_part != blr_extract_millisecond) { ERR_post(isc_expression_eval_err, 0); } @@ -3512,7 +3513,8 @@ timestamp.decode(×); if (extract_part == blr_extract_hour || extract_part == blr_extract_minute || - extract_part == blr_extract_second) + extract_part == blr_extract_second || + extract_part == blr_extract_millisecond) { ERR_post(isc_expression_eval_err, 0); } @@ -3544,15 +3546,77 @@ part = times.tm_min; break; case blr_extract_second: - impure->vlu_desc.dsc_dtype = dtype_long; impure->vlu_desc.dsc_scale = ISC_TIME_SECONDS_PRECISION_SCALE; + // fall through + case blr_extract_millisecond: + impure->vlu_desc.dsc_dtype = dtype_long; impure->vlu_desc.dsc_address = reinterpret_cast<UCHAR*>(&impure->vlu_misc.vlu_long); impure->vlu_desc.dsc_length = sizeof(ULONG); *(ULONG *) impure->vlu_desc.dsc_address = times.tm_sec * ISC_TIME_SECONDS_PRECISION + (timestamp.value().timestamp_time % ISC_TIME_SECONDS_PRECISION); + + if (extract_part == blr_extract_millisecond) + (*(ULONG *) impure->vlu_desc.dsc_address) /= ISC_TIME_SECONDS_PRECISION / 1000; + return &impure->vlu_desc; + + case blr_extract_week: + { + // Algorithm for Converting Gregorian Dates to ISO 8601 Week Date by Rick McCarty, 1999 + // http://personal.ecu.edu/mccartyr/ISOwdALG.txt + + int y = times.tm_year + 1900; + int dayOfYearNumber = times.tm_yday + 1; + + // Find the jan1Weekday for y (Monday=1, Sunday=7) + int yy = (y - 1) % 100; + int c = (y - 1) - yy; + int g = yy + yy / 4; + int jan1Weekday = 1 + (((((c / 100) % 4) * 5) + g) % 7); + + // Find the weekday for y m d + int h = dayOfYearNumber + (jan1Weekday - 1); + int weekday = 1 + ((h - 1) % 7); + + // Find if y m d falls in yearNumber y-1, weekNumber 52 or 53 + int yearNumber, weekNumber; + + if ((dayOfYearNumber <= (8 - jan1Weekday)) && (jan1Weekday > 4)) + { + yearNumber = y - 1; + weekNumber = ((jan1Weekday == 5) || ((jan1Weekday == 6) && + Firebird::TimeStamp::isLeapYear(yearNumber))) ? 53 : 52; + } + else + yearNumber = y; + + // Find if y m d falls in yearNumber y+1, weekNumber 1 + if (yearNumber == y) + { + int i = Firebird::TimeStamp::isLeapYear(y) ? 366 : 365; + + if ((i - dayOfYearNumber) < (4 - weekday)) + { + yearNumber = y + 1; + weekNumber = 1; + } + } + + // Find if y m d falls in yearNumber y, weekNumber 1 through 53 + if (yearNumber == y) + { + int j = dayOfYearNumber + (7 - weekday) + (jan1Weekday - 1); + weekNumber = j / 7; + if (jan1Weekday > 4) + weekNumber--; + } + + part = weekNumber; + break; + } + case blr_extract_yearday: part = times.tm_yday; break; |