~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/field/blob.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:
43
43
/****************************************************************************
44
44
** blob type
45
45
** A blob is saved as a length and a pointer. The length is stored in the
46
 
** packlength slot and is sizeof(uint32_t) (4 bytes)
 
46
** packlength slot and may be from 1-4.
47
47
****************************************************************************/
48
48
 
49
49
Field_blob::Field_blob(unsigned char *ptr_arg,
51
51
                       unsigned char null_bit_arg,
52
52
                                   const char *field_name_arg,
53
53
                       TableShare *share,
 
54
                       uint32_t blob_pack_length,
54
55
                       const CHARSET_INFO * const cs)
55
56
  :Field_str(ptr_arg,
56
 
             blob_pack_length_to_max_length(sizeof(uint32_t)),
 
57
             blob_pack_length_to_max_length(blob_pack_length),
57
58
             null_ptr_arg,
58
59
             null_bit_arg,
59
60
             field_name_arg,
60
 
             cs)
 
61
             cs),
 
62
   packlength(blob_pack_length)
61
63
{
62
64
  flags|= BLOB_FLAG;
63
65
  share->blob_fields++;
65
67
}
66
68
 
67
69
void Field_blob::store_length(unsigned char *i_ptr,
 
70
                              uint32_t i_packlength,
68
71
                              uint32_t i_number,
69
72
                              bool low_byte_first)
70
73
{
71
74
#ifndef WORDS_BIGENDIAN
72
75
  (void)low_byte_first;
73
76
#endif
74
 
 
75
 
#ifdef WORDS_BIGENDIAN
76
 
  if (low_byte_first)
77
 
  {
78
 
    int4store(i_ptr,i_number);
 
77
  switch (i_packlength) {
 
78
  case 1:
 
79
    i_ptr[0]= (unsigned char) i_number;
 
80
    break;
 
81
  case 2:
 
82
#ifdef WORDS_BIGENDIAN
 
83
    if (low_byte_first)
 
84
    {
 
85
      int2store(i_ptr,(unsigned short) i_number);
 
86
    }
 
87
    else
 
88
#endif
 
89
      shortstore(i_ptr,(unsigned short) i_number);
 
90
    break;
 
91
  case 3:
 
92
    int3store(i_ptr,i_number);
 
93
    break;
 
94
  case 4:
 
95
#ifdef WORDS_BIGENDIAN
 
96
    if (low_byte_first)
 
97
    {
 
98
      int4store(i_ptr,i_number);
 
99
    }
 
100
    else
 
101
#endif
 
102
      longstore(i_ptr,i_number);
79
103
  }
80
 
  else
81
 
#endif
82
 
    longstore(i_ptr,i_number);
83
104
}
84
105
 
85
106
 
86
 
void Field_blob::store_length(unsigned char *i_ptr, uint32_t i_number)
 
107
void Field_blob::store_length(unsigned char *i_ptr, uint32_t i_packlength,
 
108
                  uint32_t i_number)
87
109
{
88
 
  store_length(i_ptr, i_number, getTable()->getShare()->db_low_byte_first);
 
110
  store_length(i_ptr, i_packlength, i_number, getTable()->getShare()->db_low_byte_first);
89
111
}
90
112
 
91
113
 
92
114
uint32_t Field_blob::get_length(const unsigned char *pos,
 
115
                                uint32_t packlength_arg,
93
116
                                bool low_byte_first)
94
117
{
95
118
#ifndef WORDS_BIGENDIAN
96
119
  (void)low_byte_first;
97
120
#endif
98
 
  uint32_t tmp;
99
 
#ifdef WORDS_BIGENDIAN
100
 
  if (low_byte_first)
101
 
    tmp=uint4korr(pos);
102
 
  else
103
 
#endif
104
 
    longget(tmp,pos);
105
 
  return (uint32_t) tmp;
 
121
  switch (packlength_arg) {
 
122
  case 1:
 
123
    return (uint32_t) pos[0];
 
124
  case 2:
 
125
    {
 
126
      uint16_t tmp;
 
127
#ifdef WORDS_BIGENDIAN
 
128
      if (low_byte_first)
 
129
        tmp=sint2korr(pos);
 
130
      else
 
131
#endif
 
132
        shortget(tmp,pos);
 
133
      return (uint32_t) tmp;
 
134
    }
 
135
  case 3:
 
136
    return (uint32_t) uint3korr(pos);
 
137
  case 4:
 
138
    {
 
139
      uint32_t tmp;
 
140
#ifdef WORDS_BIGENDIAN
 
141
      if (low_byte_first)
 
142
        tmp=uint4korr(pos);
 
143
      else
 
144
#endif
 
145
        longget(tmp,pos);
 
146
      return (uint32_t) tmp;
 
147
    }
 
148
  }
 
149
  return 0;                                     // Impossible
106
150
}
107
151
 
108
152
 
109
153
uint32_t Field_blob::get_packed_size(const unsigned char *ptr_arg,
110
154
                                bool low_byte_first)
111
155
{
112
 
  return sizeof(uint32_t) + get_length(ptr_arg, low_byte_first);
 
156
  return packlength + get_length(ptr_arg, packlength, low_byte_first);
113
157
}
114
158
 
115
159
 
116
160
uint32_t Field_blob::get_length(uint32_t row_offset)
117
161
{
118
 
  return get_length(ptr+row_offset,
 
162
  return get_length(ptr+row_offset, this->packlength,
119
163
                    getTable()->getShare()->db_low_byte_first);
120
164
}
121
165
 
122
166
 
123
167
uint32_t Field_blob::get_length(const unsigned char *ptr_arg)
124
168
{
125
 
  return get_length(ptr_arg, getTable()->getShare()->db_low_byte_first);
 
169
  return get_length(ptr_arg, this->packlength, getTable()->getShare()->db_low_byte_first);
126
170
}
127
171
 
128
172
 
129
173
/**
130
174
  Put a blob length field into a record buffer.
131
175
 
132
 
  Blob length is always stored in sizeof(uint32_t) (4 bytes)
 
176
  Depending on the maximum length of a blob, its length field is
 
177
  put into 1 to 4 bytes. This is a property of the blob object,
 
178
  described by 'packlength'.
133
179
 
134
180
  @param pos                 Pointer into the record buffer.
135
181
  @param length              The length value to put.
137
183
 
138
184
void Field_blob::put_length(unsigned char *pos, uint32_t length)
139
185
{
 
186
  switch (packlength) {
 
187
  case 1:
 
188
    *pos= (char) length;
 
189
    break;
 
190
  case 2:
 
191
    int2store(pos, length);
 
192
    break;
 
193
  case 3:
 
194
    int3store(pos, length);
 
195
    break;
 
196
  case 4:
140
197
    int4store(pos, length);
 
198
    break;
 
199
  }
141
200
}
142
201
 
143
202
 
160
219
 
161
220
  if (from == value.ptr())
162
221
  {
163
 
    size_t dummy_offset;
 
222
    uint32_t dummy_offset;
164
223
    if (!String::needs_conversion(length, cs, field_charset, &dummy_offset))
165
224
    {
166
225
      Field_blob::store_length(length);
167
 
      memmove(ptr+sizeof(uint32_t), &from, sizeof(char*));
 
226
      memmove(ptr+packlength, &from, sizeof(char*));
168
227
      return 0;
169
228
    }
170
229
    if (tmpstr.copy(from, length, cs))
191
250
 
192
251
  Field_blob::store_length(copy_length);
193
252
  tmp= value.ptr();
194
 
  memmove(ptr+sizeof(uint32_t), &tmp, sizeof(char*));
 
253
  memmove(ptr+packlength, &tmp, sizeof(char*));
195
254
 
196
255
  if (check_string_copy_error(this, well_formed_error_pos,
197
256
                              cannot_convert_error_pos, from + length, cs))
233
292
 
234
293
  ASSERT_COLUMN_MARKED_FOR_READ;
235
294
 
236
 
  memcpy(&blob,ptr+sizeof(uint32_t),sizeof(char*));
 
295
  memcpy(&blob,ptr+packlength,sizeof(char*));
237
296
  if (!blob)
238
297
    return 0.0;
239
298
  length= get_length(ptr);
249
308
 
250
309
  ASSERT_COLUMN_MARKED_FOR_READ;
251
310
 
252
 
  memcpy(&blob,ptr+sizeof(uint32_t),sizeof(char*));
 
311
  memcpy(&blob,ptr+packlength,sizeof(char*));
253
312
  if (!blob)
254
313
    return 0;
255
314
  uint32_t length=get_length(ptr);
263
322
 
264
323
  ASSERT_COLUMN_MARKED_FOR_READ;
265
324
 
266
 
  memcpy(&blob,ptr+sizeof(uint32_t),sizeof(char*));
 
325
  memcpy(&blob,ptr+packlength,sizeof(char*));
267
326
  if (!blob)
268
327
    val_ptr->set("",0,charset());       // A bit safer than ->length(0)
269
328
  else
279
338
 
280
339
  ASSERT_COLUMN_MARKED_FOR_READ;
281
340
 
282
 
  memcpy(&blob, ptr+sizeof(uint32_t), sizeof(const unsigned char*));
 
341
  memcpy(&blob, ptr+packlength, sizeof(const unsigned char*));
283
342
  if (!blob)
284
343
  {
285
344
    blob= "";
307
366
                        uint32_t max_length)
308
367
{
309
368
  unsigned char *blob1,*blob2;
310
 
  memcpy(&blob1,a_ptr+sizeof(uint32_t),sizeof(char*));
311
 
  memcpy(&blob2,b_ptr+sizeof(uint32_t),sizeof(char*));
 
369
  memcpy(&blob1,a_ptr+packlength,sizeof(char*));
 
370
  memcpy(&blob2,b_ptr+packlength,sizeof(char*));
312
371
  uint32_t a_len= get_length(a_ptr), b_len= get_length(b_ptr);
313
372
  set_if_smaller(a_len, max_length);
314
373
  set_if_smaller(b_len, max_length);
322
381
  char *a,*b;
323
382
  uint32_t diff;
324
383
  uint32_t a_length,b_length;
325
 
  memcpy(&a,a_ptr+sizeof(uint32_t),sizeof(char*));
326
 
  memcpy(&b,b_ptr+sizeof(uint32_t),sizeof(char*));
 
384
  memcpy(&a,a_ptr+packlength,sizeof(char*));
 
385
  memcpy(&b,b_ptr+packlength,sizeof(char*));
327
386
 
328
387
  a_length= get_length(a_ptr);
329
388
 
337
396
 
338
397
  diff= memcmp(a,b,min(a_length,b_length));
339
398
 
340
 
  return diff ? diff : (unsigned int) (a_length - b_length);
 
399
  return diff ? diff : (int) (a_length - b_length);
341
400
}
342
401
 
343
402
/* The following is used only when comparing a key */
405
464
{
406
465
  unsigned char *blob1;
407
466
  uint32_t blob_length=get_length(ptr);
408
 
  memcpy(&blob1,ptr+sizeof(uint32_t),sizeof(char*));
 
467
  memcpy(&blob1,ptr+packlength,sizeof(char*));
409
468
  const CHARSET_INFO * const cs= charset();
410
469
  uint32_t local_char_length= max_key_length / cs->mbmaxlen;
411
470
  local_char_length= my_charpos(cs, blob1, blob1+blob_length,
425
484
uint32_t Field_blob::sort_length() const
426
485
{
427
486
  return (uint32_t) (current_session->variables.max_sort_length +
428
 
                     (field_charset == &my_charset_bin ? 0 : sizeof(uint32_t)));
 
487
                   (field_charset == &my_charset_bin ? 0 : packlength));
429
488
}
430
489
 
431
490
void Field_blob::sort_string(unsigned char *to,uint32_t length)
444
503
      /*
445
504
        Store length of blob last in blob to shorter blobs before longer blobs
446
505
      */
447
 
      length-= sizeof(uint32_t); // size of stored blob length
 
506
      length-= packlength;
448
507
      pos= to+length;
449
508
 
450
 
      mi_int4store(pos, blob_length);
 
509
      switch (packlength) {
 
510
      case 1:
 
511
        *pos= (char) blob_length;
 
512
        break;
 
513
      case 2:
 
514
        mi_int2store(pos, blob_length);
 
515
        break;
 
516
      case 3:
 
517
        mi_int3store(pos, blob_length);
 
518
        break;
 
519
      case 4:
 
520
        mi_int4store(pos, blob_length);
 
521
        break;
 
522
      }
451
523
    }
452
 
    memcpy(&blob,ptr+sizeof(uint32_t),sizeof(char*));
 
524
    memcpy(&blob,ptr+packlength,sizeof(char*));
453
525
 
454
526
    blob_length=my_strnxfrm(field_charset,
455
527
                            to, length, blob, blob_length);
459
531
 
460
532
uint32_t Field_blob::pack_length() const
461
533
{
462
 
  return (uint32_t) (sizeof(uint32_t) + portable_sizeof_char_ptr);
 
534
  return (uint32_t) (packlength + getTable()->getShare()->blob_ptr_size);
463
535
}
464
536
 
465
537
void Field_blob::sql_type(String &res) const
482
554
    length given is smaller than the actual length of the blob, we
483
555
    just store the initial bytes of the blob.
484
556
  */
485
 
  store_length(to, min(length, max_length), low_byte_first);
 
557
  store_length(to, packlength, min(length, max_length), low_byte_first);
486
558
 
487
559
  /*
488
560
    Store the actual blob data, which will occupy 'length' bytes.
490
562
  if (length > 0)
491
563
  {
492
564
    get_ptr((unsigned char**) &from);
493
 
    memcpy(to+sizeof(uint32_t), from,length);
 
565
    memcpy(to+packlength, from,length);
494
566
  }
495
567
 
496
568
  ptr= save;                                    // Restore org row pointer
497
 
  return(to+sizeof(uint32_t)+length);
 
569
  return(to+packlength+length);
498
570
}
499
571
 
500
572
/**
516
588
*/
517
589
const unsigned char *Field_blob::unpack(unsigned char *,
518
590
                                        const unsigned char *from,
519
 
                                        uint32_t,
 
591
                                        uint32_t param_data,
520
592
                                        bool low_byte_first)
521
593
{
522
 
  uint32_t const length= get_length(from, low_byte_first);
523
 
  getTable()->setWriteSet(position());
524
 
  store(reinterpret_cast<const char*>(from) + sizeof(uint32_t),
 
594
  uint32_t const master_packlength=
 
595
    param_data > 0 ? param_data & 0xFF : packlength;
 
596
  uint32_t const length= get_length(from, master_packlength, low_byte_first);
 
597
  getTable()->setWriteSet(field_index);
 
598
  store(reinterpret_cast<const char*>(from) + master_packlength,
525
599
        length, field_charset);
526
 
  return(from + sizeof(uint32_t) + length);
 
600
  return(from + master_packlength + length);
527
601
}
528
602
 
529
603
/** Create a packed key that will be used for storage from a MySQL row. */
561
635
 
562
636
uint32_t Field_blob::max_display_length()
563
637
{
 
638
  switch (packlength)
 
639
  {
 
640
  case 1:
 
641
    return 255 * field_charset->mbmaxlen;
 
642
  case 2:
 
643
    return 65535 * field_charset->mbmaxlen;
 
644
  case 3:
 
645
    return 16777215 * field_charset->mbmaxlen;
 
646
  case 4:
564
647
    return (uint32_t) 4294967295U;
 
648
  default:
 
649
    assert(0); // we should never go here
 
650
    return 0;
 
651
  }
565
652
}
566
653
 
567
654
} /* namespace drizzled */