=== modified file 'include/my_base.h'
--- include/my_base.h	2009-09-07 20:50:10 +0000
+++ include/my_base.h	2009-11-12 07:35:29 +0000
@@ -314,6 +314,7 @@
 #define HA_OPTION_RELIES_ON_SQL_LAYER   512
 #define HA_OPTION_NULL_FIELDS		1024
 #define HA_OPTION_PAGE_CHECKSUM		2048
+#define HA_OPTION_TEXT_CREATE_OPTIONS   (1 << 14) /* Maria extension */
 #define HA_OPTION_TEMP_COMPRESS_RECORD  (1L << 15)      /* set by isamchk */
 #define HA_OPTION_READ_ONLY_DATA        (1L << 16)      /* Set by isamchk */
 #define HA_OPTION_NO_CHECKSUM           (1L << 17)

=== modified file 'sql/CMakeLists.txt'
--- sql/CMakeLists.txt	2009-09-15 10:46:35 +0000
+++ sql/CMakeLists.txt	2009-11-16 20:21:01 +0000
@@ -76,6 +76,7 @@
                rpl_rli.cc rpl_mi.cc sql_servers.cc
                sql_connect.cc scheduler.cc 
                sql_profile.cc event_parse_data.cc opt_table_elimination.cc
+	       sql_create_options.cc
                ${PROJECT_SOURCE_DIR}/sql/sql_yacc.cc
                ${PROJECT_SOURCE_DIR}/sql/sql_yacc.h
                ${PROJECT_SOURCE_DIR}/include/mysqld_error.h

=== modified file 'sql/Makefile.am'
--- sql/Makefile.am	2009-09-15 10:46:35 +0000
+++ sql/Makefile.am	2009-11-16 20:20:46 +0000
@@ -77,7 +77,7 @@
 			sql_plugin.h authors.h event_parse_data.h \
 			event_data_objects.h event_scheduler.h \
 			sql_partition.h partition_info.h partition_element.h \
-			contributors.h sql_servers.h
+			contributors.h sql_servers.h sql_create_options.h
 
 mysqld_SOURCES =	sql_lex.cc sql_handler.cc sql_partition.cc \
 			item.cc item_sum.cc item_buff.cc item_func.cc \
@@ -122,7 +122,7 @@
 			sql_plugin.cc sql_binlog.cc \
 			sql_builtin.cc sql_tablespace.cc partition_info.cc \
 			sql_servers.cc event_parse_data.cc \
-                        opt_table_elimination.cc
+                        opt_table_elimination.cc sql_create_options.cc
 
 nodist_mysqld_SOURCES =	mini_client_errors.c pack.c client.c my_time.c my_user.c 
 

=== modified file 'sql/handler.cc'
--- sql/handler.cc	2009-09-09 21:06:57 +0000
+++ sql/handler.cc	2009-11-17 13:42:14 +0000
@@ -3585,6 +3585,10 @@
   name= get_canonical_filename(table.file, share.path.str, name_buff);
 
   error= table.file->ha_create(name, &table, create_info);
+
+  create_options_check_unused(thd, db, table_name,
+			      &create_info->create_table_options);
+
   VOID(closefrm(&table, 0));
   if (error)
   {

=== modified file 'sql/handler.h'
--- sql/handler.h	2009-10-15 21:38:29 +0000
+++ sql/handler.h	2009-11-16 22:26:34 +0000
@@ -912,6 +912,7 @@
   LEX_STRING comment;
   const char *data_file_name, *index_file_name;
   const char *alias;
+  TABLE_OPTIONS create_table_options;
   ulonglong max_rows,min_rows;
   ulonglong auto_increment_value;
   ulong table_options;

=== modified file 'sql/mysql_priv.h'
--- sql/mysql_priv.h	2009-10-15 21:52:31 +0000
+++ sql/mysql_priv.h	2009-11-12 07:35:29 +0000
@@ -44,6 +44,9 @@
 #include "sql_plugin.h"
 #include "scheduler.h"
 #include "log_slow.h"
+C_MODE_START
+#include "sql_create_options.h"
+C_MODE_END
 
 class Parser_state;
 

=== modified file 'sql/share/errmsg.txt'
--- sql/share/errmsg.txt	2009-10-15 21:38:29 +0000
+++ sql/share/errmsg.txt	2009-11-17 13:33:19 +0000
@@ -6206,3 +6206,10 @@
 
 WARN_NON_ASCII_SEPARATOR_NOT_IMPLEMENTED
   eng "Non-ASCII separator arguments are not fully supported"
+
+WARN_UNUSED_TABLE_OPTION
+  eng "Unused option '%-.64s' (value '%-.64s') of table '%-.64s'.'%-.64s'"
+WARN_UNUSED_FIELD_OPTION
+  eng "Unused option '%-.64s' (value '%-.64s') of field #%u table '%-.64s'.'%-.64s'"
+WARN_UNUSED_KEY_OPTION
+  eng "Unused option '%-.64s' (value '%-.64s') of key #%u table '%-.64s'.'%-.64s'"

=== modified file 'sql/sql_class.cc'
--- sql/sql_class.cc	2009-09-15 10:46:35 +0000
+++ sql/sql_class.cc	2009-11-17 09:51:48 +0000
@@ -687,6 +687,7 @@
 
 void THD::push_internal_handler(Internal_error_handler *handler)
 {
+  DBUG_ENTER("THD::push_internal_handler");
   if (m_internal_handler)
   {
     handler->m_prev_internal_handler= m_internal_handler;
@@ -696,6 +697,7 @@
   {
     m_internal_handler= handler;
   }
+  DBUG_VOID_RETURN;
 }
 
 
@@ -719,8 +721,10 @@
 
 void THD::pop_internal_handler()
 {
+  DBUG_ENTER("THD::pop_internal_handler");
   DBUG_ASSERT(m_internal_handler != NULL);
   m_internal_handler= m_internal_handler->m_prev_internal_handler;
+  DBUG_VOID_RETURN;
 }
 
 extern "C"

=== added file 'sql/sql_create_options.cc'
--- sql/sql_create_options.cc	1970-01-01 00:00:00 +0000
+++ sql/sql_create_options.cc	2009-11-17 14:03:47 +0000
@@ -0,0 +1,330 @@
+
+#include "mysql_priv.h"
+#include "sql_create_options.h"
+
+static CREATE_OPTION LastOpt;
+
+/**
+  Adds new option to this list
+
+  @param options         pointer to the list
+  @param root            memroot to allocate option
+  @param k               key
+  @param v               value
+
+  @retval TRUE  error
+  @retval FALSE OK
+*/
+
+my_bool create_option_add(CREATE_OPTION **options, MEM_ROOT *root,
+                          const LEX_STRING *k, const LEX_STRING *v)
+{
+  CREATE_OPTION *opt;
+  uchar *key, *val;
+  DBUG_ENTER("create_option_add");
+  DBUG_PRINT("enter", ("key: '%s'  value: '%s'", k->str, v->str));
+
+  if (!multi_alloc_root(root, &opt, sizeof(CREATE_OPTION),
+                        &key, k->length, &val, v->length,
+                        NULL))
+      DBUG_RETURN(TRUE);
+  opt->next= *options;
+  opt->key.str= strncpy((char *)key, (char *)k->str,
+			opt->key.length= k->length);
+  key[k->length]= '\0';
+  opt->key.length= k->length;
+  opt->val.str= strncpy((char *)val, (char *)v->str,
+			opt->val.length= v->length);
+  val[v->length]= '\0';
+  opt->val.length= v->length;
+  opt->used= FALSE;
+  *options= opt;
+  DBUG_RETURN(FALSE);
+}
+
+
+/**
+  Creates empty table create options structure
+
+  @param root            memroot where to allocate memory for this structure
+  @param fields          number of fields
+  @param keys            number of keys
+
+  @return pointer to prepared structure or NULL in case of error.
+*/
+
+TABLE_OPTIONS *create_create_options(MEM_ROOT *root, uint fields, uint keys)
+{
+  CREATE_OPTION **opts;
+  TABLE_OPTIONS *res;
+  DBUG_ENTER("create_create_options");
+  DBUG_PRINT("enter", ("fields: %u  keys: %u", fields, keys));
+
+  if (!multi_alloc_root(root, &res, sizeof(TABLE_OPTIONS),
+                        &opts, sizeof(CREATE_OPTION *) * (fields + keys + 2),
+                        NULL))
+    DBUG_RETURN(NULL);
+
+  bzero((uchar *)opts, sizeof(CREATE_OPTION *) * (fields + keys + 2));
+  res->table_opt= NULL;
+  res->field_opt= opts;
+  res->field_opt[fields]= &LastOpt;
+  res->key_opt= opts + fields + 1;
+  res->key_opt[keys]= &LastOpt;
+  DBUG_RETURN(res);
+}
+
+
+/**
+  Reads options from this buffer
+
+  @param buffer          the buffer to read from
+  @param mem_root        memroot for allocating
+  @param opt             parametes to write to
+
+  @retval TRUE  Error
+  @retval FALSE OK
+*/
+
+my_bool create_options_read(const uchar *buff, uint length, MEM_ROOT *root,
+                            TABLE_OPTIONS *opt)
+{
+  const uchar *buff_end= buff + length;
+  DBUG_ENTER("create_options_read");
+  while (buff < buff_end)
+  {
+    CREATE_OPTION *option=
+      (CREATE_OPTION *) alloc_root(root, sizeof(CREATE_OPTION));
+    uint type;
+    uint index= 0;
+    if (!option)
+      DBUG_RETURN(TRUE);
+    DBUG_ASSERT(buff + 4 <= buff_end);
+    option->val.length= uint2korr(buff);
+    option->key.length= buff[2];
+    type= buff[3];
+    switch (type) {
+    case CREATE_OPTION_FIELD:
+      /* field */
+      index= uint2korr(buff + 4);
+      buff+= 6;
+      option->next= opt->field_opt[index];
+      opt->field_opt[index]= option;
+      break;
+    case CREATE_OPTION_KEY:
+      /* key */
+      index= buff[4];
+      buff+= 5;
+      option->next= opt->key_opt[index];
+      opt->key_opt[index]= option;
+      break;
+    case CREATE_OPTION_TABLE:
+      /* table */
+      buff+= 4;
+      option->next= opt->table_opt;
+      opt->table_opt= option;
+      break;
+    default:
+      DBUG_ASSERT(0);
+    }
+    if (!(option->key.str= (char*) alloc_root(root, option->key.length + 1)) ||
+        !(option->val.str= (char*) alloc_root(root, option->val.length + 1)))
+      DBUG_RETURN(TRUE);
+    strncpy(option->key.str, (const char*)buff, option->key.length);
+    option->key.str[option->key.length]= '\0';
+    buff+= option->key.length;
+    strncpy(option->val.str, (const char*)buff, option->val.length);
+    option->val.str[option->val.length]= '\0';
+    buff+= option->val.length;
+    option->used= FALSE;
+    DBUG_PRINT("info", ("type: %u index: %u  key: '%s'  value: '%s'",
+			(uint) type, (uint) index,
+                        option->key.str, option->val.str));
+  }
+  DBUG_RETURN(FALSE);
+}
+
+/**
+  Calculates length of saved image of the option lists
+
+  @param opt             list of options
+  @param extra_length    type of the record
+
+  @return length
+*/
+
+static ulong create_options_list_length(CREATE_OPTION *opt, int extra_length)
+{
+  ulong res= 0;
+  DBUG_ENTER("create_options_list_length");
+  for (; opt != NULL; opt= opt->next)
+  {
+    DBUG_PRINT("info", ("key: '%s'  value: '%s'",
+			(opt->key.str ? opt->key.str : "<NULL>"),
+			(opt->val.str ? opt->val.str : "<NULL>")));
+    DBUG_ASSERT(opt->key.length);
+    /*
+      length of disk for every record:
+      2 bytes - value length
+      1 byte  - key length
+      1 byte  - record type
+      0/1/2 bytes - none/key number/field number
+    */
+    res+= 2 + 1 + 1 + extra_length + opt->key.length + opt->val.length;
+  }
+  DBUG_RETURN(res);
+}
+
+/**
+  Calculates length of saved image of the all options of the table
+
+  @param opt             table of options
+
+  @return length
+*/
+
+ulong create_options_length(TABLE_OPTIONS *opt)
+{
+  CREATE_OPTION **i;
+  ulong res;
+  DBUG_ENTER("create_options_length");
+
+  res= (opt->table_opt ?
+	create_options_list_length(opt->table_opt, CREATE_OPTION_TABLE):
+	0);
+  if (opt->field_opt)
+  {
+    for (i= opt->field_opt; *i != &LastOpt; i++)
+      res+= create_options_list_length(*i, CREATE_OPTION_FIELD);
+  }
+  if (opt->key_opt)
+  {
+    for (i= opt->key_opt; *i != &LastOpt; i++)
+      res+= create_options_list_length(*i, CREATE_OPTION_KEY);
+  }
+  DBUG_RETURN(res);
+}
+
+
+/**
+  Writes list of options of given type and index to the given file
+
+  @param file            file handler where to write the options
+  @param opt             list of options
+  @param record_type     type of options (table, field, key)
+  @param index           index of option (used by fields and keys)
+
+  @return pointer on the character in the buffer after last written one
+*/
+
+static my_bool create_options_list_write(File file, CREATE_OPTION *opt,
+                                         int record_type, uint index)
+{
+  uchar buffer[4];
+  DBUG_ENTER("create_options_list_write");
+  DBUG_ASSERT(record_type <= 2);
+  for (; opt != NULL; opt= opt->next)
+  {
+    DBUG_PRINT("info", ("type: %u index: %u  key: '%s'  value: '%s'",
+			(uint) record_type, (uint) index,
+                        opt->key.str, opt->val.str));
+    int2store(buffer, opt->val.length);
+    buffer[2]= opt->key.length;
+    buffer[3]= record_type;
+    if (my_write(file, (const uchar*)buffer, 4, MYF_RW))
+      DBUG_RETURN(TRUE);
+    switch (record_type) {
+    case CREATE_OPTION_FIELD:
+      DBUG_ASSERT(index <= 0xffff);
+      int2store(buffer, index);
+      if (my_write(file, (const uchar*)buffer, 2, MYF_RW))
+        DBUG_RETURN(TRUE);
+      break;
+    case CREATE_OPTION_KEY:
+      DBUG_ASSERT(index <= 0xff);
+      buffer[0]= index;
+      if (my_write(file, (const uchar*)buffer, 1, MYF_RW))
+        DBUG_RETURN(TRUE);
+      break;
+    case CREATE_OPTION_TABLE:
+      break;
+    default:
+      DBUG_ASSERT(0); /* impossible */
+    }
+
+    if (my_write(file, (const uchar*)opt->key.str, opt->key.length, MYF_RW) ||
+        my_write(file, (const uchar*)opt->val.str, opt->val.length, MYF_RW))
+        DBUG_RETURN(TRUE);
+  }
+  DBUG_RETURN(FALSE);
+}
+
+
+/**
+  Writes options of the table to the given buffer
+
+  @param file            file handler where to write the options
+  @param opt             table options structure
+*/
+
+my_bool create_options_write(File file, TABLE_OPTIONS *opt)
+{
+  CREATE_OPTION **i;
+  uint index;
+  DBUG_ENTER("create_options_write");
+  if (opt->table_opt &&
+      create_options_list_write(file, opt->table_opt,
+                                CREATE_OPTION_TABLE, 0 /*not used here*/))
+    DBUG_RETURN(TRUE);
+  if (opt->field_opt)
+  {
+    for (i= opt->field_opt, index= 0; *i != &LastOpt; i++, index++)
+    {
+      if (create_options_list_write(file, *i,
+				    CREATE_OPTION_FIELD, index))
+	DBUG_RETURN(TRUE);
+    }
+  }
+  if (opt->key_opt)
+  {
+    for (i= opt->key_opt, index= 0; *i != &LastOpt; i++, index++)
+    {
+      if (create_options_list_write(file, *i,
+				    CREATE_OPTION_KEY, index))
+	DBUG_RETURN(TRUE);
+    }
+  }
+  DBUG_RETURN(FALSE);
+}
+
+
+/**
+  Issue warnings about unused options
+
+  @param thd             thread handler
+  @param db_name:_arg    database name
+  @param table_name      table name
+  @param options         table options structure
+*/
+
+my_bool create_options_check_unused(THD *thd,
+				    const char *db_name,
+				    const char *table_name,
+				    TABLE_OPTIONS *options)
+{
+  CREATE_OPTION *opt;
+  for (opt= options->table_opt; opt != NULL; opt= opt->next)
+  {
+    if (!opt->used)
+    {
+      push_warning_printf(thd,
+			  MYSQL_ERROR::WARN_LEVEL_WARN,
+			  WARN_UNUSED_TABLE_OPTION,
+			  ER(WARN_UNUSED_TABLE_OPTION),
+			  (const char *) opt->key.str,
+			  (const char *) opt->val.str,
+			  db_name, table_name);
+
+    }
+  }
+}

=== added file 'sql/sql_create_options.h'
--- sql/sql_create_options.h	1970-01-01 00:00:00 +0000
+++ sql/sql_create_options.h	2009-11-17 13:46:36 +0000
@@ -0,0 +1,50 @@
+
+#ifndef _SQL_CREATE_OPTIONS_H
+#define _SQL_CREATE_OPTIONS_H
+
+/* types of cretate options records on disk, also it is length of extra data */
+#define CREATE_OPTION_TABLE 0 /* option of table */
+#define CREATE_OPTION_KEY   1 /* option of key */
+#define CREATE_OPTION_FIELD 2 /* option of field */
+
+
+struct st_crete_option {
+  /* pointer to the next option or NULL */
+  struct st_crete_option *next;
+  /* key and value of the option (\0 terminated)*/
+  LEX_STRING key, val;
+  /* used to issue warnings about unused options */
+  my_bool used;
+};
+
+typedef struct st_crete_option CREATE_OPTION;
+
+struct st_table_options {
+  /* table options list */
+  CREATE_OPTION *table_opt;
+  /* fields options array */
+  CREATE_OPTION **field_opt;
+  /* keys options array */
+  CREATE_OPTION **key_opt;
+};
+
+typedef struct st_table_options TABLE_OPTIONS;
+
+TABLE_OPTIONS *create_create_options(MEM_ROOT *root, uint fields, uint keys);
+
+my_bool create_options_read(const uchar *buff, uint length, MEM_ROOT *root,
+                            TABLE_OPTIONS *opt);
+
+my_bool create_option_add(CREATE_OPTION **options, MEM_ROOT *root,
+                          const LEX_STRING *k, const LEX_STRING *v);
+
+ulong create_options_length(TABLE_OPTIONS *opt);
+
+my_bool create_options_write(File file, TABLE_OPTIONS *opt);
+
+my_bool create_options_check_unused(THD *thd,
+				    const char *db_name,
+				    const char *table_name,
+				    TABLE_OPTIONS *options);
+
+#endif

=== modified file 'sql/sql_yacc.yy'
--- sql/sql_yacc.yy	2009-10-15 21:38:29 +0000
+++ sql/sql_yacc.yy	2009-11-16 22:44:55 +0000
@@ -1134,6 +1134,7 @@
         IDENT_sys TEXT_STRING_sys TEXT_STRING_literal
         NCHAR_STRING opt_component key_cache_name
         sp_opt_label BIN_NUM label_ident TEXT_STRING_filesystem ident_or_empty
+        plugin_option_value
 
 %type <lex_str_ptr>
         opt_table_alias
@@ -4557,6 +4558,12 @@
 	    Lex->create_info.used_fields|= HA_CREATE_USED_TRANSACTIONAL;
             Lex->create_info.transactional= $3;
           }
+        | IDENT_sys equal plugin_option_value
+          {
+            create_option_add(&(Lex->
+                                create_info.create_table_options.table_opt),
+                              YYTHD->stmt_arena->mem_root, &$1, &$3);
+          }
         ;
 
 default_charset:
@@ -13590,6 +13597,27 @@
           }
         ;
 
+/**************************************************************************
+
+ Create options
+
+**************************************************************************/
+
+plugin_option_value:
+  DEFAULT
+    {
+      $$.str= NULL; /* We are going to remove the option */
+      $$.length= 0;
+    }
+  | IDENT_sys { $$ = $1; }
+  | TEXT_STRING_sys { $$ = $1; }
+  | DECIMAL_NUM { $$ = $1; }
+  | FLOAT_NUM { $$ = $1; }
+  | NUM { $$ = $1; }
+  | LONG_NUM { $$ = $1; }
+  | HEX_NUM { $$ = $1; }
+
+
 /**
   @} (end of group Parser)
 */

=== modified file 'sql/table.cc'
--- sql/table.cc	2009-10-15 21:38:29 +0000
+++ sql/table.cc	2009-11-17 11:50:38 +0000
@@ -663,12 +663,13 @@
   uint interval_count, interval_parts, read_length, int_length;
   uint db_create_options, keys, key_parts, n_length;
   uint key_info_length, com_length, null_bit_pos;
-  uint extra_rec_buf_length;
+  uint extra_rec_buf_length, options_len;
   uint i,j;
   bool use_hash;
   char *keynames, *names, *comment_pos;
   uchar *record;
-  uchar *disk_buff, *strpos, *null_flags, *null_pos;
+  uchar *disk_buff, *strpos, *null_flags, *null_pos, *options;
+  uchar *buff= 0;
   ulong pos, record_offset, *rec_per_key, rec_buff_length;
   handler *handler_file= 0;
   KEY	*keyinfo;
@@ -853,7 +854,7 @@
   if ((n_length= uint4korr(head+55)))
   {
     /* Read extra data segment */
-    uchar *buff, *next_chunk, *buff_end;
+    uchar *next_chunk, *buff_end;
     DBUG_PRINT("info", ("extra segment size is %u bytes", n_length));
     if (!(next_chunk= buff= (uchar*) my_malloc(n_length, MYF(MY_WME))))
       goto err;
@@ -987,6 +988,17 @@
 #endif
       next_chunk++;
     }
+    if (share->db_create_options & HA_OPTION_TEXT_CREATE_OPTIONS)
+    {
+      /*
+        store options position, but skip till the time we will
+        know number of fields
+      */
+      options_len= uint4korr(next_chunk);
+      options= next_chunk + 4;
+      next_chunk+= options_len;
+      options_len-= 4;
+    }
     keyinfo= share->key_info;
     for (i= 0; i < keys; i++, keyinfo++)
     {
@@ -1013,7 +1025,6 @@
         }
       }
     }
-    my_free(buff, MYF(0));
   }
   share->key_block_size= uint2korr(head+62);
 
@@ -1023,21 +1034,33 @@
   share->rec_buff_length= rec_buff_length;
   if (!(record= (uchar *) alloc_root(&share->mem_root,
                                      rec_buff_length)))
+  {
+    my_free(buff, MYF(MY_ALLOW_ZERO_PTR));
     goto err;                                   /* purecov: inspected */
+  }
   share->default_values= record;
   if (my_pread(file, record, (size_t) share->reclength,
                record_offset, MYF(MY_NABP)))
+  {
+    my_free(buff, MYF(MY_ALLOW_ZERO_PTR));
     goto err;                                   /* purecov: inspected */
+  }
 
   VOID(my_seek(file,pos,MY_SEEK_SET,MYF(0)));
   if (my_read(file, head,288,MYF(MY_NABP)))
+  {
+    my_free(buff, MYF(MY_ALLOW_ZERO_PTR));
     goto err;
+  }
 #ifdef HAVE_CRYPTED_FRM
   if (crypted)
   {
     crypted->decode((char*) head+256,288-256);
     if (sint2korr(head+284) != 0)		// Should be 0
+    {
+      my_free(buff, MYF(MY_ALLOW_ZERO_PTR));
       goto err;                                 // Wrong password
+    }
   }
 #endif
 
@@ -1055,6 +1078,20 @@
 
   DBUG_PRINT("info",("i_count: %d  i_parts: %d  index: %d  n_length: %d  int_length: %d  com_length: %d", interval_count,interval_parts, share->keys,n_length,int_length, com_length));
 
+
+  if (share->db_create_options & HA_OPTION_TEXT_CREATE_OPTIONS)
+  {
+    if (!(share->create_table_options=
+          create_create_options(&share->mem_root, share->fields, keys)) ||
+        create_options_read(options, options_len, &share->mem_root,
+                            share->create_table_options))
+    {
+      my_free(buff, MYF(MY_ALLOW_ZERO_PTR));
+      goto err;
+    }
+  }
+  my_free(buff, MYF(MY_ALLOW_ZERO_PTR));
+
   if (!(field_ptr = (Field **)
 	alloc_root(&share->mem_root,
 		   (uint) ((share->fields+1)*sizeof(Field*)+
@@ -2445,6 +2482,7 @@
   ulong length;
   uchar fill[IO_SIZE];
   int create_flags= O_RDWR | O_TRUNC;
+  DBUG_ENTER("create_frm");
 
   if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
     create_flags|= O_EXCL | O_NOFOLLOW;
@@ -2526,7 +2564,7 @@
       {
 	VOID(my_close(file,MYF(0)));
 	VOID(my_delete(name,MYF(0)));
-	return(-1);
+	DBUG_RETURN(-1);
       }
     }
   }
@@ -2537,7 +2575,7 @@
     else
       my_error(ER_CANT_CREATE_TABLE,MYF(0),table,my_errno);
   }
-  return (file);
+  DBUG_RETURN(file);
 } /* create_frm */
 
 

=== modified file 'sql/table.h'
--- sql/table.h	2009-10-15 21:38:29 +0000
+++ sql/table.h	2009-11-17 08:34:10 +0000
@@ -310,6 +310,7 @@
 #ifdef NOT_YET
   struct st_table *open_tables;		/* link to open tables */
 #endif
+  TABLE_OPTIONS *create_table_options;  /* text options for table */
 
   /* The following is copied to each TABLE on OPEN */
   Field **field;

=== modified file 'sql/unireg.cc'
--- sql/unireg.cc	2009-09-07 20:50:10 +0000
+++ sql/unireg.cc	2009-11-17 11:35:16 +0000
@@ -107,6 +107,7 @@
   ulong key_buff_length;
   File file;
   ulong filepos, data_offset;
+  uint options_len= 0;
   uchar fileinfo[64],forminfo[288],*keybuff;
   TYPELIB formnames;
   uchar *screen_buff;
@@ -124,11 +125,15 @@
     DBUG_RETURN(1);
   DBUG_ASSERT(db_file != NULL);
 
+  DBUG_PRINT("info", ("If fixed row record..."));
+
  /* If fixed row records, we need one bit to check for deleted rows */
   if (!(create_info->table_options & HA_OPTION_PACK_RECORD))
     create_info->null_bits++;
   data_offset= (create_info->null_bits + 7) / 8;
 
+  DBUG_PRINT("info", ("Push..."));
+
   thd->push_internal_handler(&pack_header_error_handler);
 
   error= pack_header(forminfo, ha_legacy_type(create_info->db_type),
@@ -136,6 +141,8 @@
                      screens, create_info->table_options,
                      data_offset, db_file);
 
+  DBUG_PRINT("info", ("Pop..."));
+
   thd->pop_internal_handler();
 
   if (error)
@@ -183,6 +190,16 @@
       create_info->extra_size+= key_info[i].parser_name->length + 1;
   }
 
+  if (create_info->create_table_options.table_opt ||
+      create_info->create_table_options.field_opt ||
+      create_info->create_table_options.key_opt)
+  {
+    create_info->table_options|= HA_OPTION_TEXT_CREATE_OPTIONS;
+    create_info->extra_size+=
+      (options_len= 4 +
+       create_options_length(&create_info->create_table_options));
+  }
+
   if ((file=create_frm(thd, file_name, db, table, reclength, fileinfo,
 		       create_info, keys)) < 0)
   {
@@ -294,6 +311,16 @@
     if (my_write(file, (uchar*) buff, 6, MYF_RW))
       goto err;
   }
+
+  if (options_len)
+  {
+    DBUG_PRINT("info", ("Create options length: %u", options_len));
+    int4store(buff, options_len);
+    if (my_write(file, (const uchar*)buff, 4, MYF_RW) ||
+       create_options_write(file, &create_info->create_table_options))
+      goto err;
+  }
+
   for (i= 0; i < keys; i++)
   {
     if (key_info[i].parser_name)

