~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to unittests/date_test.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:
 
1
/* -*- mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*-
 
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
 
3
 *
 
4
 *  Copyright (C) 2010 Pawel Blokus
 
5
 *
 
6
 *  This program is free software; you can redistribute it and/or modify
 
7
 *  it under the terms of the GNU General Public License as published by
 
8
 *  the Free Software Foundation; either version 2 of the License, or
 
9
 *  (at your option) any later version.
 
10
 *
 
11
 *  This program is distributed in the hope that it will be useful,
 
12
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 *  GNU General Public License for more details.
 
15
 *
 
16
 *  You should have received a copy of the GNU General Public License
 
17
 *  along with this program; if not, write to the Free Software
 
18
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
19
 */
 
20
 
 
21
#include "config.h"
 
22
 
 
23
#include <gtest/gtest.h>
 
24
#include <drizzled/decimal.h>
 
25
#include <drizzled/temporal.h>
 
26
#include <drizzled/temporal_format.h>
 
27
 
 
28
#include "temporal_generator.h"
 
29
 
 
30
using namespace drizzled;
 
31
 
 
32
template <typename TemporalType>
 
33
class DateTestCompareOperators : public ::testing::Test
 
34
{
 
35
 protected:
 
36
  Date sample_date;
 
37
  bool result;
 
38
  
 
39
  TemporalType identical_with_sample_date, before_sample_date, after_sample_date;
 
40
  
 
41
  void initBeforeIdenticalAfter();
 
42
 
 
43
  virtual void SetUp()
 
44
  {
 
45
    TemporalGenerator::DateGen::make_date(&sample_date, 2010, 9, 8);
 
46
    initBeforeIdenticalAfter();
 
47
  }
 
48
};
 
49
 
 
50
template<> void DateTestCompareOperators<Date>::initBeforeIdenticalAfter()
 
51
{
 
52
  TemporalGenerator::DateGen::make_date(&before_sample_date, 1980, 1, 1);
 
53
  TemporalGenerator::DateGen::make_date(&identical_with_sample_date, 2010, 9, 8);
 
54
  TemporalGenerator::DateGen::make_date(&after_sample_date, 2019, 5, 30);
 
55
}
 
56
 
 
57
template<> void DateTestCompareOperators<DateTime>::initBeforeIdenticalAfter()
 
58
{
 
59
  TemporalGenerator::DateTimeGen::make_datetime(&before_sample_date, 1990, 12, 31, 12, 12, 30);
 
60
  TemporalGenerator::DateTimeGen::make_datetime(&identical_with_sample_date, 2010, 9, 8, 0, 0, 0);
 
61
  TemporalGenerator::DateTimeGen::make_datetime(&after_sample_date, 2020, 4, 4, 4, 4, 4);
 
62
}
 
63
 
 
64
template<> void DateTestCompareOperators<Timestamp>::initBeforeIdenticalAfter()
 
65
{
 
66
  TemporalGenerator::TimestampGen::make_timestamp(&before_sample_date, 1980, 1, 1, 13, 56, 41);
 
67
  TemporalGenerator::TimestampGen::make_timestamp(&identical_with_sample_date, 2010, 9, 8, 0, 0, 0);
 
68
  TemporalGenerator::TimestampGen::make_timestamp(&after_sample_date, 2019, 5, 30, 9, 10, 13);
 
69
}
 
70
 
 
71
typedef ::testing::Types<Date, DateTime, Timestamp> typesForDateTestCompareOperators;
 
72
TYPED_TEST_CASE(DateTestCompareOperators, typesForDateTestCompareOperators);
 
73
 
 
74
TYPED_TEST(DateTestCompareOperators, operatorEqual_ComparingWithIdencticalTemporal_ShouldReturn_True)
 
75
{
 
76
  this->result= (this->sample_date == this->identical_with_sample_date);
 
77
  
 
78
  ASSERT_TRUE(this->result);
 
79
}
 
80
 
 
81
TYPED_TEST(DateTestCompareOperators, operatorEqual_ComparingWithDifferentTemporal_ShouldReturn_False)
 
82
{
 
83
  this->result= (this->sample_date == this->before_sample_date);
 
84
  
 
85
  ASSERT_FALSE(this->result);
 
86
}
 
87
 
 
88
TYPED_TEST(DateTestCompareOperators, operatorNotEqual_ComparingWithIdencticalTemporal_ShouldReturn_False)
 
89
 
90
  this->result= (this->sample_date != this->identical_with_sample_date);
 
91
  
 
92
  ASSERT_FALSE(this->result);
 
93
}
 
94
 
 
95
TYPED_TEST(DateTestCompareOperators, operatorNotEqual_ComparingWithDifferentTemporal_ShouldReturn_True)
 
96
{
 
97
  this->result= (this->sample_date != this->before_sample_date);
 
98
  
 
99
  ASSERT_TRUE(this->result);
 
100
}
 
101
 
 
102
TYPED_TEST(DateTestCompareOperators, operatorGreaterThan_ComparingWithIdenticalTemporal_ShouldReturn_False)
 
103
{
 
104
  this->result= (this->sample_date > this->identical_with_sample_date);
 
105
  
 
106
  ASSERT_FALSE(this->result);
 
107
}
 
108
 
 
109
TYPED_TEST(DateTestCompareOperators, operatorGreaterThan_ComparingWithLaterTemporal_ShouldReturn_False)
 
110
{
 
111
  this->result= (this->sample_date > this->after_sample_date);
 
112
  
 
113
  ASSERT_FALSE(this->result);
 
114
}
 
115
 
 
116
TYPED_TEST(DateTestCompareOperators, operatorGreaterThan_ComparingWithEarlierTemporal_ShouldReturn_True)
 
117
{
 
118
  this->result= (this->sample_date > this->before_sample_date);
 
119
  
 
120
  ASSERT_TRUE(this->result);
 
121
}
 
122
 
 
123
TYPED_TEST(DateTestCompareOperators, operatorGreaterThanOrEqual_ComparingWithIdenticalTemporal_ShouldReturn_True)
 
124
{
 
125
  this->result= (this->sample_date >= this->identical_with_sample_date);
 
126
  
 
127
  ASSERT_TRUE(this->result);
 
128
}
 
129
 
 
130
TYPED_TEST(DateTestCompareOperators, operatorGreaterThanOrEqual_ComparingWithLaterTemporal_ShouldReturn_False)
 
131
{
 
132
  this->result= (this->sample_date >= this->after_sample_date);
 
133
  
 
134
  ASSERT_FALSE(this->result);
 
135
}
 
136
 
 
137
TYPED_TEST(DateTestCompareOperators, operatorGreaterThanOrEqual_ComparingWithEarlierTemporal_ShouldReturn_True)
 
138
{
 
139
  this->result= (this->sample_date >= this->before_sample_date);
 
140
  
 
141
  ASSERT_TRUE(this->result);
 
142
}
 
143
 
 
144
TYPED_TEST(DateTestCompareOperators, operatorLessThan_ComparingWithIdenticalTemporal_ShouldReturn_False)
 
145
{
 
146
  this->result= (this->sample_date < this->identical_with_sample_date);
 
147
  
 
148
  ASSERT_FALSE(this->result);
 
149
}
 
150
 
 
151
TYPED_TEST(DateTestCompareOperators, operatorLessThan_ComparingWithLaterTemporal_ShouldReturn_True)
 
152
{
 
153
  this->result= (this->sample_date < this->after_sample_date);
 
154
  
 
155
  ASSERT_TRUE(this->result);
 
156
}
 
157
 
 
158
TYPED_TEST(DateTestCompareOperators, operatorLessThan_ComparingWithEarlierTemporal_ShouldReturn_False)
 
159
{
 
160
  this->result= (this->sample_date < this->before_sample_date);
 
161
  
 
162
  ASSERT_FALSE(this->result);
 
163
}
 
164
 
 
165
TYPED_TEST(DateTestCompareOperators, operatorLessThanOrEqual_ComparingWithIdenticalTemporal_ShouldReturn_True)
 
166
{
 
167
  this->result= (this->sample_date <= this->identical_with_sample_date);
 
168
  
 
169
  ASSERT_TRUE(this->result);
 
170
}
 
171
 
 
172
TYPED_TEST(DateTestCompareOperators, operatorLessThanOrEqual_ComparingWithLaterTemporal_ShouldReturn_True)
 
173
{
 
174
  this->result= (this->sample_date <= this->after_sample_date);
 
175
  
 
176
  ASSERT_TRUE(this->result);
 
177
}
 
178
 
 
179
TYPED_TEST(DateTestCompareOperators, operatorLessThanOrEqual_ComparingWithEarlierTemporal_ShouldReturn_False)
 
180
{
 
181
  this->result= (this->sample_date <= this->before_sample_date);
 
182
  
 
183
  ASSERT_FALSE(this->result);
 
184
}
 
185
 
 
186
class DateTest : public ::testing::Test
 
187
{
 
188
  protected:
 
189
    Date date;
 
190
    bool result;
 
191
    
 
192
    virtual void SetUp()
 
193
    {
 
194
      TemporalGenerator::DateGen::make_valid_date(&date);
 
195
    }
 
196
};
 
197
 
 
198
TEST_F(DateTest, operatorAssign_shouldCopyDateRelatadComponents)
 
199
{
 
200
  Date copy= date;
 
201
 
 
202
  EXPECT_EQ(date.years(), copy.years());
 
203
  EXPECT_EQ(date.months(), copy.months());
 
204
  EXPECT_EQ(date.days(), copy.days());
 
205
}
 
206
 
 
207
TEST_F(DateTest, is_valid_onValidDate_shouldReturn_True)
 
208
{
 
209
  result= date.is_valid();
 
210
  ASSERT_TRUE(result);
 
211
}
 
212
 
 
213
TEST_F(DateTest, is_valid_onInvalidDateWithYearBelowMinimum_shouldReturn_False)
 
214
{
 
215
  date.set_years(DRIZZLE_MIN_YEARS_SQL - 1);
 
216
  
 
217
  result= date.is_valid();
 
218
  
 
219
  ASSERT_FALSE(result);
 
220
}
 
221
 
 
222
TEST_F(DateTest, is_valid_onInvalidDateWithYearAboveMaximum_shouldReturn_False)
 
223
{
 
224
  date.set_years(DRIZZLE_MAX_YEARS_SQL + 1);
 
225
    
 
226
  result= date.is_valid();
 
227
  
 
228
  ASSERT_FALSE(result);
 
229
}
 
230
 
 
231
TEST_F(DateTest, is_valid_onInvalidDateWithMonthSetToZero_shouldReturn_False)
 
232
{
 
233
  date.set_months(0);
 
234
  
 
235
  result= date.is_valid();
 
236
  
 
237
  ASSERT_FALSE(result);
 
238
}
 
239
 
 
240
 
 
241
TEST_F(DateTest, is_valid_onInvalidDateWithMonthAboveMaximum_shouldReturn_False)
 
242
{
 
243
  date.set_months(13);
 
244
  
 
245
  result= date.is_valid();
 
246
  
 
247
  ASSERT_FALSE(result);
 
248
}
 
249
 
 
250
TEST_F(DateTest, is_valid_onInvalidDateWithDaySetToZero_shouldReturn_False)
 
251
{
 
252
  date.set_days(0);
 
253
  
 
254
  result= date.is_valid();
 
255
  
 
256
  ASSERT_FALSE(result);
 
257
}
 
258
 
 
259
TEST_F(DateTest, is_valid_onInvalidDateWithDayAboveDaysInMonth_shouldReturn_False)
 
260
{
 
261
  date.set_days(32);
 
262
  
 
263
  result= date.is_valid();
 
264
  
 
265
  ASSERT_FALSE(result);
 
266
}
 
267
 
 
268
TEST_F(DateTest, is_valid_onInvalidDateWithLeapDayInNonLeapYear_shouldReturn_False)
 
269
{
 
270
  TemporalGenerator::TemporalGen::leap_day_in_non_leap_year(&date);
 
271
  
 
272
  result= date.is_valid();
 
273
  
 
274
  ASSERT_FALSE(result);
 
275
}
 
276
 
 
277
TEST_F(DateTest, is_valid_onValidDateWithLeapDayInLeapYear_shouldReturn_True)
 
278
{
 
279
  TemporalGenerator::TemporalGen::leap_day_in_leap_year(&date);
 
280
  
 
281
  result= date.is_valid();
 
282
  
 
283
  ASSERT_TRUE(result);
 
284
}
 
285
 
 
286
TEST_F(DateTest, to_string_shouldProduce_hyphenSeperatedDateElements)
 
287
{
 
288
  char expected[Date::MAX_STRING_LENGTH]= "2010-05-01";
 
289
  char returned[Date::MAX_STRING_LENGTH];
 
290
  TemporalGenerator::DateGen::make_date(&date, 2010, 5, 1);
 
291
  
 
292
  date.to_string(returned, Date::MAX_STRING_LENGTH);
 
293
  
 
294
  ASSERT_STREQ(expected, returned);  
 
295
}
 
296
 
 
297
TEST_F(DateTest, to_string_nullBuffer_shouldReturnProperLengthAnyway)
 
298
{
 
299
  int length= date.to_string(NULL, 0);
 
300
  
 
301
  ASSERT_EQ(Date::MAX_STRING_LENGTH - 1, length);  
 
302
}
 
303
 
 
304
TEST_F(DateTest, from_string_validString_shouldPopulateCorrectly)
 
305
{
 
306
  char valid_string[Date::MAX_STRING_LENGTH]= "2010-05-01";
 
307
  uint32_t years, months, days;
 
308
 
 
309
  init_temporal_formats();
 
310
  
 
311
  result= date.from_string(valid_string, Date::MAX_STRING_LENGTH - 1);
 
312
  ASSERT_TRUE(result);
 
313
  
 
314
  years= date.years();
 
315
  months= date.months();
 
316
  days= date.days();
 
317
 
 
318
  deinit_temporal_formats();
 
319
  
 
320
  EXPECT_EQ(2010, years);
 
321
  EXPECT_EQ(5, months);
 
322
  EXPECT_EQ(1, days);
 
323
}
 
324
 
 
325
TEST_F(DateTest, from_string_invalidString_shouldReturn_False)
 
326
{
 
327
  char valid_string[Date::MAX_STRING_LENGTH]= "2x10-05-01";
 
328
 
 
329
  init_temporal_formats();
 
330
  result= date.from_string(valid_string, Date::MAX_STRING_LENGTH - 1);
 
331
  deinit_temporal_formats();
 
332
  
 
333
  ASSERT_FALSE(result);
 
334
}
 
335
 
 
336
TEST_F(DateTest, to_int64_t)
 
337
{
 
338
  TemporalGenerator::DateGen::make_date(&date, 2030, 8, 17);
 
339
  int64_t representation;
 
340
  
 
341
  date.to_int64_t(&representation);
 
342
  
 
343
  ASSERT_EQ(20300817, representation);
 
344
}
 
345
 
 
346
TEST_F(DateTest, to_int32_t)
 
347
{
 
348
  TemporalGenerator::DateGen::make_date(&date, 2030, 8, 17);
 
349
  int32_t representation;
 
350
 
 
351
  date.to_int32_t(&representation);
 
352
 
 
353
  ASSERT_EQ(20300817, representation);
 
354
}
 
355
 
 
356
TEST_F(DateTest, from_int32_t_shouldPopulateDateCorrectly)
 
357
{
 
358
  uint32_t decoded_years, decoded_months, decoded_days;
 
359
 
 
360
  date.from_int32_t(20300817);
 
361
  
 
362
  decoded_years= date.years();
 
363
  decoded_months= date.months();
 
364
  decoded_days= date.days();
 
365
  
 
366
  EXPECT_EQ(2030, decoded_years);
 
367
  EXPECT_EQ(8, decoded_months);
 
368
  EXPECT_EQ(17, decoded_days);
 
369
}
 
370
 
 
371
TEST_F(DateTest, to_julian_day_number)
 
372
{
 
373
  int64_t julian_day;
 
374
  TemporalGenerator::DateGen::make_date(&date, 1999, 12, 31);
 
375
  
 
376
  date.to_julian_day_number(&julian_day);
 
377
  
 
378
  ASSERT_EQ(2451544, julian_day);
 
379
}
 
380
 
 
381
TEST_F(DateTest, from_julian_day_number)
 
382
{
 
383
  int64_t julian_day= 2451544;
 
384
  uint32_t years, months, days;
 
385
   
 
386
  date.from_julian_day_number(julian_day);
 
387
  
 
388
  years= date.years();
 
389
  months= date.months();
 
390
  days= date.days();
 
391
    
 
392
  EXPECT_EQ(1999, years);
 
393
  EXPECT_EQ(12, months);
 
394
  EXPECT_EQ(31, days);
 
395
}
 
396
 
 
397
TEST_F(DateTest, DISABLED_to_tm)
 
398
{
 
399
  uint32_t years= 2030, months= 8, days= 17;
 
400
  TemporalGenerator::DateGen::make_date(&date, years, months, days);
 
401
  struct tm filled;
 
402
  
 
403
  date.to_tm(&filled);
 
404
  
 
405
  EXPECT_EQ(130, filled.tm_year);
 
406
  EXPECT_EQ(7, filled.tm_mon);
 
407
  EXPECT_EQ(17, filled.tm_mday);
 
408
  EXPECT_EQ(0, filled.tm_hour);
 
409
  EXPECT_EQ(0, filled.tm_min);
 
410
  EXPECT_EQ(0, filled.tm_sec);
 
411
 
 
412
  /* TODO:these fail, shouldn't they also be set properly? */
 
413
  EXPECT_EQ(228, filled.tm_yday);
 
414
  EXPECT_EQ(6, filled.tm_wday);
 
415
  EXPECT_EQ(-1, filled.tm_isdst);
 
416
}
 
417
 
 
418
TEST_F(DateTest, from_tm)
 
419
{
 
420
  uint32_t years, months, days;
 
421
  struct tm from;
 
422
  from.tm_year= 1956 - 1900;
 
423
  from.tm_mon= 2;
 
424
  from.tm_mday= 30;
 
425
  
 
426
  date.from_tm(&from);
 
427
  
 
428
  years= date.years();
 
429
  months= date.months();
 
430
  days= date.days();
 
431
  
 
432
  EXPECT_EQ(1956, years);  
 
433
  EXPECT_EQ(3, months);
 
434
  EXPECT_EQ(30, days);
 
435
}
 
436
 
 
437
TEST_F(DateTest, to_time_t)
 
438
{
 
439
  time_t time;
 
440
  TemporalGenerator::DateGen::make_date(&date, 1990, 9, 9);
 
441
  
 
442
  date.to_time_t(&time);
 
443
  
 
444
  ASSERT_EQ(652838400, time);
 
445
}
 
446
 
 
447
TEST_F(DateTest, from_time_t)
 
448
{
 
449
  uint32_t years, months, days;
 
450
  
 
451
  date.from_time_t(652838400);
 
452
  
 
453
  years= date.years();
 
454
  months= date.months();
 
455
  days= date.days();
 
456
  
 
457
  EXPECT_EQ(1990, years);  
 
458
  EXPECT_EQ(9, months);
 
459
  EXPECT_EQ(9, days);
 
460
}
 
461
 
 
462
TEST_F(DateTest, to_decimal)
 
463
{
 
464
  drizzled::my_decimal to;
 
465
  TemporalGenerator::DateGen::make_date(&date, 1987, 5, 6);
 
466
 
 
467
  date.to_decimal(&to);
 
468
 
 
469
  ASSERT_EQ(19870506, to.buf[0]);
 
470
}
 
471
 
 
472
class DateFromStringTest: public ::testing::TestWithParam<const char*>
 
473
{
 
474
  protected:
 
475
    Date date;
 
476
    bool result;
 
477
    uint32_t years, months, days;
 
478
    
 
479
    virtual void SetUp()
 
480
    {
 
481
      init_temporal_formats();
 
482
    }
 
483
    
 
484
    virtual void TearDown()
 
485
    {
 
486
      deinit_temporal_formats();
 
487
    }
 
488
    
 
489
    void assign_date_values()
 
490
    {
 
491
      years= date.years();
 
492
      months= date.months();
 
493
      days= date.days();
 
494
    }
 
495
};
 
496
 
 
497
TEST_P(DateFromStringTest, from_string)
 
498
{
 
499
  const char *valid_string= GetParam();
 
500
  
 
501
  result= date.from_string(valid_string, strlen(valid_string));
 
502
  ASSERT_TRUE(result);
 
503
  
 
504
  assign_date_values();
 
505
  
 
506
  EXPECT_EQ(2010, years);
 
507
  EXPECT_EQ(6, months);
 
508
  EXPECT_EQ(7, days);
 
509
}
 
510
 
 
511
/* TODO:for some reason this was not declared by the macro, needs clarification*/
 
512
testing::internal::ParamGenerator<const char*> gtest_ValidStringDateFromStringTest_EvalGenerator_();
 
513
 
 
514
INSTANTIATE_TEST_CASE_P(ValidString, DateFromStringTest,
 
515
                        ::testing::Values("20100607", /* YYYYMMDD */
 
516
                                          "06/07/2010",/* MM[-/.]DD[-/.]YYYY (US common format)*/
 
517
                                          "10.06.07",/* YY[-/.]MM[-/.]DD */
 
518
                                          "10/6/7",/* YY[-/.][M]M[-/.][D]D */
 
519
                                          "2010-6-7"/* YYYY[-/.][M]M[-/.][D]D */));
 
520
                                          
 
521
 
 
522
                                          
 
 
b'\\ No newline at end of file'