Drizzled Public API Documentation

cursor.h
00001 /* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
00002  *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
00003  *
00004  *  Copyright (C) 2008 Sun Microsystems, Inc.
00005  *
00006  *  This program is free software; you can redistribute it and/or modify
00007  *  it under the terms of the GNU General Public License as published by
00008  *  the Free Software Foundation; version 2 of the License.
00009  *
00010  *  This program is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  *  GNU General Public License for more details.
00014  *
00015  *  You should have received a copy of the GNU General Public License
00016  *  along with this program; if not, write to the Free Software
00017  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00018  */
00019 
00020 #pragma once
00021 
00022 #include <drizzled/atomics.h>
00023 #include <drizzled/definitions.h>
00024 #include <drizzled/discrete_interval.h>
00025 #include <drizzled/error_t.h>
00026 #include <drizzled/ha_statistics.h>
00027 #include <drizzled/handler_structs.h>
00028 #include <drizzled/identifier.h>
00029 #include <drizzled/key_map.h>
00030 #include <drizzled/message/table.h>
00031 #include <drizzled/sql_list.h>
00032 #include <drizzled/thr_lock.h>
00033 
00034 #include <bitset>
00035 #include <algorithm>
00036 
00037 #include <drizzled/visibility.h>
00038 
00039 namespace drizzled {
00040 
00041 #define HA_MAX_ALTER_FLAGS 40
00042 
00043 typedef std::bitset<HA_MAX_ALTER_FLAGS> HA_ALTER_FLAGS;
00044 
00045 typedef List<Item> List_item;
00046 extern KEY_CREATE_INFO default_key_create_info;
00047 
00048 /*
00049   bitmap with first N+1 bits set
00050   (keypart_map for a key prefix of [0..N] keyparts)
00051 */
00052 inline key_part_map make_keypart_map(int a)
00053 {
00054   return (((key_part_map)2 << a) - 1);
00055 }
00056 
00057 /*
00058   bitmap with first N bits set
00059   (keypart_map for a key prefix of [0..N-1] keyparts)
00060 */
00061 inline key_part_map make_prev_keypart_map(int a)
00062 {
00063   return (((key_part_map)1 << a) - 1);
00064 }
00065 
00109 class DRIZZLED_API Cursor
00110 {
00111   friend class SEAPITesterCursor;
00112   Table &table;               /* The current open table */
00113   plugin::StorageEngine &engine;      /* storage engine of this Cursor */
00114 
00115 protected:
00116   ha_rows estimation_rows_to_insert;
00117 
00118 public:
00119   inline plugin::StorageEngine *getEngine() const /* table_type for handler */
00120   {
00121     return &engine;
00122   }
00123   unsigned char *ref;       /* Pointer to current row */
00124   unsigned char *dup_ref;     /* Pointer to duplicate row */
00125 
00126   TableShare *getShare();
00127 
00128   Table *getTable() const
00129   {
00130     return &table;
00131   }
00132 
00133   ha_statistics stats;
00135   range_seq_t mrr_iter;    /* Interator to traverse the range sequence */
00136   RANGE_SEQ_IF mrr_funcs;  /* Range sequence traversal functions */
00137 
00138   uint32_t ranges_in_seq; /* Total number of ranges in the traversed sequence */
00139   /* true <=> source MRR ranges and the output are ordered */
00140   bool mrr_is_output_sorted;
00141 
00143   bool mrr_have_range;
00144 
00145   bool eq_range;
00146 
00148   KEY_MULTI_RANGE mrr_cur_range;
00149 
00151   key_range save_end_range, *end_range;
00152   KeyPartInfo *range_key_part;
00153   int key_compare_result_on_equal;
00154 
00155   uint32_t errkey;        /* Last dup key */
00156   uint32_t key_used_on_scan;
00157   uint32_t active_index;
00159   uint32_t ref_length;
00160   enum {NONE=0, INDEX, RND} inited;
00161   bool locked;
00162 
00172   uint64_t next_insert_id;
00173   uint64_t getNextInsertId() const
00174   {
00175     return next_insert_id;
00176   }
00177 
00181   uint64_t getAutoIncrement() const
00182   {
00183     return stats.auto_increment_value;
00184   }
00185 
00192   uint64_t insert_id_for_cur_row;
00197   Discrete_interval auto_inc_interval_for_cur_row;
00198 
00199   Cursor(plugin::StorageEngine &engine_arg, Table &share_arg);
00200   virtual ~Cursor(void);
00201   virtual Cursor *clone(memory::Root *mem_root);
00202 
00203   /* ha_ methods: pubilc wrappers for private virtual API */
00204 
00205   int ha_open(const identifier::Table &identifier, int mode, int test_if_locked);
00206   int startIndexScan(uint32_t idx, bool sorted) __attribute__ ((warn_unused_result));
00207   int endIndexScan();
00208   int startTableScan(bool scan) __attribute__ ((warn_unused_result));
00209   int endTableScan();
00210   int ha_reset();
00211 
00212   /* this is necessary in many places, e.g. in HANDLER command */
00213   int ha_index_or_rnd_end();
00214 
00221   int ha_external_lock(Session *session, int lock_type);
00222   int insertRecord(unsigned char * buf) __attribute__ ((warn_unused_result));
00223   int updateRecord(const unsigned char * old_data, unsigned char * new_data) __attribute__ ((warn_unused_result));
00224   int deleteRecord(const unsigned char * buf) __attribute__ ((warn_unused_result));
00225   void ha_release_auto_increment();
00226   int ha_check(Session*);
00227   void ha_start_bulk_insert(ha_rows rows);
00228   int ha_end_bulk_insert();
00229   int ha_delete_all_rows();
00230   int ha_reset_auto_increment(uint64_t value);
00231   int ha_analyze(Session*);
00232 
00233   int ha_disable_indexes(uint32_t mode);
00234   int ha_enable_indexes(uint32_t mode);
00235   int ha_discard_or_import_tablespace(bool discard);
00236   void closeMarkForDelete();
00237 
00238   void adjust_next_insert_id_after_explicit_value(uint64_t nr);
00239   int update_auto_increment();
00240 
00241   /* Estimates calculation */
00242   virtual double scan_time(void)
00243   { return static_cast<double>(stats.data_file_length) / IO_SIZE + 2; }
00244   virtual double read_time(uint32_t, uint32_t ranges, ha_rows rows)
00245   { return ranges + rows; }
00246 
00247   virtual double index_only_read_time(uint32_t keynr, double records);
00248 
00249   virtual ha_rows multi_range_read_info_const(uint32_t keyno, RANGE_SEQ_IF *seq,
00250                                               void *seq_init_param,
00251                                               uint32_t n_ranges, uint32_t *bufsz,
00252                                               uint32_t *flags, optimizer::CostVector *cost);
00253   virtual int multi_range_read_info(uint32_t keyno, uint32_t n_ranges, uint32_t keys,
00254                                     uint32_t *bufsz, uint32_t *flags, optimizer::CostVector *cost);
00255   virtual int multi_range_read_init(RANGE_SEQ_IF *seq, void *seq_init_param,
00256                                     uint32_t n_ranges, uint32_t mode);
00257   virtual int multi_range_read_next(char **range_info);
00258 
00259 
00260   virtual const key_map *keys_to_use_for_scanning();
00261   bool has_transactions();
00262 
00273   virtual bool is_fatal_error(int error, uint32_t flags);
00274 
00279   virtual ha_rows records();
00280   virtual uint64_t tableSize();
00281   virtual uint64_t rowSize();
00288   virtual ha_rows estimate_rows_upper_bound()
00289   { return stats.records+EXTRA_RECORDS; }
00290 
00291   virtual const char *index_type(uint32_t)
00292   { assert(0); return "";}
00293 
00294 
00295   uint32_t get_index(void) const { return active_index; }
00296   virtual int close(void)=0;
00297 
00304   virtual int index_read_map(unsigned char * buf, const unsigned char *key,
00305                              key_part_map keypart_map,
00306                              enum ha_rkey_function find_flag)
00307   {
00308     uint32_t key_len= calculate_key_len(active_index, keypart_map);
00309     return  index_read(buf, key, key_len, find_flag);
00310   }
00317   virtual int index_read_idx_map(unsigned char * buf, uint32_t index,
00318                                  const unsigned char * key,
00319                                  key_part_map keypart_map,
00320                                  enum ha_rkey_function find_flag);
00321   virtual int index_next(unsigned char *) __attribute__ ((warn_unused_result))
00322    { return  HA_ERR_WRONG_COMMAND; }
00323   virtual int index_prev(unsigned char *)
00324    { return  HA_ERR_WRONG_COMMAND; }
00325   virtual int index_first(unsigned char *)
00326    { return  HA_ERR_WRONG_COMMAND; }
00327   virtual int index_last(unsigned char *)
00328    { return  HA_ERR_WRONG_COMMAND; }
00329   virtual int index_next_same(unsigned char *, const unsigned char *, uint32_t);
00330 
00331 private:
00332   uint32_t calculate_key_len(uint32_t key_position, key_part_map keypart_map_arg);
00333 public:
00334 
00340   virtual int index_read_last_map(unsigned char * buf, const unsigned char * key,
00341                                   key_part_map keypart_map)
00342   {
00343     uint32_t key_len= calculate_key_len(active_index, keypart_map);
00344     return index_read_last(buf, key, key_len);
00345   }
00346   virtual int read_range_first(const key_range *start_key,
00347                                const key_range *end_key,
00348                                bool eq_range, bool sorted);
00349   virtual int read_range_next();
00350   int compare_key(key_range *range);
00351   virtual int rnd_next(unsigned char *)=0;
00352   virtual int rnd_pos(unsigned char *, unsigned char *)=0;
00353   virtual int read_first_row(unsigned char *buf, uint32_t primary_key);
00354   virtual int rnd_same(unsigned char *, uint32_t)
00355     { return HA_ERR_WRONG_COMMAND; }
00356   virtual ha_rows records_in_range(uint32_t, key_range *, key_range *)
00357     { return (ha_rows) 10; }
00358   virtual void position(const unsigned char *record)=0;
00359   virtual int info(uint32_t)=0; // see my_base.h for full description
00360   virtual uint32_t calculate_key_hash_value(Field **)
00361   { assert(0); return 0; }
00362   virtual int extra(enum ha_extra_function)
00363   { return 0; }
00364   virtual int extra_opt(enum ha_extra_function operation, uint32_t)
00365   { return extra(operation); }
00366 
00379   virtual bool was_semi_consistent_read() { return 0; }
00386   virtual void try_semi_consistent_read(bool) {}
00387   virtual void unlock_row(void) {}
00388   virtual void get_auto_increment(uint64_t offset, uint64_t increment,
00389                                   uint64_t nb_desired_values,
00390                                   uint64_t *first_value,
00391                                   uint64_t *nb_reserved_values)= 0;
00392 
00393   void set_next_insert_id(uint64_t id)
00394   {
00395     next_insert_id= id;
00396   }
00397   void restore_auto_increment(uint64_t prev_insert_id)
00398   {
00399     /*
00400       Insertion of a row failed, re-use the lastly generated auto_increment
00401       id, for the next row. This is achieved by resetting next_insert_id to
00402       what it was before the failed insertion (that old value is provided by
00403       the caller). If that value was 0, it was the first row of the INSERT;
00404       then if insert_id_for_cur_row contains 0 it means no id was generated
00405       for this first row, so no id was generated since the INSERT started, so
00406       we should set next_insert_id to 0; if insert_id_for_cur_row is not 0, it
00407       is the generated id of the first and failed row, so we use it.
00408     */
00409     next_insert_id= (prev_insert_id > 0) ? prev_insert_id :
00410       insert_id_for_cur_row;
00411   }
00412 
00413   /* end of the list of admin commands */
00414 
00415   virtual int indexes_are_disabled(void) {return 0;}
00416   virtual void append_create_info(String *)
00417   {}
00428   virtual char* get_foreign_key_create_info(void)
00429   { return NULL;}  /* gets foreign key create string from InnoDB */
00433   virtual bool can_switch_engines(void) { return true; }
00435   virtual int get_foreign_key_list(Session *, List<ForeignKeyInfo> *)
00436   { return 0; }
00437   virtual uint32_t referenced_by_foreign_key() { return 0;}
00438   virtual void free_foreign_key_create_info(char *) {}
00439 
00453   virtual THR_LOCK_DATA **store_lock(Session *,
00454                                      THR_LOCK_DATA **to,
00455                                      enum thr_lock_type)
00456   {
00457     assert(0); // Impossible programming situation
00458 
00459     return(to);
00460   }
00461 
00462  /*
00463    @retval true   Primary key (if there is one) is clustered
00464                   key covering all fields
00465    @retval false  otherwise
00466  */
00467  virtual bool primary_key_is_clustered() { return false; }
00468  virtual int cmp_ref(const unsigned char *ref1, const unsigned char *ref2)
00469  {
00470    return memcmp(ref1, ref2, ref_length);
00471  }
00472 
00473   virtual bool isOrdered(void)
00474   {
00475     return false;
00476   }
00477 
00478 
00479 protected:
00480   /* Service methods for use by storage engines. */
00481   void ha_statistic_increment(uint64_t system_status_var::*offset) const;
00482   void **ha_data(Session *) const;
00483 
00484 private:
00485   /* Private helpers */
00486   inline void setTransactionReadWrite();
00487 private:
00488   /*
00489     Low-level primitives for storage engines.  These should be
00490     overridden by the storage engine class. To call these methods, use
00491     the corresponding 'ha_*' method above.
00492   */
00493 
00494   virtual int open(const char *, int , uint32_t ) { assert(0); return -1; }
00495   virtual int doOpen(const identifier::Table &identifier, int mode, uint32_t test_if_locked);
00496   virtual int doStartIndexScan(uint32_t idx, bool)
00497   { active_index= idx; return 0; }
00498   virtual int doEndIndexScan() { active_index= MAX_KEY; return 0; }
00506   virtual int doStartTableScan(bool scan) __attribute__ ((warn_unused_result)) = 0;
00507   virtual int doEndTableScan() { return 0; }
00508   virtual int doInsertRecord(unsigned char *)
00509   {
00510     return HA_ERR_WRONG_COMMAND;
00511   }
00512 
00513   virtual int doUpdateRecord(const unsigned char *, unsigned char *)
00514   {
00515     return HA_ERR_WRONG_COMMAND;
00516   }
00517 
00518   virtual int doDeleteRecord(const unsigned char *)
00519   {
00520     return HA_ERR_WRONG_COMMAND;
00521   }
00527   virtual int reset() { return 0; }
00528 
00551   virtual int external_lock(Session *, int)
00552   {
00553     return 0;
00554   }
00555   virtual void release_auto_increment(void) { return; }
00557   virtual int check(Session *)
00558   { return HA_ADMIN_NOT_IMPLEMENTED; }
00559 
00560   virtual void start_bulk_insert(ha_rows)
00561   {}
00562   virtual int end_bulk_insert(void) { return 0; }
00563   virtual int index_read(unsigned char *, const unsigned char *,
00564                          uint32_t, enum ha_rkey_function)
00565    { return  HA_ERR_WRONG_COMMAND; }
00566   virtual int index_read_last(unsigned char *, const unsigned char *, uint32_t)
00567    { return (errno= HA_ERR_WRONG_COMMAND); }
00574   virtual int delete_all_rows(void)
00575   { return (errno=HA_ERR_WRONG_COMMAND); }
00582   virtual int reset_auto_increment(uint64_t)
00583   { return HA_ERR_WRONG_COMMAND; }
00584 
00585   virtual int analyze(Session *)
00586   { return HA_ADMIN_NOT_IMPLEMENTED; }
00587 
00588   virtual int disable_indexes(uint32_t)
00589   { return HA_ERR_WRONG_COMMAND; }
00590 
00591   virtual int enable_indexes(uint32_t)
00592   { return HA_ERR_WRONG_COMMAND; }
00593 
00594   virtual int discard_or_import_tablespace(bool)
00595   { return (errno=HA_ERR_WRONG_COMMAND); }
00596 
00597   /* 
00598     @todo this is just for the HEAP engine, it should
00599     be removed at some point in the future (and
00600     no new engine should ever use it). Right
00601     now HEAP does rely on it, so we cannot remove it.
00602   */
00603   virtual void drop_table();
00604 };
00605 
00606 extern const char *ha_row_type[];
00607 
00608 /* basic stuff */
00609 void ha_init_errors(void);
00610 
00611 SortField *make_unireg_sortorder(Order *order, uint32_t *length,
00612                                  SortField *sortorder);
00613 int setup_order(Session *session, Item **ref_pointer_array, TableList *tables,
00614                 List<Item> &fields, List <Item> &all_fields, Order *order);
00615 int setup_group(Session *session, Item **ref_pointer_array, TableList *tables,
00616                 List<Item> &fields, List<Item> &all_fields, Order *order,
00617                 bool *hidden_group_fields);
00618 bool fix_inner_refs(Session *session, List<Item> &all_fields, Select_Lex *select,
00619                     Item **ref_pointer_array);
00620 
00621 bool handle_select(Session *session, LEX *lex, select_result *result,
00622                    uint64_t setup_tables_done_option);
00623 void free_underlaid_joins(Session *session, Select_Lex *select);
00624 
00625 bool handle_derived(LEX *lex, bool (*processor)(Session *session,
00626                                                       LEX *lex,
00627                                                       TableList *table));
00628 bool derived_prepare(Session *session, LEX *lex, TableList *t);
00629 bool derived_filling(Session *session, LEX *lex, TableList *t);
00630 int prepare_create_field(CreateField *sql_field,
00631                          uint32_t *blob_columns,
00632                          int *timestamps, int *timestamps_with_niladic);
00633 
00634 bool create_table(Session *session,
00635                   const identifier::Table &identifier,
00636                   HA_CREATE_INFO *create_info,
00637                   message::Table &table_proto,
00638                   AlterInfo *alter_info,
00639                   bool tmp_table, uint32_t select_field_count,
00640                   bool is_if_not_exists);
00641 
00642 bool create_table_no_lock(Session *session,
00643                           const identifier::Table &identifier,
00644                           HA_CREATE_INFO *create_info,
00645                           message::Table &table_proto,
00646                           AlterInfo *alter_info,
00647                           bool tmp_table, uint32_t select_field_count,
00648                           bool is_if_not_exists);
00649 
00650 bool create_like_table(Session* session,
00651                        const identifier::Table& destination_identifier,
00652                        const identifier::Table& source_identifier,
00653                        message::Table &create_table_proto,
00654                        bool is_if_not_exists,
00655                        bool is_engine_set);
00656 
00657 bool rename_table(Session &session,
00658                         plugin::StorageEngine *base,
00659                         const identifier::Table &old_identifier,
00660                         const identifier::Table &new_identifier);
00661 
00662 bool prepare_update(Session *session, TableList *table_list,
00663                           Item **conds, uint32_t order_num, Order *order);
00664 int update_query(Session *session,TableList *tables,List<Item> &fields,
00665                  List<Item> &values,COND *conds,
00666                  uint32_t order_num, Order *order, ha_rows limit,
00667                  enum enum_duplicates handle_duplicates, bool ignore);
00668 bool prepare_insert(Session *session, TableList *table_list, Table *table,
00669                           List<Item> &fields, List_item *values,
00670                           List<Item> &update_fields,
00671                           List<Item> &update_values, enum_duplicates duplic,
00672                           COND **where, bool select_insert,
00673                           bool check_fields, bool abort_on_warning);
00674 bool insert_query(Session *session,TableList *table,List<Item> &fields,
00675                   List<List_item> &values, List<Item> &update_fields,
00676                   List<Item> &update_values, enum_duplicates flag,
00677                   bool ignore);
00678 int check_that_all_fields_are_given_values(Session *session, Table *entry,
00679                                            TableList *table_list);
00680 int prepare_delete(Session *session, TableList *table_list, Item **conds);
00681 bool delete_query(Session *session, TableList *table_list, COND *conds,
00682                   SQL_LIST *order, ha_rows rows, uint64_t options,
00683                   bool reset_auto_increment);
00684 bool truncate(Session& session, TableList *table_list);
00685 TableShare *get_table_share(Session *session, TableList *table_list, char *key,
00686                              uint32_t key_length, uint32_t db_flags, int *error);
00687 TableShare *get_cached_table_share(const char *db, const char *table_name);
00688 bool reopen_name_locked_table(Session* session, TableList* table_list, bool link_in);
00689 bool reopen_tables(Session *session,bool get_locks,bool in_refresh);
00690 void close_handle_and_leave_table_as_lock(Table *table);
00691 bool wait_for_tables(Session *session);
00692 bool table_is_used(Table *table, bool wait_for_name_lock);
00693 Table *drop_locked_tables(Session *session, const drizzled::identifier::Table &identifier);
00694 void abort_locked_tables(Session *session, const drizzled::identifier::Table &identifier);
00695 extern Field *not_found_field;
00696 extern Field *view_ref_found;
00697 
00698 Field *
00699 find_field_in_tables(Session *session, Item_ident *item,
00700                      TableList *first_table, TableList *last_table,
00701                      Item **ref, find_item_error_report_type report_error,
00702                      bool register_tree_change);
00703 Field *
00704 find_field_in_table_ref(Session *session, TableList *table_list,
00705                         const char *name, uint32_t length,
00706                         const char *item_name, const char *db_name,
00707                         const char *table_name, Item **ref,
00708                         bool allow_rowid,
00709                         uint32_t *cached_field_index_ptr,
00710                         bool register_tree_change, TableList **actual_table);
00711 Field *
00712 find_field_in_table(Session *session, Table *table, const char *name, uint32_t length,
00713                     bool allow_rowid, uint32_t *cached_field_index_ptr);
00714 
00715 } /* namespace drizzled */
00716