diff --git a/mysql-test/r/partition.result b/mysql-test/r/partition.result
index 2fb7b6942de..6e440c4312c 100644
--- a/mysql-test/r/partition.result
+++ b/mysql-test/r/partition.result
@@ -3,6 +3,23 @@ create table t1 (a int)
 partition by key(a)
 (partition p0 engine = MEMORY);
 drop table t1;
+create table t1 (a int)
+partition by range (a)
+subpartition by key (a)
+(partition p0 values less than (1));
+alter table t1 add partition (partition p1 values less than (2));
+show create table t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `a` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 PARTITION BY RANGE (a) SUBPARTITION BY KEY (a) (PARTITION p0 VALUES LESS THAN (1) ENGINE = MyISAM, PARTITION p1 VALUES LESS THAN (2) ENGINE = MyISAM)
+alter table t1 reorganize partition p1 into (partition p1 values less than (3));
+show create table t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `a` int(11) DEFAULT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 PARTITION BY RANGE (a) SUBPARTITION BY KEY (a) (PARTITION p0 VALUES LESS THAN (1) ENGINE = MyISAM, PARTITION p1 VALUES LESS THAN (3) ENGINE = MyISAM)
+drop table t1;
 CREATE TABLE t1 (
 a int not null,
 b int not null,
@@ -574,7 +591,7 @@ show create table t1;
 Table	Create Table
 t1	CREATE TABLE `t1` (
   `a` int(11) DEFAULT NULL
-) ENGINE=MyISAM DEFAULT CHARSET=latin1 PARTITION BY RANGE (a) SUBPARTITION BY HASH (a) (PARTITION p0 VALUES LESS THAN (100) )
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 PARTITION BY RANGE (a) SUBPARTITION BY HASH (a) (PARTITION p0 VALUES LESS THAN (100) ENGINE = MyISAM)
 alter table t1 add partition (partition p1 values less than (200)
 (subpartition subpart21));
 show create table t1;
diff --git a/mysql-test/r/partition_02myisam.result b/mysql-test/r/partition_02myisam.result
index a7786bfcfbd..147e705f861 100644
--- a/mysql-test/r/partition_02myisam.result
+++ b/mysql-test/r/partition_02myisam.result
@@ -996,7 +996,7 @@ Table	Create Table
 t1	CREATE TABLE `t1` (
   `f1` int(11) DEFAULT NULL,
   `f2` char(20) DEFAULT NULL
-) ENGINE=MyISAM DEFAULT CHARSET=latin1 PARTITION BY RANGE (f1) SUBPARTITION BY HASH (f1) SUBPARTITIONS 2 (PARTITION part1 VALUES LESS THAN (100) , PARTITION part2 VALUES LESS THAN (2147483647) )
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 PARTITION BY RANGE (f1) SUBPARTITION BY HASH (f1) SUBPARTITIONS 2 (PARTITION part1 VALUES LESS THAN (100) ENGINE = MyISAM, PARTITION part2 VALUES LESS THAN (2147483647) ENGINE = MyISAM)
 SELECT COUNT(*) = 0 AS my_value FROM t1;
 my_value
 1
@@ -1098,7 +1098,7 @@ Table	Create Table
 t1	CREATE TABLE `t1` (
   `f1` int(11) DEFAULT NULL,
   `f2` char(20) DEFAULT NULL
-) ENGINE=MyISAM DEFAULT CHARSET=latin1 PARTITION BY RANGE (f1) SUBPARTITION BY HASH (f1) SUBPARTITIONS 1 (PARTITION part1 VALUES LESS THAN (100) , PARTITION part2 VALUES LESS THAN (2147483647) )
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 PARTITION BY RANGE (f1) SUBPARTITION BY HASH (f1) SUBPARTITIONS 1 (PARTITION part1 VALUES LESS THAN (100) ENGINE = MyISAM, PARTITION part2 VALUES LESS THAN (2147483647) ENGINE = MyISAM)
 SELECT COUNT(*) = 0 AS my_value FROM t1;
 my_value
 1
diff --git a/mysql-test/t/partition.test b/mysql-test/t/partition.test
index f7676ca471a..be4fc1081f3 100644
--- a/mysql-test/t/partition.test
+++ b/mysql-test/t/partition.test
@@ -14,6 +14,19 @@ partition by key(a)
 (partition p0 engine = MEMORY);
 drop table t1;
 
+#
+# BUG 19067 ALTER TABLE .. ADD PARTITION for subpartitioned table crashes
+#
+create table t1 (a int)
+partition by range (a)
+subpartition by key (a)
+(partition p0 values less than (1));
+alter table t1 add partition (partition p1 values less than (2));
+show create table t1;
+alter table t1 reorganize partition p1 into (partition p1 values less than (3));
+show create table t1;
+drop table t1;
+
 #
 # Partition by key no partition defined => OK
 #
diff --git a/sql/partition_element.h b/sql/partition_element.h
index 13693934c0f..bd68d8b18ea 100644
--- a/sql/partition_element.h
+++ b/sql/partition_element.h
@@ -67,5 +67,21 @@ public:
     subpartitions.empty();
     list_val_list.empty();
   }
+  partition_element(partition_element *part_elem)
+  : partition_name(NULL), range_value(0), has_null_value(FALSE)
+  {
+    subpartitions.empty();
+    list_val_list.empty();
+
+    part_max_rows= part_elem->part_max_rows;
+    part_min_rows= part_elem->part_min_rows;
+    tablespace_name= part_elem->tablespace_name;
+    part_comment= part_elem->part_comment;
+    data_file_name= part_elem->data_file_name;
+    index_file_name= part_elem->index_file_name;
+    engine_type= part_elem->engine_type;
+    part_state= part_elem->part_state;
+    nodegroup_id= part_elem->nodegroup_id;
+  }
   ~partition_element() {}
 };
diff --git a/sql/partition_info.cc b/sql/partition_info.cc
index 289296fcac3..e5f8cd7ffac 100644
--- a/sql/partition_info.cc
+++ b/sql/partition_info.cc
@@ -267,7 +267,7 @@ bool partition_info::set_up_default_subpartitions(handler *file,
     j= 0;
     do
     {
-      partition_element *subpart_elem= new partition_element();
+      partition_element *subpart_elem= new partition_element(part_elem);
       if (likely(subpart_elem != 0 &&
           (!part_elem->subpartitions.push_back(subpart_elem))))
       {
@@ -736,6 +736,8 @@ bool partition_info::check_partition_info(handlerton **eng_type,
     do
     {
       partition_element *part_elem= part_it++;
+      if (part_elem->engine_type == NULL)
+        part_elem->engine_type= default_engine_type;
       if (!is_sub_partitioned())
       {
         if (check_table_name(part_elem->partition_name,
@@ -744,8 +746,6 @@ bool partition_info::check_partition_info(handlerton **eng_type,
           my_error(ER_WRONG_PARTITION_NAME, MYF(0));
           goto end;
         }
-        if (part_elem->engine_type == NULL)
-          part_elem->engine_type= default_engine_type;
         DBUG_PRINT("info", ("engine = %d",
                    ha_legacy_type(part_elem->engine_type)));
         engine_array[part_count++]= part_elem->engine_type;
@@ -756,18 +756,18 @@ bool partition_info::check_partition_info(handlerton **eng_type,
         List_iterator<partition_element> sub_it(part_elem->subpartitions);
         do
         {
-          part_elem= sub_it++;
-          if (check_table_name(part_elem->partition_name,
-                               strlen(part_elem->partition_name)))
+          partition_element *sub_elem= sub_it++;
+          if (check_table_name(sub_elem->partition_name,
+                               strlen(sub_elem->partition_name)))
           {
             my_error(ER_WRONG_PARTITION_NAME, MYF(0));
             goto end;
           }
-          if (part_elem->engine_type == NULL)
-            part_elem->engine_type= default_engine_type;
+          if (sub_elem->engine_type == NULL)
+            sub_elem->engine_type= default_engine_type;
           DBUG_PRINT("info", ("engine = %u",
-                     ha_legacy_type(part_elem->engine_type)));
-          engine_array[part_count++]= part_elem->engine_type;
+                     ha_legacy_type(sub_elem->engine_type)));
+          engine_array[part_count++]= sub_elem->engine_type;
         } while (++j < no_subparts);
       }
     } while (++i < no_parts);
diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc
index 716a37f8907..69104ea2ba8 100644
--- a/sql/sql_partition.cc
+++ b/sql/sql_partition.cc
@@ -1754,7 +1754,6 @@ end:
     buf_length                 A pointer to the returned buffer length
     use_sql_alloc              Allocate buffer from sql_alloc if true
                                otherwise use my_malloc
-    write_all                  Write everything, also default values
 
   RETURN VALUES
     NULL error
@@ -1782,8 +1781,7 @@ end:
 
 char *generate_partition_syntax(partition_info *part_info,
                                 uint *buf_length,
-                                bool use_sql_alloc,
-                                bool write_all)
+                                bool use_sql_alloc)
 {
   uint i,j, tot_no_parts, no_subparts, no_parts;
   partition_element *part_elem;
@@ -1865,7 +1863,7 @@ char *generate_partition_syntax(partition_info *part_info,
   tot_no_parts= part_info->partitions.elements;
   no_subparts= part_info->no_subparts;
 
-  if (write_all || (!part_info->use_default_partitions))
+  if (!part_info->use_default_partitions)
   {
     bool first= TRUE;
     err+= add_begin_parenthesis(fptr);
@@ -1886,10 +1884,11 @@ char *generate_partition_syntax(partition_info *part_info,
         err+= add_name_string(fptr, part_elem->partition_name);
         err+= add_space(fptr);
         err+= add_partition_values(fptr, part_info, part_elem);
-        if (!part_info->is_sub_partitioned())
+        if (!part_info->is_sub_partitioned() ||
+            part_info->use_default_subpartitions)
           err+= add_partition_options(fptr, part_elem);
         if (part_info->is_sub_partitioned() &&
-            (write_all || (!part_info->use_default_subpartitions)))
+            (!part_info->use_default_subpartitions))
         {
           err+= add_space(fptr);
           err+= add_begin_parenthesis(fptr);
@@ -3877,6 +3876,7 @@ uint prep_alter_part_table(THD *thd, TABLE *table, ALTER_INFO *alter_info,
         DBUG_RETURN(TRUE);
       }
       alt_part_info->part_type= tab_part_info->part_type;
+      alt_part_info->subpart_type= tab_part_info->subpart_type;
       if (alt_part_info->set_up_defaults_for_partitioning(table->file,
                                                           ULL(0), 
                                                           tab_part_info->no_parts))
@@ -4319,6 +4319,15 @@ state of p1.
         my_error(ER_TOO_MANY_PARTITIONS_ERROR, MYF(0));
         DBUG_RETURN(TRUE);
       }
+      alt_part_info->part_type= tab_part_info->part_type;
+      alt_part_info->subpart_type= tab_part_info->subpart_type;
+      DBUG_ASSERT(!alt_part_info->use_default_partitions);
+      if (alt_part_info->set_up_defaults_for_partitioning(table->file,
+                                                          ULL(0), 
+                                                          0))
+      {
+        DBUG_RETURN(TRUE);
+      }
 /*
 Online handling:
 REORGANIZE PARTITION:
@@ -4455,7 +4464,7 @@ the generated partition syntax in a correct manner.
         tab_part_info->use_default_no_subpartitions= FALSE;
       }
       if (tab_part_info->check_partition_info((handlerton**)NULL,
-                               table->file, ULL(0)))
+                                              table->file, ULL(0)))
       {
         DBUG_RETURN(TRUE);
       }
diff --git a/sql/sql_partition.h b/sql/sql_partition.h
index fd2c474236f..87f9a751ca3 100644
--- a/sql/sql_partition.h
+++ b/sql/sql_partition.h
@@ -69,8 +69,7 @@ bool check_partition_info(partition_info *part_info,handlerton **eng_type,
 bool fix_partition_func(THD *thd, const char *name, TABLE *table,
                         bool create_table_ind);
 char *generate_partition_syntax(partition_info *part_info,
-                                uint *buf_length, bool use_sql_alloc,
-                                bool write_all);
+                                uint *buf_length, bool use_sql_alloc);
 bool partition_key_modified(TABLE *table, List<Item> &fields);
 void get_partition_set(const TABLE *table, byte *buf, const uint index,
                        const key_range *key_spec,
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 06f68e17bf2..16afb1e1a65 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -1326,7 +1326,7 @@ store_create_info(THD *thd, TABLE_LIST *table_list, String *packet,
         (!table->part_info->is_auto_partitioned) &&
         ((part_syntax= generate_partition_syntax(table->part_info,
                                                   &part_syntax_len,
-                                                  FALSE,FALSE))))
+                                                  FALSE))))
     {
        packet->append(part_syntax, part_syntax_len);
        my_free(part_syntax, MYF(0));
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index f39e4e77d70..49a504742e9 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -1231,7 +1231,7 @@ bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags)
       {
         if (!(part_syntax_buf= generate_partition_syntax(part_info,
                                                          &syntax_len,
-                                                         TRUE, FALSE)))
+                                                         TRUE)))
         {
           DBUG_RETURN(TRUE);
         }
@@ -3151,7 +3151,7 @@ bool mysql_create_table_internal(THD *thd,
     */
     if (!(part_syntax_buf= generate_partition_syntax(part_info,
                                                      &syntax_len,
-                                                     TRUE, FALSE)))
+                                                     TRUE)))
       goto err;
     part_info->part_info_string= part_syntax_buf;
     part_info->part_info_len= syntax_len;