struct TABLE_SHARE

struct TABLE_SHARE
{
  TABLE_SHARE() {}                    /* Remove gcc warning */

  /** Category of this table. */
  TABLE_CATEGORY table_category;

  /* hash of field names (contains pointers to elements of field array) */
  HASH    name_hash;            /* hash of field names */
  MEM_ROOT mem_root;
  TYPELIB keynames;            /* Pointers to keynames */
  TYPELIB fieldnames;            /* Pointer to fieldnames */
  TYPELIB *intervals;            /* pointer to interval info */
  mysql_mutex_t LOCK_ha_data;           /* To protect access to ha_data */
  TABLE_SHARE *next, **prev;            /* Link to unused shares */

  /*
    Doubly-linked (back-linked) lists of used and unused TABLE objects
    for this share.
  */
  I_P_List <TABLE, TABLE_share> used_tables;
  I_P_List <TABLE, TABLE_share> free_tables;

  /* The following is copied to each TABLE on OPEN */
  Field **field;
  Field **found_next_number_field;
  Field *timestamp_field;               /* Used only during open */
  KEY  *key_info;            /* data of keys in database */
  uint    *blob_field;            /* Index to blobs in Field arrray*/

  uchar    *default_values;        /* row with default values */
  LEX_STRING comment;            /* Comment about table */
  CHARSET_INFO *table_charset;        /* Default charset of string fields */

  MY_BITMAP all_set;
  /*
    Key which is used for looking-up table in table cache and in the list
    of thread's temporary tables. Has the form of:
      "database_name\0table_name\0" + optional part for temporary tables.

    Note that all three 'table_cache_key', 'db' and 'table_name' members
    must be set (and be non-zero) for tables in table cache. They also
    should correspond to each other.
    To ensure this one can use set_table_cache() methods.
  */
  LEX_STRING table_cache_key;
  LEX_STRING db;                        /* Pointer to db */
  LEX_STRING table_name;                /* Table name (for open) */
  LEX_STRING path;                    /* Path to .frm file (from datadir) */
  LEX_STRING normalized_path;        /* unpack_filename(path) */
  LEX_STRING connect_string;

  /*
     Set of keys in use, implemented as a Bitmap.
     Excludes keys disabled by ALTER TABLE ... DISABLE KEYS.
  */
  key_map keys_in_use;
  key_map keys_for_keyread;
  ha_rows min_rows, max_rows;        /* create information */
  ulong   avg_row_length;        /* create information */
  ulong   version, mysql_version;
  ulong   reclength;            /* Recordlength */

  plugin_ref db_plugin;            /* storage engine plugin */
  inline handlerton *db_type() const    /* table_type for handler */
  {
    // DBUG_ASSERT(db_plugin);
    return db_plugin ? plugin_data(db_plugin, handlerton*) : NULL;
  }
  enum row_type row_type;        /* How rows are stored */
  enum tmp_table_type tmp_table;

  uint ref_count;                       /* How many TABLE objects uses this */
  uint blob_ptr_size;            /* 4 or 8 */
  uint key_block_size;            /* create key_block_size, if used */
  uint null_bytes, last_null_bit_pos;
  uint fields;                /* Number of fields */
  uint rec_buff_length;                 /* Size of table->record[] buffer */
  uint keys, key_parts;
  uint max_key_length, max_unique_length, total_key_length;
  uint uniques;                         /* Number of UNIQUE index */
  uint null_fields;            /* number of null fields */
  uint blob_fields;            /* number of blob fields */
  uint timestamp_field_offset;        /* Field number for timestamp field */
  uint varchar_fields;                  /* number of varchar fields */
  uint db_create_options;        /* Create options from database */
  uint db_options_in_use;        /* Options in use */
  uint db_record_offset;        /* if HA_REC_IN_SEQ */
  uint rowid_field_offset;        /* Field_nr +1 to rowid field */
  /* Primary key index number, used in TABLE::key_info[] */
  uint primary_key;
  uint next_number_index;               /* autoincrement key number */
  uint next_number_key_offset;          /* autoinc keypart offset in a key */
  uint next_number_keypart;             /* autoinc keypart number in a key */
  uint error, open_errno, errarg;       /* error from open_table_def() */
  uint column_bitmap_size;
  uchar frm_version;
  bool null_field_first;
  bool system;                          /* Set if system table (one record) */
  bool crypted;                         /* If .frm file is crypted */
  bool db_low_byte_first;        /* Portable row format */
  bool crashed;
  bool is_view;
  ulong table_map_id;                   /* for row-based replication */

  /*
    Cache for row-based replication table share checks that does not
    need to be repeated. Possible values are: -1 when cache value is
    not calculated yet, 0 when table *shall not* be replicated, 1 when
    table *may* be replicated.
  */
  int cached_row_logging_check;

  /*
    Storage media to use for this table (unless another storage
    media has been specified on an individual column - in versions
    where that is supported)
  */
  enum ha_storage_media default_storage_media;

  /* Name of the tablespace used for this table */
  char *tablespace;

#ifdef WITH_PARTITION_STORAGE_ENGINE
  /* filled in when reading from frm */
  bool auto_partitioned;
  char *partition_info_str;
  uint  partition_info_str_len;
  uint  partition_info_buffer_size;
  handlerton *default_part_db_type;
#endif

  /**
    Cache the checked structure of this table.

    The pointer data is used to describe the structure that
    a instance of the table must have. Each element of the
    array specifies a field that must exist on the table.

    The pointer is cached in order to perform the check only
    once -- when the table is loaded from the disk.
  */
  const TABLE_FIELD_DEF *table_field_def_cache;

  /** place to store storage engine specific data */
  void *ha_data;
  void (*ha_data_destroy)(void *); /* An optional destructor for ha_data */

#ifdef WITH_PARTITION_STORAGE_ENGINE
  /** place to store partition specific data, LOCK_ha_data hold while init. */
  HA_DATA_PARTITION *ha_part_data;
  /* Destructor for ha_part_data */
  void (*ha_part_data_destroy)(HA_DATA_PARTITION *);
#endif

  /** Instrumentation for this table share. */
  PSI_table_share *m_psi;

  /**
    List of tickets representing threads waiting for the share to be flushed.
  */
  Wait_for_flush_list m_flush_tickets;

  /*
    Set share's table cache key and update its db and table name appropriately.

    SYNOPSIS
      set_table_cache_key()
        key_buff    Buffer with already built table cache key to be
                    referenced from share.
        key_length  Key length.

    NOTES
      Since 'key_buff' buffer will be referenced from share it should has same
      life-time as share itself.
      This method automatically ensures that TABLE_SHARE::table_name/db have
      appropriate values by using table cache key as their source.
  */

  void set_table_cache_key(char *key_buff, uint key_length)
  {
    table_cache_key.str= key_buff;
    table_cache_key.length= key_length;
    /*
      Let us use the fact that the key is "db/0/table_name/0" + optional
      part for temporary tables.
    */
    db.str=            table_cache_key.str;
    db.length=         strlen(db.str);
    table_name.str=    db.str + db.length + ;
    table_name.length= strlen(table_name.str);
  }

  /*
    Set share's table cache key and update its db and table name appropriately.

    SYNOPSIS
      set_table_cache_key()
        key_buff    Buffer to be used as storage for table cache key
                    (should be at least key_length bytes).
        key         Value for table cache key.
        key_length  Key length.

    NOTE
      Since 'key_buff' buffer will be used as storage for table cache key
      it should has same life-time as share itself.
  */

  void set_table_cache_key(char *key_buff, const char *key, uint key_length)
  {
    memcpy(key_buff, key, key_length);
    set_table_cache_key(key_buff, key_length);
  }

  inline bool honor_global_locks()
  {
    return ((table_category == TABLE_CATEGORY_USER)
            || (table_category == TABLE_CATEGORY_SYSTEM));
  }

  inline bool require_write_privileges()
  {
    return (table_category == TABLE_CATEGORY_LOG);
  }

  inline ulong get_table_def_version()
  {
    return table_map_id;
  }

  /** Is this table share being expelled from the table definition cache?  */
  inline bool has_old_version() const
  {
    return version != refresh_version;
  }
  /**
    Convert unrelated members of TABLE_SHARE to one enum
    representing its type.

    @todo perhaps we need to have a member instead of a function.
  */
  enum enum_table_ref_type get_table_ref_type() const
  {
    if (is_view)
      return TABLE_REF_VIEW;
    switch (tmp_table) {
    case NO_TMP_TABLE:
      return TABLE_REF_BASE_TABLE;
    case SYSTEM_TMP_TABLE:
      return TABLE_REF_I_S_TABLE;
    default:
      return TABLE_REF_TMP_TABLE;
    }
  }
  /**
    Return a table metadata version.
     * for base tables, we return table_map_id.
       It is assigned from a global counter incremented for each
       new table loaded into the table definition cache (TDC).
     * for temporary tables it's table_map_id again. But for
       temporary tables table_map_id is assigned from
       thd->query_id. The latter is assigned from a thread local
       counter incremented for every new SQL statement. Since
       temporary tables are thread-local, each temporary table
       gets a unique id.
     * for everything else (views, information schema tables),
       the version id is zero.

   This choice of version id is a large compromise
   to have a working prepared statement validation in 5.1. In
   future version ids will be persistent, as described in WL#4180.

   Let's try to explain why and how this limited solution allows
   to validate prepared statements.

   Firstly, sets (in mathematical sense) of version numbers
   never intersect for different table types. Therefore,
   version id of a temporary table is never compared with
   a version id of a view, and vice versa.

   Secondly, for base tables, we know that each DDL flushes the
   respective share from the TDC. This ensures that whenever
   a table is altered or dropped and recreated, it gets a new
   version id.
   Unfortunately, since elements of the TDC are also flushed on
   LRU basis, this choice of version ids leads to false positives.
   E.g. when the TDC size is too small, we may have a SELECT
   * FROM INFORMATION_SCHEMA.TABLES flush all its elements, which
   in turn will lead to a validation error and a subsequent
   reprepare of all prepared statements.  This is
   considered acceptable, since as long as prepared statements are
   automatically reprepared, spurious invalidation is only
   a performance hit. Besides, no better simple solution exists.

   For temporary tables, using thd->query_id ensures that if
   a temporary table was altered or recreated, a new version id is
   assigned. This suits validation needs very well and will perhaps
   never change.

   Metadata of information schema tables never changes.
   Thus we can safely assume 0 for a good enough version id.

   Views are a special and tricky case. A view is always inlined
   into the parse tree of a prepared statement at prepare.
   Thus, when we execute a prepared statement, the parse tree
   will not get modified even if the view is replaced with another
   view.  Therefore, we can safely choose 0 for version id of
   views and effectively never invalidate a prepared statement
   when a view definition is altered. Note, that this leads to
   wrong binary log in statement-based replication, since we log
   prepared statement execution in form Query_log_events
   containing conventional statements. But since there is no
   metadata locking for views, the very same problem exists for
   conventional statements alone, as reported in Bug#25144. The only
   difference between prepared and conventional execution is,
   effectively, that for prepared statements the race condition
   window is much wider.
   In 6.0 we plan to support view metadata locking (WL#3726) and
   extend table definition cache to cache views (WL#4298).
   When this is done, views will be handled in the same fashion
   as the base tables.

   Finally, by taking into account table type, we always
   track that a change has taken place when a view is replaced
   with a base table, a base table is replaced with a temporary
   table and so on.

   @sa TABLE_LIST::is_table_ref_id_equal()
  */
  ulong get_table_ref_version() const
  {
     : table_map_id;
  }

  bool visit_subgraph(Wait_for_flush *waiting_ticket,
                      MDL_wait_for_graph_visitor *gvisitor);

  bool wait_for_old_version(THD *thd, struct timespec *abstime,
                            uint deadlock_weight);
  /** Release resources and free memory occupied by the table share. */
  void destroy();
};
上一篇:Swift学习笔记八


下一篇:Hibernate之继承映射