Commit acdaa9ae authored by Alexey Botchkov's avatar Alexey Botchkov
Browse files

Bug#38005 Partitions: error with insert select.

MyISAM blocks index usage for bulk insert into zero-records tables.
See ha_myisam::start_bulk_insert() lines from
...
    if (file->state->records == 0 ...
...

That causes problems for partition engine when some partitions have records some not
as the engine uses same access method for all partitions.

Now partition engine doesn't call index_first/index_last
for empty tables.

per-file comments:
  mysql-test/r/partition.result
        Bug#38005 Partitions: error with insert select.
        test result

  mysql-test/t/partition.test
        Bug#38005 Partitions: error with insert select.
        test case

  sql/ha_partition.cc
        Bug#38005 Partitions: error with insert select.
        ha_engine::index_first and
        ha_engine::index_last not called for empty tables.
parent 79a66a97
Loading
Loading
Loading
Loading
+70 −0
Original line number Diff line number Diff line
@@ -1637,4 +1637,74 @@ select count(*) from t1, t2 where t1.createdDate = t2.createdDate;
count(*)
1
drop table t1, t2;
create table t1 (s1 int) partition by hash(s1) partitions 2;
create index i on t1 (s1);
insert into t1 values (1);
insert into t1 select s1 from t1;
insert into t1 select s1 from t1;
insert into t1 select s1 from t1 order by s1 desc;
select * from t1;
s1
1
1
1
1
1
1
1
1
drop table t1;
create table t1 (s1 int) partition by range(s1) 
(partition pa1 values less than (10),
partition pa2 values less than MAXVALUE);
create index i on t1 (s1);
insert into t1 values (1);
insert into t1 select s1 from t1;
insert into t1 select s1 from t1;
insert into t1 select s1 from t1 order by s1 desc;
select * from t1;
s1
1
1
1
1
1
1
1
1
drop table t1;
create table t1 (s1 int) partition by range(s1) 
(partition pa1 values less than (10),
partition pa2 values less than MAXVALUE);
create index i on t1 (s1);
insert into t1 values (20);
insert into t1 select s1 from t1;
insert into t1 select s1 from t1;
insert into t1 select s1 from t1 order by s1 desc;
select * from t1;
s1
20
20
20
20
20
20
20
20
drop table t1;
create table t1 (s1 int) partition by range(s1) 
(partition pa1 values less than (10),
partition pa2 values less than MAXVALUE);
create index i on t1 (s1);
insert into t1 values (1), (2), (3), (4), (5), (6), (7), (8);
insert into t1 select s1 from t1;
insert into t1 select s1 from t1;
insert into t1 select s1 from t1;
insert into t1 select s1 from t1;
insert into t1 select s1 from t1 order by s1 desc;
insert into t1 select s1 from t1 where s1=3;
select count(*) from t1;
count(*)
288
drop table t1;
End of 5.1 tests
+49 −0
Original line number Diff line number Diff line
@@ -1791,4 +1791,53 @@ select count(*) from t1, t2 where t1.createdDate = t2.createdDate;

drop table t1, t2;

#
# Bug #38005 Partitions: error with insert select
#

create table t1 (s1 int) partition by hash(s1) partitions 2;
create index i on t1 (s1);
insert into t1 values (1);
insert into t1 select s1 from t1;
insert into t1 select s1 from t1;
insert into t1 select s1 from t1 order by s1 desc;
select * from t1;
drop table t1;

create table t1 (s1 int) partition by range(s1) 
        (partition pa1 values less than (10),
         partition pa2 values less than MAXVALUE);
create index i on t1 (s1);
insert into t1 values (1);
insert into t1 select s1 from t1;
insert into t1 select s1 from t1;
insert into t1 select s1 from t1 order by s1 desc;
select * from t1;
drop table t1;

create table t1 (s1 int) partition by range(s1) 
        (partition pa1 values less than (10),
         partition pa2 values less than MAXVALUE);
create index i on t1 (s1);
insert into t1 values (20);
insert into t1 select s1 from t1;
insert into t1 select s1 from t1;
insert into t1 select s1 from t1 order by s1 desc;
select * from t1;
drop table t1;

create table t1 (s1 int) partition by range(s1) 
        (partition pa1 values less than (10),
         partition pa2 values less than MAXVALUE);
create index i on t1 (s1);
insert into t1 values (1), (2), (3), (4), (5), (6), (7), (8);
insert into t1 select s1 from t1;
insert into t1 select s1 from t1;
insert into t1 select s1 from t1;
insert into t1 select s1 from t1;
insert into t1 select s1 from t1 order by s1 desc;
insert into t1 select s1 from t1 where s1=3;
select count(*) from t1;
drop table t1;

--echo End of 5.1 tests
+33 −0
Original line number Diff line number Diff line
@@ -4290,6 +4290,17 @@ int ha_partition::handle_unordered_scan_next_partition(uchar * buf)
      break;
    case partition_index_first:
      DBUG_PRINT("info", ("index_first on partition %d", i));
      /* MyISAM engine can fail if we call index_first() when indexes disabled */
      /* that happens if the table is empty. */
      /* Here we use file->stats.records instead of file->records() because */
      /* file->records() is supposed to return an EXACT count, and it can be   */
      /* possibly slow. We don't need an exact number, an approximate one- from*/
      /* the last ::info() call - is sufficient. */
      if (file->stats.records == 0)
      {
        error= HA_ERR_END_OF_FILE;
        break;
      }
      error= file->index_first(buf);
      break;
    case partition_index_first_unordered:
@@ -4377,10 +4388,32 @@ int ha_partition::handle_ordered_index_scan(uchar *buf, bool reverse_order)
                                  m_start_key.flag);
      break;
    case partition_index_first:
      /* MyISAM engine can fail if we call index_first() when indexes disabled */
      /* that happens if the table is empty. */
      /* Here we use file->stats.records instead of file->records() because */
      /* file->records() is supposed to return an EXACT count, and it can be   */
      /* possibly slow. We don't need an exact number, an approximate one- from*/
      /* the last ::info() call - is sufficient. */
      if (file->stats.records == 0)
      {
        error= HA_ERR_END_OF_FILE;
        break;
      }
      error= file->index_first(rec_buf_ptr);
      reverse_order= FALSE;
      break;
    case partition_index_last:
      /* MyISAM engine can fail if we call index_last() when indexes disabled */
      /* that happens if the table is empty. */
      /* Here we use file->stats.records instead of file->records() because */
      /* file->records() is supposed to return an EXACT count, and it can be   */
      /* possibly slow. We don't need an exact number, an approximate one- from*/
      /* the last ::info() call - is sufficient. */
      if (file->stats.records == 0)
      {
        error= HA_ERR_END_OF_FILE;
        break;
      }
      error= file->index_last(rec_buf_ptr);
      reverse_order= TRUE;
      break;