diff options
-rw-r--r-- | Docs/manual.texi | 9 | ||||
-rw-r--r-- | myisam/mi_locking.c | 7 | ||||
-rw-r--r-- | mysql-test/r/join_outer.result | 11 | ||||
-rw-r--r-- | mysql-test/t/join_outer.test | 12 | ||||
-rw-r--r-- | mysys/my_init.c | 2 | ||||
-rw-r--r-- | scripts/mysqlhotcopy.sh | 96 | ||||
-rw-r--r-- | sql/sql_select.cc | 22 |
7 files changed, 126 insertions, 33 deletions
diff --git a/Docs/manual.texi b/Docs/manual.texi index fe1ca86af6b..560ad720050 100644 --- a/Docs/manual.texi +++ b/Docs/manual.texi @@ -46784,6 +46784,7 @@ users use this code as the rest of the code and because of this we are not yet 100% confident in this code. @menu +* News-3.23.47:: * News-3.23.46:: Changes in release 3.23.46 * News-3.23.45:: Changes in release 3.23.45 * News-3.23.44:: Changes in release 3.23.44 @@ -46834,7 +46835,13 @@ not yet 100% confident in this code. * News-3.23.0:: Changes in release 3.23.0 @end menu -@node News-3.23.46, News-3.23.45, News-3.23.x, News-3.23.x +@node News-3.23.47, News-3.23.46, News-3.23.x, News-3.23.x +@appendixsubsec Changes in release 3.23.46 +@itemize @bullet +Fixed bug when using @code{t1 LEFT JOIN t2 ON t2.key=constant}. +@end itemize + +@node News-3.23.46, News-3.23.45, News-3.23.47, News-3.23.x @appendixsubsec Changes in release 3.23.46 @itemize @bullet @item diff --git a/myisam/mi_locking.c b/myisam/mi_locking.c index e067e80fcf3..de5f0d0c2cf 100644 --- a/myisam/mi_locking.c +++ b/myisam/mi_locking.c @@ -303,10 +303,9 @@ int _mi_readinfo(register MI_INFO *info, int lock_type, int check_keybuffer) { if (!share->r_locks && !share->w_locks) { - if ((info->tmp_lock_type=lock_type) != F_RDLCK) - if (my_lock(share->kfile,lock_type,0L,F_TO_EOF, - info->lock_wait | MY_SEEK_NOT_DONE)) - DBUG_RETURN(1); + if (my_lock(share->kfile,lock_type,0L,F_TO_EOF, + info->lock_wait | MY_SEEK_NOT_DONE)) + DBUG_RETURN(1); if (mi_state_info_read_dsk(share->kfile, &share->state, 1)) { int error=my_errno ? my_errno : -1; diff --git a/mysql-test/r/join_outer.result b/mysql-test/r/join_outer.result index 38f2f44f6ce..f5e643a9bbf 100644 --- a/mysql-test/r/join_outer.result +++ b/mysql-test/r/join_outer.result @@ -320,3 +320,14 @@ id name id idx 2 no NULL NULL bug_id reporter bug_id who 1 1 1 2 +table type possible_keys key key_len ref rows Extra +t2 index NULL PRIMARY 4 NULL 3 Using index +t1 eq_ref PRIMARY PRIMARY 2 const 1 where used; Using index +fooID barID fooID +10 1 NULL +20 2 NULL +30 3 30 +fooID barID fooID +10 1 NULL +20 2 NULL +30 3 30 diff --git a/mysql-test/t/join_outer.test b/mysql-test/t/join_outer.test index 774f35ae38e..af5f377afb5 100644 --- a/mysql-test/t/join_outer.test +++ b/mysql-test/t/join_outer.test @@ -404,3 +404,15 @@ insert into t2 values (1,1),(1,2); insert into t1 values (1,1),(2,1); SELECT * FROM t1 LEFT JOIN t2 ON (t1.bug_id = t2.bug_id AND t2.who = 2) WHERE (t1.reporter = 2 OR t2.who = 2); drop table t1,t2; + +# +# Test problem with LEFT JOIN + +create table t1 (fooID smallint unsigned auto_increment, primary key (fooID)); +create table t2 (fooID smallint unsigned not null, barID smallint unsigned not null, primary key (fooID,barID)); +insert into t1 (fooID) values (10),(20),(30); +insert into t2 values (10,1),(20,2),(30,3); +explain select * from t2 left join t1 on t1.fooID = t2.fooID and t1.fooID = 30; +select * from t2 left join t1 on t1.fooID = t2.fooID and t1.fooID = 30; +select * from t2 left join t1 ignore index(primary) on t1.fooID = t2.fooID and t1.fooID = 30; +drop table t1,t2; diff --git a/mysys/my_init.c b/mysys/my_init.c index c3b9cecf86e..3bc87fd179d 100644 --- a/mysys/my_init.c +++ b/mysys/my_init.c @@ -126,6 +126,7 @@ void my_end(int infoflag) DBUG_PRINT("error",("%s",errbuff[0])); } } + free_charsets(); if (infoflag & MY_GIVE_INFO || info_file != stderr) { #ifdef HAVE_GETRUSAGE @@ -150,7 +151,6 @@ Voluntary context switches %ld, Involuntary context switches %ld\n", #if defined(MSDOS) && !defined(__WIN__) fprintf(info_file,"\nRun time: %.1f\n",(double) clock()/CLOCKS_PER_SEC); #endif - free_charsets(); #if defined(SAFEMALLOC) TERMINATE(stderr); /* Give statistic on screen */ #elif defined(__WIN__) && defined(_MSC_VER) diff --git a/scripts/mysqlhotcopy.sh b/scripts/mysqlhotcopy.sh index 655e5a2a52b..caf2615fe7a 100644 --- a/scripts/mysqlhotcopy.sh +++ b/scripts/mysqlhotcopy.sh @@ -37,7 +37,7 @@ WARNING: THIS PROGRAM IS STILL IN BETA. Comments/patches welcome. # Documentation continued at end of file -my $VERSION = "1.13"; +my $VERSION = "1.14"; my $opt_tmpdir = $ENV{TMPDIR} || "/tmp"; @@ -120,6 +120,7 @@ GetOptions( \%opt, # 'target' - destination directory of the copy # 'tables' - array-ref to list of tables in the db # 'files' - array-ref to list of files to be copied +# (RAID files look like 'nn/name.MYD') # 'index' - array-ref to list of indexes to be copied # @@ -265,11 +266,23 @@ foreach my $rdb ( @db_desc ) { or die "Cannot open dir '$db_dir': $!"; my %db_files; - map { ( /(.+)\.\w+$/ ? ( $db_files{$_} = $1 ) : () ) } readdir(DBDIR); + my @raid_dir = (); + + while ( defined( my $name = readdir DBDIR ) ) { + if ( $name =~ /^\d\d$/ && -d "$db_dir/$name" ) { + push @raid_dir, $name; + } + else { + $db_files{$name} = $1 if ( $name =~ /(.+)\.\w+$/ ); + } + } + closedir( DBDIR ); + + scan_raid_dir( \%db_files, $db_dir, @raid_dir ); + unless( keys %db_files ) { warn "'$db' is an empty database\n"; } - closedir( DBDIR ); ## filter (out) files specified in t_regex my @db_files; @@ -297,6 +310,8 @@ foreach my $rdb ( @db_desc ) { my @hc_tables = map { "$db.$_" } @dbh_tables; $rdb->{tables} = [ @hc_tables ]; + $rdb->{raid_dirs} = [ get_raid_dirs( $rdb->{files} ) ]; + $hc_locks .= ", " if ( length $hc_locks && @hc_tables ); $hc_locks .= join ", ", map { "$_ READ" } @hc_tables; $hc_tables .= ", " if ( length $hc_tables && @hc_tables ); @@ -370,17 +385,20 @@ if ($opt{method} =~ /^cp\b/) retire_directory( @existing ) if ( @existing ); foreach my $rdb ( @db_desc ) { - my $tgt_dirpath = $rdb->{target}; - if ( $opt{dryrun} ) { - print "mkdir $tgt_dirpath, 0750\n"; - } - elsif ($opt{method} =~ /^scp\b/) { - ## assume it's there? - ## ... - } - else { - mkdir($tgt_dirpath, 0750) - or die "Can't create '$tgt_dirpath': $!\n"; + foreach my $td ( '', @{$rdb->{raid_dirs}} ) { + + my $tgt_dirpath = "$rdb->{target}/$td"; + if ( $opt{dryrun} ) { + print "mkdir $tgt_dirpath, 0750\n"; + } + elsif ($opt{method} =~ /^scp\b/) { + ## assume it's there? + ## ... + } + else { + mkdir($tgt_dirpath, 0750) + or die "Can't create '$tgt_dirpath': $!\n"; + } } } @@ -438,7 +456,7 @@ foreach my $rdb ( @db_desc ) my @files = map { "$datadir/$rdb->{src}/$_" } @{$rdb->{files}}; next unless @files; - eval { copy_files($opt{method}, \@files, $rdb->{target} ); }; + eval { copy_files($opt{method}, \@files, $rdb->{target}, $rdb->{raid_dirs} ); }; push @failed, "$rdb->{src} -> $rdb->{target} failed: $@" if ( $@ ); @@ -531,27 +549,33 @@ exit 0; # --- sub copy_files { - my ($method, $files, $target) = @_; + my ($method, $files, $target, $raid_dirs) = @_; my @cmd; print "Copying ".@$files." files...\n" unless $opt{quiet}; if ($method =~ /^s?cp\b/) { # cp or scp with optional flags - @cmd = ($method); + my @cp = ($method); # add option to preserve mod time etc of copied files # not critical, but nice to have - push @cmd, "-p" if $^O =~ m/^(solaris|linux|freebsd)$/; + push @cp, "-p" if $^O =~ m/^(solaris|linux|freebsd)$/; # add recursive option for scp - push @cmd, "-r" if $^O =~ /m^(solaris|linux|freebsd)$/ && $method =~ /^scp\b/; + push @cp, "-r" if $^O =~ /m^(solaris|linux|freebsd)$/ && $method =~ /^scp\b/; + + my @non_raid = grep { $_ !~ m:\d\d/: } @$files; # add files to copy and the destination directory - push @cmd, @$files, $target; + safe_system( @cp, @non_raid, $target ); + + foreach my $rd ( @$raid_dirs ) { + my @raid = grep { m:$rd/: } @$files; + safe_system( @cp, @raid, "$target/$rd" ) if ( @raid ); + } } else { die "Can't use unsupported method '$method'\n"; } - safe_system (@cmd); } # @@ -682,6 +706,35 @@ sub get_row { return $sth->fetchrow_array(); } +sub scan_raid_dir { + my ( $r_db_files, $data_dir, @raid_dir ) = @_; + + local(*RAID_DIR); + + foreach my $rd ( @raid_dir ) { + + opendir(RAID_DIR, "$data_dir/$rd" ) + or die "Cannot open dir '$data_dir/$rd': $!"; + + while ( defined( my $name = readdir RAID_DIR ) ) { + $r_db_files->{"$rd/$name"} = $1 if ( $name =~ /(.+)\.\w+$/ ); + } + closedir( RAID_DIR ); + } +} + +sub get_raid_dirs { + my ( $r_files ) = @_; + + my %dirs = (); + foreach my $f ( @$r_files ) { + if ( $f =~ m:^(\d\d)/: ) { + $dirs{$1} = 1; + } + } + return sort keys %dirs; +} + __END__ =head1 DESCRIPTION @@ -905,6 +958,7 @@ Tim Bunce Martin Waite - added checkpoint, flushlog, regexp and dryrun options Fixed cleanup of targets when hotcopy fails. Added --record_log_pos. + RAID tables are now copied (don't know if this works over scp). Ralph Corderoy - added synonyms for commands diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 9456211a7cc..330df610b46 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -2119,10 +2119,17 @@ get_best_combination(JOIN *join) j->type=JT_REF; /* Must read with repeat */ else if (ref_key == j->ref.key_copy) { /* Should never be reached */ - j->type=JT_CONST; /* purecov: deadcode */ + /* + This happen if we are using a constant expression in the ON part + of an LEFT JOIN. + SELECT * FROM a LEFT JOIN b ON b.key=30 + Here we should not mark the table as a 'const' as a field may + have a 'normal' value or a NULL value. + */ + j->type=JT_CONST; if (join->const_tables == tablenr) { - join->const_tables++; /* purecov: deadcode */ + join->const_tables++; join->const_table_map|=form->map; } } @@ -2251,7 +2258,7 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) used_tables|=current_map; if (tab->type == JT_REF && tab->quick && - tab->ref.key == tab->quick->index && + (uint) tab->ref.key == tab->quick->index && tab->ref.key_length < tab->quick->max_used_key_length) { /* Range uses longer key; Use this instead of ref on key */ @@ -2689,8 +2696,8 @@ static void update_depend_map(JOIN *join, ORDER *order) /* -** simple_order is set to 1 if sort_order only uses fields from head table -** and the head table is not a LEFT JOIN table + simple_order is set to 1 if sort_order only uses fields from head table + and the head table is not a LEFT JOIN table */ static ORDER * @@ -4331,8 +4338,11 @@ join_read_const(JOIN_TAB *tab) } store_record(table,1); } - else if (!table->status) // Only happens with left join + else if (!(table->status & ~STATUS_NULL_ROW)) // Only happens with left join + { + table->status=0; restore_record(table,1); // restore old record + } table->null_row=0; return table->status ? -1 : 0; } |