~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/pbms/src/cslib/CSStrUtil.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
 
/* Copyright (C) 2008 PrimeBase Technologies GmbH, Germany
 
1
/* Copyright (c) 2008 PrimeBase Technologies GmbH, Germany
2
2
 *
3
3
 * PrimeBase Media Stream for MySQL
4
4
 *
14
14
 *
15
15
 * You should have received a copy of the GNU General Public License
16
16
 * along with this program; if not, write to the Free Software
17
 
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 
17
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
18
 *
19
19
 * Original author: Paul McCullagh (H&G2JCtL)
20
20
 * Continued development: Barry Leslie
29
29
#include "CSConfig.h"
30
30
#include <inttypes.h>
31
31
 
32
 
#include <stdlib.h>
33
32
#include <stdio.h>
34
33
#include <string.h>
35
34
#include <ctype.h>
36
35
 
37
 
#ifndef OS_WINDOWS
38
 
#include <fnmatch.h>
39
 
#endif
40
 
 
41
36
#include "CSDefs.h"
42
37
#include "CSStrUtil.h"
43
38
#include "CSMemory.h"
44
39
#include "CSGlobal.h"
45
40
 
46
 
const char *cs_version()
47
 
{
48
 
        static char version[124];
49
 
        
50
 
        if (!version[0]) {
51
 
                snprintf(version, 124, "%s(Built %s %s)", VERSION, __DATE__, __TIME__);
52
 
        }
53
 
        
54
 
        return version;
55
 
}
56
 
 
57
41
void cs_strcpy(size_t size, char *to, const char *from, size_t len)
58
42
{
59
43
        if (size > 0) {
75
59
        }
76
60
}
77
61
 
78
 
/* This function adds '...' to the end of the string.
79
 
 * if it does not fit!
80
 
 */
81
 
void cs_strcpy_dottt(size_t size, char *d, const char *s, size_t len)
82
 
{
83
 
        if (len+1 <= size) {
84
 
                cs_strcpy(size, d, s, len);
85
 
                return;
86
 
        }
87
 
        if (size < 5) {
88
 
                /* Silly, but anyway... */
89
 
                cs_strcpy(size, d, "...");
90
 
                return;
91
 
        }
92
 
        memcpy(d, s, size-4);
93
 
        memcpy(d+size-4, "...", 3);
94
 
        d[size-1] = 0;
95
 
}
96
 
 
97
62
void cs_strcpy_left(size_t size, char *to, const char *from, char ch)
98
63
{
99
64
        if (size > 0) {
209
174
                cs_strcat(size, buffer, ")");
210
175
}
211
176
 
212
 
int cs_path_depth(const char *path)
213
 
{
214
 
        int count = 0;
215
 
        while (*path) {
216
 
                if (IS_DIR_CHAR(*path))
217
 
                        count++;
218
 
 
219
 
                path++;
220
 
        }
221
 
        return count;
222
 
}
223
 
 
224
 
static const char *find_wildcard(const char *pattern)
225
 
{
226
 
        bool escaped = false;
227
 
        while (*pattern) {
228
 
                if ((*pattern == '*' || *pattern == '?' ) && !escaped)
229
 
                        return pattern;
230
 
                        
231
 
                if (*pattern == '\\')
232
 
                        escaped = !escaped;
233
 
                else
234
 
                        escaped = false;
235
 
                        
236
 
                pattern++;
237
 
        }
238
 
        
239
 
        return NULL;
240
 
}
241
 
 
242
 
// Check if the path contains any variable components.
243
 
bool cs_fixed_pattern(const char *str)
244
 
{
245
 
        return (find_wildcard(str) == NULL);
246
 
}
247
 
 
248
 
#ifdef OS_WINDOWS
249
 
/* 
250
 
bool cs_match_patern(const char *pattern, const char *str, bool ignore_case)
251
 
{
252
 
        bool escaped = false;
253
 
        
254
 
        while (*pattern && *str) {
255
 
                if ((*pattern == '*' || *pattern == '?' ) && !escaped) {
256
 
                        if (*pattern == '?') {
257
 
                                pattern++;
258
 
                                str++;  
259
 
                                continue;                       
260
 
                        }
261
 
                        
262
 
                        while (*pattern == '*' || *pattern == '?' ) pattern++; // eat the pattern matching characters.
263
 
                        
264
 
                        if (!*pattern) // A * at the end of the pattern matches everything.
265
 
                                return true;
266
 
                                
267
 
                        // This is where it gets complicted.
268
 
                        
269
 
                        coming soon!
270
 
                        
271
 
                }
272
 
                                        
273
 
                if (*pattern == '\\')
274
 
                        escaped = !escaped;
275
 
                else
276
 
                        escaped = false;
277
 
                        
278
 
                if (escaped)
279
 
                        pattern++;
280
 
                else {
281
 
                        if (ignore_case) {
282
 
                                if (toupper(*pattern) != toupper(*str))
283
 
                                        return false;
284
 
                        } else if (*pattern != *str)
285
 
                                return false;
286
 
                        pattern++;
287
 
                        str++;                          
288
 
                }
289
 
                
290
 
        }
291
 
        
292
 
        return ((!*pattern) && (!*str));
293
 
}
294
 
*/
295
 
#else
296
 
bool cs_match_patern(const char *pattern, const char *str, bool ignore_case)
297
 
{
298
 
        return (fnmatch(pattern, str, (ignore_case)?FNM_CASEFOLD:0) == 0);
299
 
}
300
 
#endif
301
 
 
302
177
/* This function returns "" if the path ends with a dir char */
303
178
char *cs_last_name_of_path(const char *path, int count)
304
179
{
327
202
}
328
203
 
329
204
/* This function returns the last name component, even if the path ends with a dir char */
330
 
char *cs_last_directory_of_path(const char *path)
 
205
char *cs_last_directory_of_path(char *path)
331
206
{
332
207
        size_t  length;
333
 
        const char      *ptr;
 
208
        char    *ptr;
334
209
 
335
210
        length = strlen(path);
336
211
        if (!length)
337
 
                return((char *)path);
 
212
                return(path);
338
213
        ptr = path + length - 1;
339
214
        if (IS_DIR_CHAR(*ptr))
340
215
                ptr--;
341
216
        while (ptr != path && !IS_DIR_CHAR(*ptr)) ptr--;
342
217
        if (IS_DIR_CHAR(*ptr)) ptr++;
343
 
        return((char *)ptr);
 
218
        return(ptr);
344
219
}
345
220
 
346
221
const char *cs_find_extension(const char *file_name)
527
402
                return NULL;
528
403
 
529
404
        str = (char *) cs_malloc(len + 1);
530
 
 
531
 
        // Allow for allocation of an oversized buffer.
532
 
        size_t str_len = strlen(in_str);
533
 
        if (len > str_len)
534
 
                len = str_len;
535
 
                
536
405
        memcpy(str, in_str, len);
537
406
        str[len] = 0;
538
407
        return str;
549
418
        return *cstr || !*w_cstr;
550
419
}
551
420
 
552
 
bool cs_ends_with(const char *cstr, const char *w_cstr)
553
 
{
554
 
        size_t          len = strlen(cstr);
555
 
        size_t          w_len = strlen(w_cstr);
556
 
        const char      *ptr = cstr + len - 1;
557
 
        const char      *w_ptr = w_cstr + w_len - 1;
558
 
        
559
 
        if (w_len > len)
560
 
                return false;
561
 
 
562
 
        if (w_len == 0)
563
 
                return false;
564
 
 
565
 
        while (w_ptr >= w_cstr) {
566
 
                if (*w_ptr != *ptr)
567
 
                        return false;
568
 
                w_ptr--;
569
 
                ptr--;
570
 
        }
571
 
 
572
 
        return true;
573
 
}
574
 
 
575
 
void cs_replace_string(size_t size, char *into, const char *find_str, const char *str)
576
 
{
577
 
        char *ptr;
578
 
 
579
 
        if ((ptr = strstr(into, find_str))) {
580
 
                size_t len = strlen(into);
581
 
                size_t len2 = strlen(str);
582
 
                size_t len3 = strlen(find_str);
583
 
                
584
 
                if (len + len2 + len3 >= size)
585
 
                        len2 = size - len;
586
 
                
587
 
                memmove(ptr+len2, ptr+len3, len - (ptr + len3 - into));
588
 
                memcpy(ptr, str, len2);
589
 
                into[len + len2 - len3] = 0;
590
 
        }
591
 
}
592
 
 
593
421
void cs_replace_string(size_t size, char *into, const char ch, const char *str)
594
422
{
595
423
        char *ptr;
641
469
        return value;
642
470
}
643
471
 
644
 
int64_t cs_byte_size_to_int8(const char *ptr, bool *invalid)
 
472
int64_t cs_byte_size_to_int8(const char *ptr)
645
473
{
646
 
        char    *end_ptr;
 
474
        char    number[101], *num_ptr;
647
475
        int64_t size;
648
476
 
649
 
        if (invalid)
650
 
                *invalid = false;
651
 
 
652
477
        while (*ptr && isspace(*ptr))
653
478
                ptr++;
654
479
 
655
 
        if (!isdigit(*ptr) && *ptr != '.')
656
 
                goto failed;
657
 
 
658
 
        size = (int64_t) strtod(ptr, &end_ptr);
659
 
 
660
 
        ptr = end_ptr;
 
480
        num_ptr = number;
 
481
        while (*ptr && isdigit(*ptr)) {
 
482
                if (num_ptr < number+100) {
 
483
                        *num_ptr = *ptr;
 
484
                        num_ptr++;
 
485
                }
 
486
                ptr++;
 
487
        }
 
488
        *num_ptr = 0;
 
489
        size = cs_str_to_int8(number, NULL);
 
490
 
661
491
        while (*ptr && isspace(*ptr))
662
492
                ptr++;
663
493
        
664
494
        switch (toupper(*ptr)) {
665
 
                case 'P':
666
 
                        size *= (int64_t) 1024;
667
 
                case 'T':
668
 
                        size *= (int64_t) 1024;
669
495
                case 'G':
670
 
                        size *= (int64_t) 1024;
 
496
                        size *= 1024LL * 1024LL * 1024LL;
 
497
                        break;
671
498
                case 'M':
672
 
                        size *= (int64_t) 1024;
 
499
                        size *= 1024LL * 1024LL;
 
500
                        break;
673
501
                case 'K':
674
 
                        size *= (int64_t) 1024;
675
 
                        ptr++;
676
 
                        break;
677
 
                case '\0':
678
 
                        break;
679
 
                default:
680
 
                        goto failed;
681
 
        }
682
 
        
683
 
        if (toupper(*ptr) == 'B')
684
 
                ptr++;
685
 
 
686
 
        while (*ptr && isspace(*ptr))
687
 
                ptr++;
688
 
 
689
 
        if (*ptr)
690
 
                goto failed;
691
 
 
692
 
        return (int64_t) size;
693
 
 
694
 
        failed:
695
 
        if (invalid)
696
 
                *invalid = true;
697
 
        return 0;
698
 
}
699
 
 
700
 
 
701
 
static uint32_t cs_hex_value(char ch)
702
 
{
703
 
        u_char uch = (u_char) ch;
704
 
 
705
 
        if (uch >= '0' && uch <= '9')
706
 
                return uch - '0';
707
 
        if (uch >= 'A' && uch <= 'F')
708
 
                return uch - 'A' + 10; 
709
 
        if (uch >= 'a' && uch <= 'f')
710
 
                return uch - 'a' + 10;
711
 
        return 0;
712
 
}
713
 
 
714
 
size_t cs_hex_to_bin(size_t size, void *v_bin, size_t len, const char *hex)
715
 
{
716
 
        size_t  tot_size = size;
717
 
        uint32_t        val = 0;
718
 
        size_t  shift = 0;
719
 
        u_char *bin = (u_char *) v_bin;
720
 
 
721
 
        if (len & 1)
722
 
                shift = 1;
723
 
        for (size_t i=shift; i<len+shift && size > 0; i++) {
724
 
                if (i & 1) {
725
 
                        val = val | cs_hex_value(*hex);
726
 
                        *bin = val;
727
 
                        bin++;
728
 
                        size--;
729
 
                }
730
 
                else
731
 
                        val = cs_hex_value(*hex) << 4;
732
 
                hex++;
733
 
        }
734
 
        return tot_size - size;
735
 
}
736
 
 
737
 
size_t cs_hex_to_bin(size_t size, void *bin, const char *hex)
738
 
{
739
 
        return cs_hex_to_bin(size, bin, strlen(hex), hex);
740
 
}
741
 
 
742
 
#define HEX_DIGIT(x)    ((x) <= 9 ? '0' + (x) : 'A' + ((x) - 10))
743
 
 
744
 
void cs_bin_to_hex(size_t size, char *hex, size_t len, const void *v_bin)
745
 
{
746
 
        const u_char *bin = (u_char *) v_bin;
747
 
        if (size == 0)
748
 
                return;
749
 
        size--;
750
 
        for (size_t i=0; i<len && size > 0; i++) {
751
 
                *hex = HEX_DIGIT(*bin >> 4);
752
 
                hex++;
753
 
                size--;
754
 
                if (size == 0)
755
 
                        break;
756
 
                *hex = HEX_DIGIT(*bin & 0x0F);
757
 
                hex++;
758
 
                size--;
759
 
                bin++;
760
 
        }
761
 
        *hex = 0;
 
502
                        size *= 1024LL;
 
503
                        break;
 
504
        }
 
505
        
 
506
        return size;
 
507
}
 
508
 
 
509
 
 
510
/*--------------------------------------------------------------------------------------------------*/
 
511
size_t cs_hex_to_bin(size_t size, void *bin, size_t len, const char *hex)
 
512
{       
 
513
        unsigned char *bin_ptr, *hex_ptr, c, val;
 
514
        size_t result = 0;
 
515
 
 
516
        if (len %2)  /* The hex string must be an even number of bytes. */
 
517
                len--;
 
518
                
 
519
        if (len > (2 *size)) {
 
520
                len = 2 * size;
 
521
        } 
 
522
                        
 
523
        bin_ptr = (unsigned char *) bin;        
 
524
        hex_ptr = (unsigned char *) hex;        
 
525
 
 
526
        
 
527
        for (; len > 0; len--, hex_ptr++) {
 
528
                c = *hex_ptr;
 
529
                if ((c >= '0') && (c <= '9')) {
 
530
                        val = c - '0';
 
531
                }
 
532
                else {
 
533
                        c = toupper(c);
 
534
                        if ((c >= 'A') && (c <= 'F')) {
 
535
                                val = c - 'A' + 10;
 
536
                        }
 
537
                        else
 
538
                                return(result);
 
539
                }
 
540
                
 
541
                if ( len & 0X01) {
 
542
                        *bin_ptr += val;
 
543
                        bin_ptr++;
 
544
                        result++;
 
545
                }
 
546
                else {
 
547
                        *bin_ptr = val << 4;
 
548
                }
 
549
        }
 
550
        
 
551
        return(result);
 
552
}
 
553
        
 
554
/*--------------------------------------------------------------------------------------------------*/
 
555
size_t cs_bin_to_hex(size_t size, char *hex, size_t len, const void *bin)
 
556
{
 
557
        static uint16_t hex_table[256], initialized = 0;
 
558
        uint16_t *hex_ptr = (uint16_t *)hex;
 
559
        unsigned char *bin_ptr = (unsigned char *)bin;
 
560
        size_t  result = 0;
 
561
 
 
562
        /* init the hex table if required */
 
563
        if (!initialized) {
 
564
                char buf[20];
 
565
                int i;
 
566
                for ( i=0; i < 256; i++) {
 
567
                        snprintf(buf, 20,"%X", i + 256);
 
568
                        memcpy(&(hex_table[i]), buf +1, 2);
 
569
                }
 
570
                
 
571
                initialized = 1;
 
572
        }
 
573
        /*----------------------------------*/  
 
574
 
 
575
        if (size < len *2) {
 
576
                len = size/2;
 
577
        }
 
578
                
 
579
        result = len *2;
 
580
                
 
581
        hex_ptr += len -1;
 
582
        bin_ptr += len -1;
 
583
        for (; len != 0; len--, hex_ptr--, bin_ptr--) {
 
584
                memcpy(hex_ptr, hex_table + *bin_ptr, 2);
 
585
        }
 
586
        
 
587
        // If there is room null terminate the hex string.
 
588
        if (size > result)
 
589
                hex[result] = 0;
 
590
                
 
591
        return(result);
762
592
}       
763
593
 
764
594
void cs_strToUpper(char *ptr)
777
607
        }
778
608
}
779
609
 
780
 
/*
781
 
 * Return failed if this is not a valid number.
782
 
 */
783
 
bool cs_str_to_value(const char *ptr, uint32_t *value, uint8_t base)
784
 
{
785
 
        char *endptr;
786
 
 
787
 
        *value = strtoul(ptr, &endptr, base);
788
 
        return *endptr ? false : true;
789
 
}
790
 
 
791