My Project
ha_partition.h
00001 #ifndef HA_PARTITION_INCLUDED
00002 #define HA_PARTITION_INCLUDED
00003 
00004 /*
00005    Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
00006 
00007    This program is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License as published by
00009    the Free Software Foundation; version 2 of the License.
00010 
00011    This program is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014    GNU General Public License for more details.
00015 
00016    You should have received a copy of the GNU General Public License
00017    along with this program; if not, write to the Free Software
00018    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
00019 
00020 #include "sql_partition.h"      /* part_id_range, partition_element */
00021 #include "queues.h"             /* QUEUE */
00022 
00023 enum partition_keywords
00024 {
00025   PKW_HASH= 0, PKW_RANGE, PKW_LIST, PKW_KEY, PKW_MAXVALUE, PKW_LINEAR,
00026   PKW_COLUMNS, PKW_ALGORITHM
00027 };
00028 
00029 
00030 #define PARTITION_BYTES_IN_POS 2
00031 
00032 
00034 typedef struct st_part_name_def
00035 {
00036   uchar *partition_name;
00037   uint length;
00038   uint32 part_id;
00039   my_bool is_subpart;
00040 } PART_NAME_DEF;
00041 
00043 class Parts_share_refs
00044 {
00045 public:
00046   uint num_parts;                              
00047   Handler_share **ha_shares;                   
00048   Parts_share_refs()
00049   {
00050     num_parts= 0;
00051     ha_shares= NULL;
00052   }
00053   ~Parts_share_refs()
00054   {
00055     uint i;
00056     for (i= 0; i < num_parts; i++)
00057       if (ha_shares[i])
00058         delete ha_shares[i];
00059     if (ha_shares)
00060       delete [] ha_shares;
00061   }
00062   bool init(uint arg_num_parts)
00063   {
00064     DBUG_ASSERT(!num_parts && !ha_shares);
00065     num_parts= arg_num_parts;
00066     /* Allocate an array of Handler_share pointers */
00067     ha_shares= new Handler_share *[num_parts];
00068     if (!ha_shares)
00069     {
00070       num_parts= 0;
00071       return true;
00072     }
00073     memset(ha_shares, 0, sizeof(Handler_share*) * num_parts);
00074     return false;
00075   }
00076 };
00077 
00078 
00082 class Partition_share : public Handler_share
00083 {
00084 public:
00085   bool auto_inc_initialized;
00086   mysql_mutex_t auto_inc_mutex;                
00087   ulonglong next_auto_inc_val;                 
00092   bool partition_name_hash_initialized;
00093   HASH partition_name_hash;
00095   Parts_share_refs *partitions_share_refs;
00096   Partition_share() {}
00097   ~Partition_share()
00098   {
00099     DBUG_ENTER("Partition_share::~Partition_share");
00100     mysql_mutex_destroy(&auto_inc_mutex);
00101     if (partition_name_hash_initialized)
00102       my_hash_free(&partition_name_hash);
00103     if (partitions_share_refs)
00104       delete partitions_share_refs;
00105     DBUG_VOID_RETURN;
00106   }
00107   bool init(uint num_parts);
00108   void lock_auto_inc()
00109   {
00110     mysql_mutex_lock(&auto_inc_mutex);
00111   }
00112   void unlock_auto_inc()
00113   {
00114     mysql_mutex_unlock(&auto_inc_mutex);
00115   }
00116 };
00117 
00118 
00119 class ha_partition :public handler
00120 {
00121 private:
00122   enum partition_index_scan_type
00123   {
00124     partition_index_read= 0,
00125     partition_index_first= 1,
00126     partition_index_first_unordered= 2,
00127     partition_index_last= 3,
00128     partition_index_read_last= 4,
00129     partition_read_range = 5,
00130     partition_no_index_scan= 6
00131   };
00132   /* Data for the partition handler */
00133   int  m_mode;                          // Open mode
00134   uint m_open_test_lock;                // Open test_if_locked
00135   char *m_file_buffer;                  // Content of the .par file 
00136   char *m_name_buffer_ptr;              // Pointer to first partition name
00137   plugin_ref *m_engine_array;           // Array of types of the handlers
00138   handler **m_file;                     // Array of references to handler inst.
00139   uint m_file_tot_parts;                // Debug
00140   handler **m_new_file;                 // Array of references to new handlers
00141   handler **m_reorged_file;             // Reorganised partitions
00142   handler **m_added_file;               // Added parts kept for errors
00143   partition_info *m_part_info;          // local reference to partition
00144   Field **m_part_field_array;           // Part field array locally to save acc
00145   uchar *m_ordered_rec_buffer;          // Row and key buffer for ord. idx scan
00155   KEY *m_curr_key_info[3];
00157   uint m_rec_offset;
00158   uchar *m_rec0;                        // table->record[0]
00159   const uchar *m_err_rec;               // record which gave error
00160   QUEUE m_queue;                        // Prio queue used by sorted read
00161   /*
00162     Since the partition handler is a handler on top of other handlers, it
00163     is necessary to keep information about what the underlying handler
00164     characteristics is. It is not possible to keep any handler instances
00165     for this since the MySQL Server sometimes allocating the handler object
00166     without freeing them.
00167   */
00168   ulong m_low_byte_first;
00169   enum enum_handler_status
00170   {
00171     handler_not_initialized= 0,
00172     handler_initialized,
00173     handler_opened,
00174     handler_closed
00175   };
00176   enum_handler_status m_handler_status;
00177 
00178   uint m_reorged_parts;                  // Number of reorganised parts
00179   uint m_tot_parts;                      // Total number of partitions;
00180   uint m_num_locks;                       // For engines like ha_blackhole, which needs no locks
00181   uint m_last_part;                      // Last file that we update,write,read
00182   part_id_range m_part_spec;             // Which parts to scan
00183   uint m_scan_value;                     // Value passed in rnd_init
00184                                          // call
00185   uint m_ref_length;                     // Length of position in this
00186                                          // handler object
00187   key_range m_start_key;                 // index read key range
00188   enum partition_index_scan_type m_index_scan_type;// What type of index
00189                                                    // scan
00190   uint m_top_entry;                      // Which partition is to
00191                                          // deliver next result
00192   uint m_rec_length;                     // Local copy of record length
00193 
00194   bool m_ordered;                        // Ordered/Unordered index scan
00195   bool m_pkey_is_clustered;              // Is primary key clustered
00196   bool m_create_handler;                 // Handler used to create table
00197   bool m_is_sub_partitioned;             // Is subpartitioned
00198   bool m_ordered_scan_ongoing;
00199 
00200   /* 
00201     If set, this object was created with ha_partition::clone and doesn't
00202     "own" the m_part_info structure.
00203   */
00204   ha_partition *m_is_clone_of;
00205   MEM_ROOT *m_clone_mem_root;
00206   
00207   /*
00208     We keep track if all underlying handlers are MyISAM since MyISAM has a
00209     great number of extra flags not needed by other handlers.
00210   */
00211   bool m_myisam;                         // Are all underlying handlers
00212                                          // MyISAM
00213   /*
00214     We keep track of InnoDB handlers below since it requires proper setting
00215     of query_id in fields at index_init and index_read calls.
00216   */
00217   bool m_innodb;                        // Are all underlying handlers
00218                                         // InnoDB
00219   /*
00220     When calling extra(HA_EXTRA_CACHE) we do not pass this to the underlying
00221     handlers immediately. Instead we cache it and call the underlying
00222     immediately before starting the scan on the partition. This is to
00223     prevent allocating a READ CACHE for each partition in parallel when
00224     performing a full table scan on MyISAM partitioned table.
00225     This state is cleared by extra(HA_EXTRA_NO_CACHE).
00226   */
00227   bool m_extra_cache;
00228   uint m_extra_cache_size;
00229   /* The same goes for HA_EXTRA_PREPARE_FOR_UPDATE */
00230   bool m_extra_prepare_for_update;
00231   /* Which partition has active cache */
00232   uint m_extra_cache_part_id;
00233 
00234   void init_handler_variables();
00235   /*
00236     Variables for lock structures.
00237   */
00238   THR_LOCK_DATA lock;                   /* MySQL lock */
00239 
00240   bool auto_increment_lock;             
00245   bool auto_increment_safe_stmt_log_lock;
00247   MY_BITMAP m_bulk_insert_started;
00248   ha_rows   m_bulk_inserted_rows;
00250   enum_monotonicity_info m_part_func_monotonicity_info;
00252   MY_BITMAP m_locked_partitions;
00254   Partition_share *part_share;
00256   List<Parts_share_refs> m_new_partitions_share_refs;
00258   uint32 *m_part_ids_sorted_by_num_of_records;
00259   /* Compare function for my_qsort2, for reversed order. */
00260   static int compare_number_of_records(ha_partition *me,
00261                                        const uint32 *a,
00262                                        const uint32 *b);
00264   MY_BITMAP m_partitions_to_reset;
00266   MY_BITMAP m_key_not_found_partitions;
00267   bool m_key_not_found;
00269   bool m_sec_sort_by_rowid;
00270 public:
00271   Partition_share *get_part_share() { return part_share; }
00272   handler *clone(const char *name, MEM_ROOT *mem_root);
00273   virtual void set_part_info(partition_info *part_info, bool early)
00274   {
00275      m_part_info= part_info;
00276      m_is_sub_partitioned= part_info->is_sub_partitioned();
00277   }
00278   /*
00279     -------------------------------------------------------------------------
00280     MODULE create/delete handler object
00281     -------------------------------------------------------------------------
00282     Object create/delete methode. The normal called when a table object
00283     exists. There is also a method to create the handler object with only
00284     partition information. This is used from mysql_create_table when the
00285     table is to be created and the engine type is deduced to be the
00286     partition handler.
00287     -------------------------------------------------------------------------
00288   */
00289     ha_partition(handlerton *hton, TABLE_SHARE * table);
00290     ha_partition(handlerton *hton, partition_info * part_info);
00291     ha_partition(handlerton *hton, TABLE_SHARE *share,
00292                  partition_info *part_info_arg,
00293                  ha_partition *clone_arg,
00294                  MEM_ROOT *clone_mem_root_arg);
00295    ~ha_partition();
00296   /*
00297     A partition handler has no characteristics in itself. It only inherits
00298     those from the underlying handlers. Here we set-up those constants to
00299     enable later calls of the methods to retrieve constants from the under-
00300     lying handlers. Returns false if not successful.
00301   */
00302    bool initialize_partition(MEM_ROOT *mem_root);
00303 
00304   /*
00305     -------------------------------------------------------------------------
00306     MODULE meta data changes
00307     -------------------------------------------------------------------------
00308     Meta data routines to CREATE, DROP, RENAME table and often used at
00309     ALTER TABLE (update_create_info used from ALTER TABLE and SHOW ..).
00310 
00311     update_table_comment is used in SHOW TABLE commands to provide a
00312     chance for the handler to add any interesting comments to the table
00313     comments not provided by the users comment.
00314 
00315     create_handler_files is called before opening a new handler object
00316     with openfrm to call create. It is used to create any local handler
00317     object needed in opening the object in openfrm
00318     -------------------------------------------------------------------------
00319   */
00320   virtual int delete_table(const char *from);
00321   virtual int rename_table(const char *from, const char *to);
00322   virtual int create(const char *name, TABLE *form,
00323                      HA_CREATE_INFO *create_info);
00324   virtual int create_handler_files(const char *name,
00325                                    const char *old_name, int action_flag,
00326                                    HA_CREATE_INFO *create_info);
00327   virtual void update_create_info(HA_CREATE_INFO *create_info);
00328   virtual char *update_table_comment(const char *comment);
00329   virtual int change_partitions(HA_CREATE_INFO *create_info,
00330                                 const char *path,
00331                                 ulonglong * const copied,
00332                                 ulonglong * const deleted,
00333                                 const uchar *pack_frm_data,
00334                                 size_t pack_frm_len);
00335   virtual int drop_partitions(const char *path);
00336   virtual int rename_partitions(const char *path);
00337   bool get_no_parts(const char *name, uint *num_parts)
00338   {
00339     DBUG_ENTER("ha_partition::get_no_parts");
00340     *num_parts= m_tot_parts;
00341     DBUG_RETURN(0);
00342   }
00343   virtual void change_table_ptr(TABLE *table_arg, TABLE_SHARE *share);
00344   virtual bool check_if_incompatible_data(HA_CREATE_INFO *create_info,
00345                                           uint table_changes);
00346 private:
00347   int copy_partitions(ulonglong * const copied, ulonglong * const deleted);
00348   void cleanup_new_partition(uint part_count);
00349   int prepare_new_partition(TABLE *table, HA_CREATE_INFO *create_info,
00350                             handler *file, const char *part_name,
00351                             partition_element *p_elem,
00352                             uint disable_non_uniq_indexes);
00353   /*
00354     delete_table and rename_table uses very similar logic which
00355     is packed into this routine.
00356   */
00357   int del_ren_table(const char *from, const char *to);
00358   /*
00359     One method to create the table_name.par file containing the names of the
00360     underlying partitions, their engine and the number of partitions.
00361     And one method to read it in.
00362   */
00363   bool create_handler_file(const char *name);
00364   bool setup_engine_array(MEM_ROOT *mem_root);
00365   bool read_par_file(const char *name);
00366   bool get_from_handler_file(const char *name, MEM_ROOT *mem_root,
00367                              bool is_clone);
00368   bool new_handlers_from_part_info(MEM_ROOT *mem_root);
00369   bool create_handlers(MEM_ROOT *mem_root);
00370   void clear_handler_file();
00371   int set_up_table_before_create(TABLE *table_arg,
00372                                  const char *partition_name_with_path,
00373                                  HA_CREATE_INFO *info,
00374                                  partition_element *p_elem);
00375   partition_element *find_partition_element(uint part_id);
00376   bool insert_partition_name_in_hash(const char *name, uint part_id,
00377                                      bool is_subpart);
00378   bool populate_partition_name_hash();
00379   Partition_share *get_share();
00380   bool set_ha_share_ref(Handler_share **ha_share);
00381   void fix_data_dir(char* path);
00382   bool init_partition_bitmaps();
00383   void free_partition_bitmaps();
00384 
00385 public:
00386 
00387   /*
00388     -------------------------------------------------------------------------
00389     MODULE open/close object
00390     -------------------------------------------------------------------------
00391     Open and close handler object to ensure all underlying files and
00392     objects allocated and deallocated for query handling is handled
00393     properly.
00394     -------------------------------------------------------------------------
00395 
00396     A handler object is opened as part of its initialisation and before
00397     being used for normal queries (not before meta-data changes always.
00398     If the object was opened it will also be closed before being deleted.
00399   */
00400   virtual int open(const char *name, int mode, uint test_if_locked);
00401   virtual int close(void);
00402 
00403   /*
00404     -------------------------------------------------------------------------
00405     MODULE start/end statement
00406     -------------------------------------------------------------------------
00407     This module contains methods that are used to understand start/end of
00408     statements, transaction boundaries, and aid for proper concurrency
00409     control.
00410     The partition handler need not implement abort and commit since this
00411     will be handled by any underlying handlers implementing transactions.
00412     There is only one call to each handler type involved per transaction
00413     and these go directly to the handlers supporting transactions
00414     currently InnoDB, BDB and NDB).
00415     -------------------------------------------------------------------------
00416   */
00417   virtual THR_LOCK_DATA **store_lock(THD * thd, THR_LOCK_DATA ** to,
00418                                      enum thr_lock_type lock_type);
00419   virtual int external_lock(THD * thd, int lock_type);
00420   /*
00421     When table is locked a statement is started by calling start_stmt
00422     instead of external_lock
00423   */
00424   virtual int start_stmt(THD * thd, thr_lock_type lock_type);
00425   /*
00426     Lock count is number of locked underlying handlers (I assume)
00427   */
00428   virtual uint lock_count(void) const;
00429   /*
00430     Call to unlock rows not to be updated in transaction
00431   */
00432   virtual void unlock_row();
00433   /*
00434     Check if semi consistent read
00435   */
00436   virtual bool was_semi_consistent_read();
00437   /*
00438     Call to hint about semi consistent read
00439   */
00440   virtual void try_semi_consistent_read(bool);
00441 
00442   /*
00443     NOTE: due to performance and resource issues with many partitions,
00444     we only use the m_psi on the ha_partition handler, excluding all
00445     partitions m_psi.
00446   */
00447 #ifdef HAVE_M_PSI_PER_PARTITION
00448   /*
00449     Bind the table/handler thread to track table i/o.
00450   */
00451   virtual void unbind_psi();
00452   virtual void rebind_psi();
00453 #endif
00454   /*
00455     -------------------------------------------------------------------------
00456     MODULE change record
00457     -------------------------------------------------------------------------
00458     This part of the handler interface is used to change the records
00459     after INSERT, DELETE, UPDATE, REPLACE method calls but also other
00460     special meta-data operations as ALTER TABLE, LOAD DATA, TRUNCATE.
00461     -------------------------------------------------------------------------
00462 
00463     These methods are used for insert (write_row), update (update_row)
00464     and delete (delete_row). All methods to change data always work on
00465     one row at a time. update_row and delete_row also contains the old
00466     row.
00467     delete_all_rows will delete all rows in the table in one call as a
00468     special optimisation for DELETE from table;
00469 
00470     Bulk inserts are supported if all underlying handlers support it.
00471     start_bulk_insert and end_bulk_insert is called before and after a
00472     number of calls to write_row.
00473   */
00474   virtual int write_row(uchar * buf);
00475   virtual int update_row(const uchar * old_data, uchar * new_data);
00476   virtual int delete_row(const uchar * buf);
00477   virtual int delete_all_rows(void);
00478   virtual int truncate();
00479   virtual void start_bulk_insert(ha_rows rows);
00480   virtual int end_bulk_insert();
00481 private:
00482   ha_rows guess_bulk_insert_rows();
00483   void start_part_bulk_insert(THD *thd, uint part_id);
00484   long estimate_read_buffer_size(long original_size);
00485 public:
00486 
00487   /*
00488     Method for truncating a specific partition.
00489     (i.e. ALTER TABLE t1 TRUNCATE PARTITION p).
00490 
00491     @remark This method is a partitioning-specific hook
00492             and thus not a member of the general SE API.
00493   */
00494   int truncate_partition(Alter_info *, bool *binlog_stmt);
00495 
00496   virtual bool is_fatal_error(int error, uint flags)
00497   {
00498     if (!handler::is_fatal_error(error, flags) ||
00499         error == HA_ERR_NO_PARTITION_FOUND ||
00500         error == HA_ERR_NOT_IN_LOCK_PARTITIONS)
00501       return FALSE;
00502     return TRUE;
00503   }
00504 
00505 
00506   /*
00507     -------------------------------------------------------------------------
00508     MODULE full table scan
00509     -------------------------------------------------------------------------
00510     This module is used for the most basic access method for any table
00511     handler. This is to fetch all data through a full table scan. No
00512     indexes are needed to implement this part.
00513     It contains one method to start the scan (rnd_init) that can also be
00514     called multiple times (typical in a nested loop join). Then proceeding
00515     to the next record (rnd_next) and closing the scan (rnd_end).
00516     To remember a record for later access there is a method (position)
00517     and there is a method used to retrieve the record based on the stored
00518     position.
00519     The position can be a file position, a primary key, a ROWID dependent
00520     on the handler below.
00521     -------------------------------------------------------------------------
00522   */
00523   /*
00524     unlike index_init(), rnd_init() can be called two times
00525     without rnd_end() in between (it only makes sense if scan=1).
00526     then the second call should prepare for the new table scan
00527     (e.g if rnd_init allocates the cursor, second call should
00528     position it to the start of the table, no need to deallocate
00529     and allocate it again
00530   */
00531   virtual int rnd_init(bool scan);
00532   virtual int rnd_end();
00533   virtual int rnd_next(uchar * buf);
00534   virtual int rnd_pos(uchar * buf, uchar * pos);
00535   virtual int rnd_pos_by_record(uchar *record);
00536   virtual void position(const uchar * record);
00537 
00538   /*
00539     -------------------------------------------------------------------------
00540     MODULE index scan
00541     -------------------------------------------------------------------------
00542     This part of the handler interface is used to perform access through
00543     indexes. The interface is defined as a scan interface but the handler
00544     can also use key lookup if the index is a unique index or a primary
00545     key index.
00546     Index scans are mostly useful for SELECT queries but are an important
00547     part also of UPDATE, DELETE, REPLACE and CREATE TABLE table AS SELECT
00548     and so forth.
00549     Naturally an index is needed for an index scan and indexes can either
00550     be ordered, hash based. Some ordered indexes can return data in order
00551     but not necessarily all of them.
00552     There are many flags that define the behavior of indexes in the
00553     various handlers. These methods are found in the optimizer module.
00554     -------------------------------------------------------------------------
00555 
00556     index_read is called to start a scan of an index. The find_flag defines
00557     the semantics of the scan. These flags are defined in
00558     include/my_base.h
00559     index_read_idx is the same but also initializes index before calling doing
00560     the same thing as index_read. Thus it is similar to index_init followed
00561     by index_read. This is also how we implement it.
00562 
00563     index_read/index_read_idx does also return the first row. Thus for
00564     key lookups, the index_read will be the only call to the handler in
00565     the index scan.
00566 
00567     index_init initializes an index before using it and index_end does
00568     any end processing needed.
00569   */
00570   virtual int index_read_map(uchar * buf, const uchar * key,
00571                              key_part_map keypart_map,
00572                              enum ha_rkey_function find_flag);
00573   virtual int index_init(uint idx, bool sorted);
00574   virtual int index_end();
00575 
00582   virtual int index_read_idx_map(uchar *buf, uint index, const uchar *key,
00583                                  key_part_map keypart_map,
00584                                  enum ha_rkey_function find_flag);
00585   /*
00586     These methods are used to jump to next or previous entry in the index
00587     scan. There are also methods to jump to first and last entry.
00588   */
00589   virtual int index_next(uchar * buf);
00590   virtual int index_prev(uchar * buf);
00591   virtual int index_first(uchar * buf);
00592   virtual int index_last(uchar * buf);
00593   virtual int index_next_same(uchar * buf, const uchar * key, uint keylen);
00594   virtual int index_read_last_map(uchar * buf, const uchar * key,
00595                                   key_part_map keypart_map);
00596 
00597   /*
00598     read_first_row is virtual method but is only implemented by
00599     handler.cc, no storage engine has implemented it so neither
00600     will the partition handler.
00601     
00602     virtual int read_first_row(uchar *buf, uint primary_key);
00603   */
00604 
00605   /*
00606     We don't implement multi read range yet, will do later.
00607     virtual int read_multi_range_first(KEY_MULTI_RANGE **found_range_p,
00608     KEY_MULTI_RANGE *ranges, uint range_count,
00609     bool sorted, HANDLER_BUFFER *buffer);
00610     virtual int read_multi_range_next(KEY_MULTI_RANGE **found_range_p);
00611   */
00612 
00613 
00614   virtual int read_range_first(const key_range * start_key,
00615                                const key_range * end_key,
00616                                bool eq_range, bool sorted);
00617   virtual int read_range_next();
00618 
00619 private:
00620   bool init_record_priority_queue();
00621   void destroy_record_priority_queue();
00622   int common_index_read(uchar * buf, bool have_start_key);
00623   int common_first_last(uchar * buf);
00624   int partition_scan_set_up(uchar * buf, bool idx_read_flag);
00625   int handle_unordered_next(uchar * buf, bool next_same);
00626   int handle_unordered_scan_next_partition(uchar * buf);
00627   int handle_ordered_index_scan(uchar * buf, bool reverse_order);
00628   int handle_ordered_index_scan_key_not_found();
00629   int handle_ordered_next(uchar * buf, bool next_same);
00630   int handle_ordered_prev(uchar * buf);
00631   void return_top_record(uchar * buf);
00632 public:
00633   /*
00634     -------------------------------------------------------------------------
00635     MODULE information calls
00636     -------------------------------------------------------------------------
00637     This calls are used to inform the handler of specifics of the ongoing
00638     scans and other actions. Most of these are used for optimisation
00639     purposes.
00640     -------------------------------------------------------------------------
00641   */
00642   virtual int info(uint);
00643   void get_dynamic_partition_info(PARTITION_STATS *stat_info,
00644                                   uint part_id);
00645   virtual int extra(enum ha_extra_function operation);
00646   virtual int extra_opt(enum ha_extra_function operation, ulong cachesize);
00647   virtual int reset(void);
00648   /*
00649     Do not allow caching of partitioned tables, since we cannot return
00650     a callback or engine_data that would work for a generic engine.
00651   */
00652   virtual my_bool register_query_cache_table(THD *thd, char *table_key,
00653                                              uint key_length,
00654                                              qc_engine_callback
00655                                                *engine_callback,
00656                                              ulonglong *engine_data)
00657   {
00658     *engine_callback= NULL;
00659     *engine_data= 0;
00660     return FALSE;
00661   }
00662 
00663 private:
00664   static const uint NO_CURRENT_PART_ID;
00665   int loop_extra(enum ha_extra_function operation);
00666   int loop_extra_alter(enum ha_extra_function operations);
00667   void late_extra_cache(uint partition_id);
00668   void late_extra_no_cache(uint partition_id);
00669   void prepare_extra_cache(uint cachesize);
00670 public:
00671 
00672   /*
00673     -------------------------------------------------------------------------
00674     MODULE optimiser support
00675     -------------------------------------------------------------------------
00676     -------------------------------------------------------------------------
00677   */
00678 
00679   /*
00680     NOTE !!!!!!
00681      -------------------------------------------------------------------------
00682      -------------------------------------------------------------------------
00683      One important part of the public handler interface that is not depicted in
00684      the methods is the attribute records
00685 
00686      which is defined in the base class. This is looked upon directly and is
00687      set by calling info(HA_STATUS_INFO) ?
00688      -------------------------------------------------------------------------
00689   */
00690 
00691 private:
00692   /* Helper functions for optimizer hints. */
00693   ha_rows min_rows_for_estimate();
00694   uint get_biggest_used_partition(uint *part_index);
00695 public:
00696 
00697   /*
00698     keys_to_use_for_scanning can probably be implemented as the
00699     intersection of all underlying handlers if mixed handlers are used.
00700     This method is used to derive whether an index can be used for
00701     index-only scanning when performing an ORDER BY query.
00702     Only called from one place in sql_select.cc
00703   */
00704   virtual const key_map *keys_to_use_for_scanning();
00705 
00706   /*
00707     Called in test_quick_select to determine if indexes should be used.
00708   */
00709   virtual double scan_time();
00710 
00711   /*
00712     The next method will never be called if you do not implement indexes.
00713   */
00714   virtual double read_time(uint index, uint ranges, ha_rows rows);
00715   /*
00716     For the given range how many records are estimated to be in this range.
00717     Used by optimiser to calculate cost of using a particular index.
00718   */
00719   virtual ha_rows records_in_range(uint inx, key_range * min_key,
00720                                    key_range * max_key);
00721 
00722   /*
00723     Upper bound of number records returned in scan is sum of all
00724     underlying handlers.
00725   */
00726   virtual ha_rows estimate_rows_upper_bound();
00727 
00728   /*
00729     table_cache_type is implemented by the underlying handler but all
00730     underlying handlers must have the same implementation for it to work.
00731   */
00732   virtual uint8 table_cache_type();
00733   virtual ha_rows records();
00734 
00735   /* Calculate hash value for PARTITION BY KEY tables. */
00736   uint32 calculate_key_hash_value(Field **field_array);
00737 
00738   /*
00739     -------------------------------------------------------------------------
00740     MODULE print messages
00741     -------------------------------------------------------------------------
00742     This module contains various methods that returns text messages for
00743     table types, index type and error messages.
00744     -------------------------------------------------------------------------
00745   */
00746   /*
00747     The name of the index type that will be used for display
00748     Here we must ensure that all handlers use the same index type
00749     for each index created.
00750   */
00751   virtual const char *index_type(uint inx);
00752 
00753   /* The name of the table type that will be used for display purposes */
00754   virtual const char *table_type() const;
00755 
00756   /* The name of the row type used for the underlying tables. */
00757   virtual enum row_type get_row_type() const;
00758 
00759   /*
00760      Handler specific error messages
00761   */
00762   virtual void print_error(int error, myf errflag);
00763   virtual bool get_error_message(int error, String * buf);
00764   /*
00765    -------------------------------------------------------------------------
00766     MODULE handler characteristics
00767     -------------------------------------------------------------------------
00768     This module contains a number of methods defining limitations and
00769     characteristics of the handler. The partition handler will calculate
00770     this characteristics based on underlying handler characteristics.
00771     -------------------------------------------------------------------------
00772 
00773     This is a list of flags that says what the storage engine
00774     implements. The current table flags are documented in handler.h
00775     The partition handler will support whatever the underlying handlers
00776     support except when specifically mentioned below about exceptions
00777     to this rule.
00778     NOTE: This cannot be cached since it can depend on TRANSACTION ISOLATION
00779     LEVEL which is dynamic, see bug#39084.
00780 
00781     HA_READ_RND_SAME:
00782     Not currently used. (Means that the handler supports the rnd_same() call)
00783     (MyISAM, HEAP)
00784 
00785     HA_TABLE_SCAN_ON_INDEX:
00786     Used to avoid scanning full tables on an index. If this flag is set then
00787     the handler always has a primary key (hidden if not defined) and this
00788     index is used for scanning rather than a full table scan in all
00789     situations.
00790     (InnoDB, BDB, Federated)
00791 
00792     HA_REC_NOT_IN_SEQ:
00793     This flag is set for handlers that cannot guarantee that the rows are
00794     returned accroding to incremental positions (0, 1, 2, 3...).
00795     This also means that rnd_next() should return HA_ERR_RECORD_DELETED
00796     if it finds a deleted row.
00797     (MyISAM (not fixed length row), BDB, HEAP, NDB, InooDB)
00798 
00799     HA_CAN_GEOMETRY:
00800     Can the storage engine handle spatial data.
00801     Used to check that no spatial attributes are declared unless
00802     the storage engine is capable of handling it.
00803     (MyISAM)
00804 
00805     HA_FAST_KEY_READ:
00806     Setting this flag indicates that the handler is equally fast in
00807     finding a row by key as by position.
00808     This flag is used in a very special situation in conjunction with
00809     filesort's. For further explanation see intro to init_read_record.
00810     (BDB, HEAP, InnoDB)
00811 
00812     HA_NULL_IN_KEY:
00813     Is NULL values allowed in indexes.
00814     If this is not allowed then it is not possible to use an index on a
00815     NULLable field.
00816     (BDB, HEAP, MyISAM, NDB, InnoDB)
00817 
00818     HA_DUPLICATE_POS:
00819     Tells that we can the position for the conflicting duplicate key
00820     record is stored in table->file->dupp_ref. (insert uses rnd_pos() on
00821     this to find the duplicated row)
00822     (MyISAM)
00823 
00824     HA_CAN_INDEX_BLOBS:
00825     Is the storage engine capable of defining an index of a prefix on
00826     a BLOB attribute.
00827     (BDB, Federated, MyISAM, InnoDB)
00828 
00829     HA_AUTO_PART_KEY:
00830     Auto increment fields can be part of a multi-part key. For second part
00831     auto-increment keys, the auto_incrementing is done in handler.cc
00832     (BDB, Federated, MyISAM, NDB)
00833 
00834     HA_REQUIRE_PRIMARY_KEY:
00835     Can't define a table without primary key (and cannot handle a table
00836     with hidden primary key)
00837     (No handler has this limitation currently)
00838 
00839     HA_STATS_RECORDS_IS_EXACT:
00840     Does the counter of records after the info call specify an exact
00841     value or not. If it does this flag is set.
00842     Only MyISAM and HEAP uses exact count.
00843 
00844     HA_CAN_INSERT_DELAYED:
00845     Can the storage engine support delayed inserts.
00846     To start with the partition handler will not support delayed inserts.
00847     Further investigation needed.
00848     (HEAP, MyISAM)
00849 
00850     HA_PRIMARY_KEY_IN_READ_INDEX:
00851     This parameter is set when the handler will also return the primary key
00852     when doing read-only-key on another index.
00853 
00854     HA_NOT_DELETE_WITH_CACHE:
00855     Seems to be an old MyISAM feature that is no longer used. No handler
00856     has it defined but it is checked in init_read_record.
00857     Further investigation needed.
00858     (No handler defines it)
00859 
00860     HA_NO_PREFIX_CHAR_KEYS:
00861     Indexes on prefixes of character fields is not allowed.
00862     (NDB)
00863 
00864     HA_CAN_FULLTEXT:
00865     Does the storage engine support fulltext indexes
00866     The partition handler will start by not supporting fulltext indexes.
00867     (MyISAM)
00868 
00869     HA_CAN_SQL_HANDLER:
00870     Can the HANDLER interface in the MySQL API be used towards this
00871     storage engine.
00872     (MyISAM, InnoDB)
00873 
00874     HA_NO_AUTO_INCREMENT:
00875     Set if the storage engine does not support auto increment fields.
00876     (Currently not set by any handler)
00877 
00878     HA_HAS_CHECKSUM:
00879     Special MyISAM feature. Has special SQL support in CREATE TABLE.
00880     No special handling needed by partition handler.
00881     (MyISAM)
00882 
00883     HA_FILE_BASED:
00884     Should file names always be in lower case (used by engines
00885     that map table names to file names.
00886     Since partition handler has a local file this flag is set.
00887     (BDB, Federated, MyISAM)
00888 
00889     HA_CAN_BIT_FIELD:
00890     Is the storage engine capable of handling bit fields?
00891     (MyISAM, NDB)
00892 
00893     HA_PRIMARY_KEY_REQUIRED_FOR_POSITION:
00894     Does the storage engine need a PK for position?
00895     (InnoDB)
00896 
00897     HA_FILE_BASED is always set for partition handler since we use a
00898     special file for handling names of partitions, engine types.
00899     HA_REC_NOT_IN_SEQ is always set for partition handler since we cannot
00900     guarantee that the records will be returned in sequence.
00901     HA_CAN_GEOMETRY, HA_CAN_FULLTEXT, HA_CAN_SQL_HANDLER, HA_DUPLICATE_POS,
00902     HA_CAN_INSERT_DELAYED, HA_PRIMARY_KEY_REQUIRED_FOR_POSITION is disabled
00903     until further investigated.
00904   */
00905   virtual Table_flags table_flags() const;
00906 
00907   /*
00908     This is a bitmap of flags that says how the storage engine
00909     implements indexes. The current index flags are documented in
00910     handler.h. If you do not implement indexes, just return zero
00911     here.
00912 
00913     part is the key part to check. First key part is 0
00914     If all_parts it's set, MySQL want to know the flags for the combined
00915     index up to and including 'part'.
00916 
00917     HA_READ_NEXT:
00918     Does the index support read next, this is assumed in the server
00919     code and never checked so all indexes must support this.
00920     Note that the handler can be used even if it doesn't have any index.
00921     (BDB, HEAP, MyISAM, Federated, NDB, InnoDB)
00922 
00923     HA_READ_PREV:
00924     Can the index be used to scan backwards.
00925     (BDB, HEAP, MyISAM, NDB, InnoDB)
00926 
00927     HA_READ_ORDER:
00928     Can the index deliver its record in index order. Typically true for
00929     all ordered indexes and not true for hash indexes.
00930     In first step this is not true for partition handler until a merge
00931     sort has been implemented in partition handler.
00932     Used to set keymap part_of_sortkey
00933     This keymap is only used to find indexes usable for resolving an ORDER BY
00934     in the query. Thus in most cases index_read will work just fine without
00935     order in result production. When this flag is set it is however safe to
00936     order all output started by index_read since most engines do this. With
00937     read_multi_range calls there is a specific flag setting order or not
00938     order so in those cases ordering of index output can be avoided.
00939     (BDB, InnoDB, HEAP, MyISAM, NDB)
00940 
00941     HA_READ_RANGE:
00942     Specify whether index can handle ranges, typically true for all
00943     ordered indexes and not true for hash indexes.
00944     Used by optimiser to check if ranges (as key >= 5) can be optimised
00945     by index.
00946     (BDB, InnoDB, NDB, MyISAM, HEAP)
00947 
00948     HA_ONLY_WHOLE_INDEX:
00949     Can't use part key searches. This is typically true for hash indexes
00950     and typically not true for ordered indexes.
00951     (Federated, NDB, HEAP)
00952 
00953     HA_KEYREAD_ONLY:
00954     Does the storage engine support index-only scans on this index.
00955     Enables use of HA_EXTRA_KEYREAD and HA_EXTRA_NO_KEYREAD
00956     Used to set key_map keys_for_keyread and to check in optimiser for
00957     index-only scans.  When doing a read under HA_EXTRA_KEYREAD the handler
00958     only have to fill in the columns the key covers. If
00959     HA_PRIMARY_KEY_IN_READ_INDEX is set then also the PRIMARY KEY columns
00960     must be updated in the row.
00961     (BDB, InnoDB, MyISAM)
00962   */
00963   virtual ulong index_flags(uint inx, uint part, bool all_parts) const
00964   {
00965     /* 
00966       TODO: sergefp: Support Index Condition Pushdown in this table handler.
00967     */
00968     return m_file[0]->index_flags(inx, part, all_parts) &
00969            ~HA_DO_INDEX_COND_PUSHDOWN;
00970   }
00971 
00976   virtual uint alter_table_flags(uint flags);
00977   /*
00978      extensions of table handler files
00979   */
00980   virtual const char **bas_ext() const;
00981   /*
00982     unireg.cc will call the following to make sure that the storage engine
00983     can handle the data it is about to send.
00984 
00985     The maximum supported values is the minimum of all handlers in the table
00986   */
00987   uint min_of_the_max_uint(uint (handler::*operator_func)(void) const) const; 
00988   virtual uint max_supported_record_length() const;
00989   virtual uint max_supported_keys() const;
00990   virtual uint max_supported_key_parts() const;
00991   virtual uint max_supported_key_length() const;
00992   virtual uint max_supported_key_part_length() const;
00993 
00994   /*
00995     All handlers in a partitioned table must have the same low_byte_first
00996   */
00997   virtual bool low_byte_first() const
00998   { return m_low_byte_first; }
00999 
01000   /*
01001     The extra record buffer length is the maximum needed by all handlers.
01002     The minimum record length is the maximum of all involved handlers.
01003   */
01004   virtual uint extra_rec_buf_length() const;
01005   virtual uint min_record_length(uint options) const;
01006 
01007   /*
01008     Primary key is clustered can only be true if all underlying handlers have
01009     this feature.
01010   */
01011   virtual bool primary_key_is_clustered()
01012   { return m_pkey_is_clustered; }
01013 
01014   /*
01015     -------------------------------------------------------------------------
01016     MODULE compare records
01017     -------------------------------------------------------------------------
01018     cmp_ref checks if two references are the same. For most handlers this is
01019     a simple memcmp of the reference. However some handlers use primary key
01020     as reference and this can be the same even if memcmp says they are
01021     different. This is due to character sets and end spaces and so forth.
01022     For the partition handler the reference is first two bytes providing the
01023     partition identity of the referred record and then the reference of the
01024     underlying handler.
01025     Thus cmp_ref for the partition handler always returns FALSE for records
01026     not in the same partition and uses cmp_ref on the underlying handler
01027     to check whether the rest of the reference part is also the same.
01028     -------------------------------------------------------------------------
01029   */
01030   virtual int cmp_ref(const uchar * ref1, const uchar * ref2);
01031   /*
01032     -------------------------------------------------------------------------
01033     MODULE auto increment
01034     -------------------------------------------------------------------------
01035     This module is used to handle the support of auto increments.
01036 
01037     This variable in the handler is used as part of the handler interface
01038     It is maintained by the parent handler object and should not be
01039     touched by child handler objects (see handler.cc for its use).
01040 
01041     auto_increment_column_changed
01042      -------------------------------------------------------------------------
01043   */
01044   virtual void get_auto_increment(ulonglong offset, ulonglong increment,
01045                                   ulonglong nb_desired_values,
01046                                   ulonglong *first_value,
01047                                   ulonglong *nb_reserved_values);
01048   virtual void release_auto_increment();
01049 private:
01050   virtual int reset_auto_increment(ulonglong value);
01051   virtual void lock_auto_increment()
01052   {
01053     /* lock already taken */
01054     if (auto_increment_safe_stmt_log_lock)
01055       return;
01056     DBUG_ASSERT(!auto_increment_lock);
01057     if(table_share->tmp_table == NO_TMP_TABLE)
01058     {
01059       auto_increment_lock= TRUE;
01060       part_share->lock_auto_inc();
01061     }
01062   }
01063   virtual void unlock_auto_increment()
01064   {
01065     /*
01066       If auto_increment_safe_stmt_log_lock is true, we have to keep the lock.
01067       It will be set to false and thus unlocked at the end of the statement by
01068       ha_partition::release_auto_increment.
01069     */
01070     if(auto_increment_lock && !auto_increment_safe_stmt_log_lock)
01071     {
01072       part_share->unlock_auto_inc();
01073       auto_increment_lock= FALSE;
01074     }
01075   }
01076   virtual void set_auto_increment_if_higher(Field *field)
01077   {
01078     ulonglong nr= (((Field_num*) field)->unsigned_flag ||
01079                    field->val_int() > 0) ? field->val_int() : 0;
01080     lock_auto_increment();
01081     DBUG_ASSERT(part_share->auto_inc_initialized);
01082     /* must check when the mutex is taken */
01083     if (nr >= part_share->next_auto_inc_val)
01084       part_share->next_auto_inc_val= nr + 1;
01085     unlock_auto_increment();
01086   }
01087 
01088 public:
01089 
01090   /*
01091      -------------------------------------------------------------------------
01092      MODULE initialize handler for HANDLER call
01093      -------------------------------------------------------------------------
01094      This method is a special InnoDB method called before a HANDLER query.
01095      -------------------------------------------------------------------------
01096   */
01097   virtual void init_table_handle_for_HANDLER();
01098 
01099   /*
01100     The remainder of this file defines the handler methods not implemented
01101     by the partition handler
01102   */
01103 
01104   /*
01105     -------------------------------------------------------------------------
01106     MODULE foreign key support
01107     -------------------------------------------------------------------------
01108     The following methods are used to implement foreign keys as supported by
01109     InnoDB. Implement this ??
01110     get_foreign_key_create_info is used by SHOW CREATE TABLE to get a textual
01111     description of how the CREATE TABLE part to define FOREIGN KEY's is done.
01112     free_foreign_key_create_info is used to free the memory area that provided
01113     this description.
01114     can_switch_engines checks if it is ok to switch to a new engine based on
01115     the foreign key info in the table.
01116     -------------------------------------------------------------------------
01117 
01118     virtual char* get_foreign_key_create_info()
01119     virtual void free_foreign_key_create_info(char* str)
01120 
01121     virtual int get_foreign_key_list(THD *thd,
01122     List<FOREIGN_KEY_INFO> *f_key_list)
01123     virtual uint referenced_by_foreign_key()
01124   */
01125     virtual bool can_switch_engines();
01126   /*
01127     -------------------------------------------------------------------------
01128     MODULE fulltext index
01129     -------------------------------------------------------------------------
01130     Fulltext stuff not yet.
01131     -------------------------------------------------------------------------
01132     virtual int ft_init() { return HA_ERR_WRONG_COMMAND; }
01133     virtual FT_INFO *ft_init_ext(uint flags,uint inx,const uchar *key,
01134     uint keylen)
01135     { return NULL; }
01136     virtual int ft_read(uchar *buf) { return HA_ERR_WRONG_COMMAND; }
01137   */
01138 
01139   /*
01140      -------------------------------------------------------------------------
01141      MODULE restart full table scan at position (MyISAM)
01142      -------------------------------------------------------------------------
01143      The following method is only used by MyISAM when used as
01144      temporary tables in a join.
01145      virtual int restart_rnd_next(uchar *buf, uchar *pos);
01146   */
01147 
01148   /*
01149     -------------------------------------------------------------------------
01150     MODULE in-place ALTER TABLE
01151     -------------------------------------------------------------------------
01152     These methods are in the handler interface. (used by innodb-plugin)
01153     They are used for in-place alter table:
01154     -------------------------------------------------------------------------
01155   */
01156     virtual enum_alter_inplace_result
01157       check_if_supported_inplace_alter(TABLE *altered_table,
01158                                        Alter_inplace_info *ha_alter_info);
01159     virtual bool prepare_inplace_alter_table(TABLE *altered_table,
01160                                              Alter_inplace_info *ha_alter_info);
01161     virtual bool inplace_alter_table(TABLE *altered_table,
01162                                      Alter_inplace_info *ha_alter_info);
01163     virtual bool commit_inplace_alter_table(TABLE *altered_table,
01164                                             Alter_inplace_info *ha_alter_info,
01165                                             bool commit);
01166     virtual void notify_table_changed();
01167 
01168   /*
01169     -------------------------------------------------------------------------
01170     MODULE tablespace support
01171     -------------------------------------------------------------------------
01172     Admin of table spaces is not applicable to the partition handler (InnoDB)
01173     This means that the following method is not implemented:
01174     -------------------------------------------------------------------------
01175     virtual int discard_or_import_tablespace(my_bool discard)
01176   */
01177 
01178   /*
01179     -------------------------------------------------------------------------
01180     MODULE admin MyISAM
01181     -------------------------------------------------------------------------
01182 
01183     -------------------------------------------------------------------------
01184       OPTIMIZE TABLE, CHECK TABLE, ANALYZE TABLE and REPAIR TABLE are
01185       mapped to a routine that handles looping over a given set of
01186       partitions and those routines send a flag indicating to execute on
01187       all partitions.
01188     -------------------------------------------------------------------------
01189   */
01190     virtual int optimize(THD* thd, HA_CHECK_OPT *check_opt);
01191     virtual int analyze(THD* thd, HA_CHECK_OPT *check_opt);
01192     virtual int check(THD* thd, HA_CHECK_OPT *check_opt);
01193     virtual int repair(THD* thd, HA_CHECK_OPT *check_opt);
01194     virtual bool check_and_repair(THD *thd);
01195     virtual bool auto_repair() const;
01196     virtual bool is_crashed() const;
01197     virtual int check_for_upgrade(HA_CHECK_OPT *check_opt);
01198 
01199     private:
01200     int handle_opt_partitions(THD *thd, HA_CHECK_OPT *check_opt, uint flags);
01201     int handle_opt_part(THD *thd, HA_CHECK_OPT *check_opt, uint part_id,
01202                         uint flag);
01207     int check_misplaced_rows(uint read_part_id, bool repair);
01208     void append_row_to_str(String &str);
01209     public:
01210   /*
01211     -------------------------------------------------------------------------
01212     Admin commands not supported currently (almost purely MyISAM routines)
01213     This means that the following methods are not implemented:
01214     -------------------------------------------------------------------------
01215 
01216     virtual int backup(TD* thd, HA_CHECK_OPT *check_opt);
01217     virtual int restore(THD* thd, HA_CHECK_OPT *check_opt);
01218     virtual int dump(THD* thd, int fd = -1);
01219     virtual int net_read_dump(NET* net);
01220   */
01221     virtual uint checksum() const;
01222   /* Enabled keycache for performance reasons, WL#4571 */
01223     virtual int assign_to_keycache(THD* thd, HA_CHECK_OPT *check_opt);
01224     virtual int preload_keys(THD* thd, HA_CHECK_OPT* check_opt);
01225 
01226   /*
01227     -------------------------------------------------------------------------
01228     MODULE enable/disable indexes
01229     -------------------------------------------------------------------------
01230     Enable/Disable Indexes are only supported by HEAP and MyISAM.
01231     -------------------------------------------------------------------------
01232   */
01233     virtual int disable_indexes(uint mode);
01234     virtual int enable_indexes(uint mode);
01235     virtual int indexes_are_disabled(void);
01236 
01237   /*
01238     -------------------------------------------------------------------------
01239     MODULE append_create_info
01240     -------------------------------------------------------------------------
01241     append_create_info is only used by MyISAM MERGE tables and the partition
01242     handler will not support this handler as underlying handler.
01243     Implement this??
01244     -------------------------------------------------------------------------
01245     virtual void append_create_info(String *packet)
01246   */
01247 };
01248 
01249 #endif /* HA_PARTITION_INCLUDED */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines