4486
4487
value->result_type() != STRING_RESULT &&
4487
4488
field->cmp_type() != value->result_type())
4489
/* For comparison purposes allow invalid dates like 2000-01-32 */
4490
orig_sql_mode= field->table->in_use->variables.sql_mode;
4491
if (value->real_item()->type() == Item::STRING_ITEM &&
4492
(field->type() == DRIZZLE_TYPE_DATE ||
4493
field->type() == DRIZZLE_TYPE_DATETIME))
4494
field->table->in_use->variables.sql_mode|= MODE_INVALID_DATES;
4495
err= value->save_in_field_no_warnings(field, 1);
4492
* Some notes from Jay...
4494
* OK, so previously, and in MySQL, what the optimizer does here is
4495
* override the sql_mode variable to ignore out-of-range or bad date-
4496
* time values. It does this because the optimizer is populating the
4497
* field variable with the incoming value from the comparison field,
4498
* and the value may exceed the bounds of a proper column type.
4500
* For instance, assume the following:
4502
* CREATE TABLE t1 (ts TIMESTAMP);
4503
* INSERT INTO t1 ('2009-03-04 00:00:00');
4504
* CREATE TABLE t2 (dt1 DATETIME, dt2 DATETIME);
4505
* INSERT INT t2 ('2003-12-31 00:00:00','2999-12-31 00:00:00');
4507
* If we issue this query:
4509
* SELECT * FROM t1, t2 WHERE t1.ts BETWEEN t2.dt1 AND t2.dt2;
4511
* We will come into bounds issues. Field_timestamp::store() will be
4512
* called with a datetime value of "2999-12-31 00:00:00" and will throw
4513
* an error for out-of-bounds. MySQL solves this via a hack with sql_mode
4514
* but Drizzle always throws errors on bad data storage in a Field class.
4516
* Therefore, to get around the problem of the Field class being used for
4517
* "storage" here without actually storing anything...we must check to see
4518
* if the value being stored in a Field_timestamp here is out of range. If
4519
* it is, then we must convert to the highest Timestamp value (or lowest,
4520
* depending on whether the datetime is before or after the epoch.
4522
if (field->type() == DRIZZLE_TYPE_TIMESTAMP)
4525
* The left-side of the range comparison is a timestamp field. Therefore,
4526
* we must check to see if the value in the right-hand side is outside the
4527
* range of the UNIX epoch, and cut to the epoch bounds if it is.
4529
/* Datetime and date columns are Item::FIELD_ITEM ... and have a result type of STRING_RESULT */
4530
if (value->real_item()->type() == Item::FIELD_ITEM
4531
&& value->result_type() == STRING_RESULT)
4533
char buff[MAX_DATETIME_FULL_WIDTH];
4534
String tmp(buff, sizeof(buff), &my_charset_bin);
4535
String *res= value->val_str(&tmp);
4542
* Create a datetime from the string and compare to fixed timestamp
4543
* instances representing the epoch boundaries.
4545
drizzled::DateTime value_datetime;
4547
if (! value_datetime.from_string(res->c_ptr(), (size_t) res->length()))
4550
drizzled::Timestamp max_timestamp;
4551
drizzled::Timestamp min_timestamp;
4553
(void) max_timestamp.from_time_t((time_t) INT32_MAX);
4554
(void) min_timestamp.from_time_t((time_t) 0);
4556
/* We rely on Temporal class operator overloads to do our comparisons. */
4557
if (value_datetime < min_timestamp)
4560
* Datetime in right-hand side column is before UNIX epoch, so adjust to
4563
char new_value_buff[MAX_DATETIME_FULL_WIDTH];
4564
size_t new_value_length;
4565
String new_value_string(new_value_buff, sizeof(new_value_buff), &my_charset_bin);
4567
min_timestamp.to_string(new_value_string.c_ptr(), &new_value_length);
4568
new_value_string.length(new_value_length);
4569
err= value->save_str_value_in_field(field, &new_value_string);
4571
else if (value_datetime > max_timestamp)
4574
* Datetime in right hand side column is after UNIX epoch, so adjust
4575
* to the higher bound of the epoch.
4577
char new_value_buff[MAX_DATETIME_FULL_WIDTH];
4578
size_t new_value_length;
4579
String new_value_string(new_value_buff, sizeof(new_value_buff), &my_charset_bin);
4581
max_timestamp.to_string(new_value_string.c_ptr(), &new_value_length);
4582
new_value_string.length(new_value_length);
4583
err= value->save_str_value_in_field(field, &new_value_string);
4586
err= value->save_in_field(field, 1);
4589
else /* Not a datetime -> timestamp comparison */
4590
err= value->save_in_field(field, 1);
4592
else /* Not a timestamp comparison */
4593
err= value->save_in_field(field, 1);
4498
4597
if (field->cmp_type() != value->result_type())