~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/field/datetime.cc

  • Committer: Stewart Smith
  • Date: 2010-08-12 16:48:46 UTC
  • mto: This revision was merged to the branch mainline in revision 1707.
  • Revision ID: stewart@flamingspork.com-20100812164846-s9bhy47g60bvqs41
bug lp:611379 Equivalent queries with Impossible where return different results

The following two equivalent queries return different results in maria 5.2 and 5.3 (and identical results in mysql 5.5.5) :

SELECT SUM( DISTINCT table1 .`pk` ) FROM B table1 STRAIGHT_JOIN ( BB table2 JOIN CC ON table2 .`col_varchar_key` ) ON table2 .`pk` ;

SELECT * FROM ( SELECT SUM( DISTINCT table1 .`pk` ) FROM B table1 STRAIGHT_JOIN ( BB table2 JOIN CC ON table2 .`col_varchar_key` ) ON table2 .`pk` );

MariaDB returns 0 on the second query and NULL on the first, whereas MySQL returns NULL on both. In MariaDB, both EXPLAIN plans agree that "Impossible WHERE noticed after reading const tables"



We have some slightly different output in drizzle:

main.bug_lp611379 [ fail ]
drizzletest: At line 9: query 'explain select * from (select sum(distinct t1.a) from t1,t2 where t1.a=t2.a)
as t' failed: 1048: Column 'sum(distinct t1.a)' cannot be null

but the fix gets us the correct query results, although with slightly different execution plans.



This fix is directly ported from MariaDB.

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19
19
 */
20
20
 
21
 
#include <config.h>
22
 
#include <boost/lexical_cast.hpp>
23
 
#include <drizzled/field/datetime.h>
24
 
#include <drizzled/error.h>
25
 
#include <drizzled/table.h>
26
 
#include <drizzled/temporal.h>
27
 
#include <drizzled/session.h>
 
21
#include "config.h"
 
22
#include "drizzled/field/datetime.h"
 
23
#include "drizzled/error.h"
 
24
#include "drizzled/table.h"
 
25
#include "drizzled/temporal.h"
 
26
#include "drizzled/session.h"
28
27
 
29
28
#include <math.h>
30
29
 
39
38
** datetime type
40
39
** In string context: YYYY-MM-DD HH:MM:DD
41
40
** In number context: YYYYMMDDHHMMDD
 
41
** Stored as a 8 byte unsigned int. Should sometimes be change to a 6 byte int.
42
42
****************************************************************************/
43
43
 
44
44
int Field_datetime::store(const char *from,
61
61
  temporal.to_int64_t(&int_value);
62
62
 
63
63
#ifdef WORDS_BIGENDIAN
64
 
  if (getTable() && getTable()->isDatabaseLowByteFirst())
 
64
  if (getTable() && getTable()->s->db_low_byte_first)
65
65
  {
66
66
    int8store(ptr, int_value);
67
67
  }
76
76
  ASSERT_COLUMN_MARKED_FOR_WRITE;
77
77
  if (from < 0.0 || from > 99991231235959.0)
78
78
  {
79
 
    /* Convert the double to a string using boost::lexical_cast */
80
 
    std::string tmp(boost::lexical_cast<std::string>(from));
 
79
    /* Convert the double to a string using stringstream */
 
80
    std::stringstream ss;
 
81
    std::string tmp;
 
82
    ss.precision(18); /* 18 places should be fine for error display of double input. */
 
83
    ss << from; ss >> tmp;
81
84
 
82
85
    my_error(ER_INVALID_DATETIME_VALUE, MYF(ME_FATALERROR), tmp.c_str());
83
86
    return 2;
95
98
  DateTime temporal;
96
99
  if (! temporal.from_int64_t(from))
97
100
  {
98
 
    /* Convert the integer to a string using boost::lexical_cast */
99
 
    std::string tmp(boost::lexical_cast<std::string>(from));
 
101
    /* Convert the integer to a string using stringstream */
 
102
    std::stringstream ss;
 
103
    std::string tmp;
 
104
    ss << from; ss >> tmp;
100
105
 
101
106
    my_error(ER_INVALID_DATETIME_VALUE, MYF(ME_FATALERROR), tmp.c_str());
102
107
    return 2;
111
116
  temporal.to_int64_t(&int_value);
112
117
 
113
118
#ifdef WORDS_BIGENDIAN
114
 
  if (getTable() && getTable()->isDatabaseLowByteFirst())
 
119
  if (getTable() && getTable()->s->db_low_byte_first)
115
120
  {
116
121
    int8store(ptr, int_value);
117
122
  }
121
126
  return 0;
122
127
}
123
128
 
124
 
int Field_datetime::store_time(type::Time &ltime, type::timestamp_t)
 
129
int Field_datetime::store_time(DRIZZLE_TIME *ltime, enum enum_drizzle_timestamp_type)
125
130
{
126
131
  DateTime temporal;
127
132
 
128
 
  temporal.set_years(ltime.year);
129
 
  temporal.set_months(ltime.month);
130
 
  temporal.set_days(ltime.day);
131
 
  temporal.set_hours(ltime.hour);
132
 
  temporal.set_minutes(ltime.minute);
133
 
  temporal.set_seconds(ltime.second);
 
133
  temporal.set_years(ltime->year);
 
134
  temporal.set_months(ltime->month);
 
135
  temporal.set_days(ltime->day);
 
136
  temporal.set_hours(ltime->hour);
 
137
  temporal.set_minutes(ltime->minute);
 
138
  temporal.set_seconds(ltime->second);
134
139
 
135
140
  if (! temporal.is_valid())
136
141
  {
137
 
    char tmp_string[type::Time::MAX_STRING_LENGTH];
 
142
    char tmp_string[MAX_DATE_STRING_REP_LENGTH];
138
143
    size_t tmp_string_len;
139
144
 
140
 
    tmp_string_len= temporal.to_string(tmp_string, type::Time::MAX_STRING_LENGTH);
141
 
    assert(tmp_string_len < type::Time::MAX_STRING_LENGTH);
 
145
    tmp_string_len= temporal.to_string(tmp_string, MAX_DATE_STRING_REP_LENGTH);
 
146
    assert(tmp_string_len < MAX_DATE_STRING_REP_LENGTH);
142
147
    my_error(ER_INVALID_DATETIME_VALUE, MYF(ME_FATALERROR), tmp_string);
143
148
    return 1;
144
149
  }
147
152
  temporal.to_int64_t(&int_value);
148
153
 
149
154
#ifdef WORDS_BIGENDIAN
150
 
  if (getTable() && getTable()->isDatabaseLowByteFirst())
 
155
  if (getTable() && getTable()->s->db_low_byte_first)
151
156
  {
152
157
    int8store(ptr, int_value);
153
158
  }
154
159
  else
155
160
#endif
156
161
    int64_tstore(ptr, int_value);
157
 
 
158
162
  return 0;
159
163
}
160
164
 
161
 
double Field_datetime::val_real(void) const
 
165
double Field_datetime::val_real(void)
162
166
{
163
167
  return (double) Field_datetime::val_int();
164
168
}
165
169
 
166
 
int64_t Field_datetime::val_int(void) const
 
170
int64_t Field_datetime::val_int(void)
167
171
{
168
172
  int64_t j;
169
173
 
170
174
  ASSERT_COLUMN_MARKED_FOR_READ;
171
175
 
172
176
#ifdef WORDS_BIGENDIAN
173
 
  if (getTable() && getTable()->isDatabaseLowByteFirst())
 
177
  if (getTable() && getTable()->s->db_low_byte_first)
174
178
    j=sint8korr(ptr);
175
179
  else
176
180
#endif
179
183
}
180
184
 
181
185
 
182
 
String *Field_datetime::val_str(String *val_buffer, String *) const
 
186
String *Field_datetime::val_str(String *val_buffer,
 
187
                                String *)
183
188
{
184
189
  val_buffer->alloc(DateTime::MAX_STRING_LENGTH);
185
190
  val_buffer->length(DateTime::MAX_STRING_LENGTH);
188
193
  ASSERT_COLUMN_MARKED_FOR_READ;
189
194
 
190
195
#ifdef WORDS_BIGENDIAN
191
 
  if (getTable() && getTable()->isDatabaseLowByteFirst())
 
196
  if (getTable() && getTable()->s->db_low_byte_first)
192
197
    tmp=sint8korr(ptr);
193
198
  else
194
199
#endif
202
207
   * not null without a default value.
203
208
   */
204
209
  dt.from_int64_t(tmp, false); /* NOTE: this does *NOT* attempt convertion
205
 
                                 from formats such as 20090101 as
206
 
                                 the stored value has already been
207
 
                                 converted.
208
 
                               */
 
210
                                        from formats such as 20090101 as
 
211
                                        the stored value has already been
 
212
                                        converted.
 
213
                               */
209
214
 
210
215
  int rlen;
211
216
  rlen= dt.to_string((char*)val_buffer->ptr(), DateTime::MAX_STRING_LENGTH);
216
221
  return val_buffer;
217
222
}
218
223
 
219
 
bool Field_datetime::get_date(type::Time &ltime, uint32_t fuzzydate) const
 
224
bool Field_datetime::get_date(DRIZZLE_TIME *ltime, uint32_t fuzzydate)
220
225
{
221
226
  int64_t tmp=Field_datetime::val_int();
222
227
  uint32_t part1,part2;
223
228
  part1=(uint32_t) (tmp/INT64_C(1000000));
224
229
  part2=(uint32_t) (tmp - (uint64_t) part1*INT64_C(1000000));
225
230
 
226
 
  ltime.time_type=      type::DRIZZLE_TIMESTAMP_DATETIME;
227
 
  ltime.neg=            0;
228
 
  ltime.second_part=    0;
229
 
  ltime.second= (int) (part2%100);
230
 
  ltime.minute= (int) (part2/100%100);
231
 
  ltime.hour=           (int) (part2/10000);
232
 
  ltime.day=            (int) (part1%100);
233
 
  ltime.month=  (int) (part1/100%100);
234
 
  ltime.year=           (int) (part1/10000);
235
 
 
236
 
  return (!(fuzzydate & TIME_FUZZY_DATE) && (!ltime.month || !ltime.day)) ? 1 : 0;
 
231
  ltime->time_type=     DRIZZLE_TIMESTAMP_DATETIME;
 
232
  ltime->neg=           0;
 
233
  ltime->second_part=   0;
 
234
  ltime->second=        (int) (part2%100);
 
235
  ltime->minute=        (int) (part2/100%100);
 
236
  ltime->hour=          (int) (part2/10000);
 
237
  ltime->day=           (int) (part1%100);
 
238
  ltime->month=         (int) (part1/100%100);
 
239
  ltime->year=          (int) (part1/10000);
 
240
  return (!(fuzzydate & TIME_FUZZY_DATE) && (!ltime->month || !ltime->day)) ? 1 : 0;
237
241
}
238
242
 
239
 
bool Field_datetime::get_time(type::Time &ltime) const
 
243
bool Field_datetime::get_time(DRIZZLE_TIME *ltime)
240
244
{
241
245
  return Field_datetime::get_date(ltime,0);
242
246
}
245
249
{
246
250
  int64_t a,b;
247
251
#ifdef WORDS_BIGENDIAN
248
 
  if (getTable() && getTable()->isDatabaseLowByteFirst())
 
252
  if (getTable() && getTable()->s->db_low_byte_first)
249
253
  {
250
254
    a=sint8korr(a_ptr);
251
255
    b=sint8korr(b_ptr);
263
267
void Field_datetime::sort_string(unsigned char *to,uint32_t )
264
268
{
265
269
#ifdef WORDS_BIGENDIAN
266
 
  if (not getTable() || not getTable()->isDatabaseLowByteFirst())
 
270
  if (!getTable() || !getTable()->s->db_low_byte_first)
267
271
  {
268
272
    to[0] = ptr[0];
269
273
    to[1] = ptr[1];