/* Copyright (c) 2005 PrimeBase Technologies GmbH * * Derived from ha_example.h * Copyright (C) 2003 MySQL AB * * PrimeBase XT * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * 2005-11-10 Paul McCullagh * */ #ifndef __ha_pbxt_h__ #define __ha_pbxt_h__ #ifdef DRIZZLED #include #include #include #include #include using namespace drizzled; using namespace drizzled::plugin; #else #include "mysql_priv.h" #endif #include "xt_defs.h" #include "table_xt.h" #ifdef USE_PRAGMA_INTERFACE #pragma interface /* gcc class implementation */ #endif #if MYSQL_VERSION_ID <= 50120 #define thd_killed(t) (t)->killed #endif #if MYSQL_VERSION_ID >= 50120 #define byte uchar #endif class ha_pbxt; #ifdef DRIZZLED class PBXTStorageEngine : public drizzled::plugin::TransactionalStorageEngine { int delete_system_table(const char *table_path); int rename_system_table(const char * from, const char * to); public: PBXTStorageEngine(std::string name_arg) : drizzled::plugin::TransactionalStorageEngine(name_arg, HTON_FAST_KEY_READ | HTON_NULL_IN_KEY | HTON_CAN_INDEX_BLOBS | HTON_AUTO_PART_KEY | HTON_HAS_FOREIGN_KEYS | HTON_HAS_DOES_TRANSACTIONS) {} void operator delete(void *) {} void operator delete[] (void *) {} /* override */ int close_connection(Session *); /* override */ int commit(Session *, bool); /* override */ int rollback(Session *, bool); /* override */ Cursor *create(TableShare&); /* override */ void drop_database(char *); /* override */ bool show_status(Session *, stat_print_fn *, enum ha_stat_type); /* override */ const char **bas_ext() const; /* override */ int doCreateTable(Session& session, Table &table_arg, const TableIdentifier& ident, drizzled::message::Table &proto); /* override */ int doRenameTable(Session& session, const TableIdentifier& from, const TableIdentifier& to); /* override */ int doDropTable(Session &session, const TableIdentifier& ident); /* override */ int doStartTransaction(Session *session, start_transaction_option_t options); /* override */ int doStartConsistentSnapshot(Session *) { /* obsolete */ return -1; } /* override */ int doSetSavepoint(drizzled::Session* thd, drizzled::NamedSavepoint&); /* override */ int doRollbackToSavepoint(drizzled::Session* thd, drizzled::NamedSavepoint&); /* override */ int doReleaseSavepoint(drizzled::Session* thd, drizzled::NamedSavepoint&); /* override */ int doCommit(drizzled::Session*, bool); /* override */ int doRollback(drizzled::Session*, bool); /* override */ uint32_t max_supported_keys(void) const { return -1; } /* override */ uint32_t max_supported_key_part_length(void) const { return MAX_KEY_LENGTH; } /* override */ void doGetTableIdentifiers(drizzled::CachedDirectory&, const drizzled::SchemaIdentifier&, drizzled::TableIdentifiers&) {} /* override */ bool doDoesTableExist(Session&, const TableIdentifier &identifier); virtual void shutdownPlugin(); ~PBXTStorageEngine(); }; typedef PBXTStorageEngine handlerton; #endif extern handlerton *pbxt_hton; /* * XTShareRec is a structure that will be shared amoung all open handlers. */ typedef struct XTShare { XTPathStrPtr sh_table_path; uint sh_use_count; XTTableHPtr sh_table; /* This is a XTTableHPtr, a reference to the XT internal table handle. */ uint sh_dic_key_count; XTIndexPtr *sh_dic_keys; /* A reference to the XT internal index list. */ xtBool sh_recalc_selectivity; /* This is set to TRUE if when have < 100 rows when the table is openned. */ /* We use a trick here to get an exclusive lock * on a table. The trick avoids having to use a * semaphore if a thread does not want * exclusive use. */ xt_mutex_type *sh_ex_mutex; xt_cond_type *sh_ex_cond; xtBool sh_table_lock; /* Set to TRUE if a lock on the table is held. */ ha_pbxt *sh_handlers; /* Double linked list of handlers for a particular table. */ xtWord8 sh_min_auto_inc; /* Used to proporgate the current auto-inc over a DELETE FROM * (does not work if the server shuts down in between!). */ THR_LOCK sh_lock; /* MySQL lock */ } XTShareRec, *XTSharePtr; /* * Class definition for the storage engine */ class ha_pbxt: public handler { public: XTSharePtr pb_share; /* Shared table info */ XTOpenTablePtr pb_open_tab; /* This is a XTOpenTablePtr (a reference to the XT internal table handle)! */ xtBool pb_key_read; /* No Need to retrieve the entire row, index values are sufficient. */ u_int pb_import_row_count; int pb_ignore_dup_key; u_int pb_ind_row_count; THR_LOCK_DATA pb_lock; /* MySQL lock */ ha_pbxt *pb_ex_next; /* Double linked list of handlers for a particular table. */ ha_pbxt *pb_ex_prev; xtBool pb_lock_table; /* The operation requires a table lock. */ int pb_table_locked; /* TRUE of this handler holds the table lock. */ int pb_ex_in_use; /* Set to 1 while when the handler is in use. */ THD *pb_mysql_thd; /* A pointer to the MySQL thread. */ xtBool pb_in_stat; /* TRUE of start_stmt() was issued */ ha_pbxt(plugin::StorageEngine &engine_arg, TableShare &table_arg); virtual ~ha_pbxt() { } /* The name that will be used for display purposes */ const char *table_type() const { return "PBXT"; } /* * The name of the index type that will be used for display * don't implement this method unless you really have indexes. */ const char *index_type(uint inx) { (void) inx; return "BTREE"; } #ifndef DRIZZLED const char **bas_ext() const; #endif MX_UINT8_T table_cache_type(); /* * This is a list of flags that says what the storage engine * implements. The current table flags are documented in * handler.h */ MX_TABLE_TYPES_T table_flags() const; /* * part is the key part to check. First key part is 0 * If all_parts it's set, MySQL want to know the flags for the combined * index up to and including 'part'. */ MX_ULONG_T index_flags(uint inx, uint part, bool all_parts) const; /* * unireg.cc will call the following to make sure that the storage engine can * handle the data it is about to send. * * Return *real* limits of your storage engine here. MySQL will do * min(your_limits, MySQL_limits) automatically * * Theoretically PBXT supports any number of key parts, etc. * Practically this is not true of course. */ uint max_supported_record_length() const { return UINT_MAX; } uint max_supported_keys() const { return 512; } uint max_supported_key_parts() const { return 128; } uint max_supported_key_length() const; uint max_supported_key_part_length() const; double scan_time(); double read_time(uint index, uint ranges, ha_rows rows); bool has_transactions() { return 1; } /* * Everything below are methods that we implement in ha_pbxt.cc. */ void internal_close(THD *thd, struct XTThread *self); int open(const char *name, int mode, uint test_if_locked); // required int reopen(void); int close(void); // required void init_auto_increment(xtWord8 min_auto_inc); void get_auto_increment(MX_ULONGLONG_T offset, MX_ULONGLONG_T increment, MX_ULONGLONG_T nb_desired_values, MX_ULONGLONG_T *first_value, MX_ULONGLONG_T *nb_reserved_values); void set_auto_increment(Field *nr); int doInsertRecord(byte * buf); int doUpdateRecord(const byte * old_data, byte * new_data); int doDeleteRecord(const byte * buf); /* Index access functions: */ int xt_index_in_range(register XTOpenTablePtr ot, register XTIndexPtr ind, register XTIdxSearchKeyPtr search_key, byte *buf); int xt_index_next_read(register XTOpenTablePtr ot, register XTIndexPtr ind, xtBool key_only, register XTIdxSearchKeyPtr search_key, byte *buf); int xt_index_prev_read(XTOpenTablePtr ot, XTIndexPtr ind, xtBool key_only, register XTIdxSearchKeyPtr search_key, byte *buf); int doStartIndexScan(uint idx, bool sorted); int doEndIndexScan(); int index_read(byte * buf, const byte * key, uint key_len, enum ha_rkey_function find_flag); int index_read_idx(byte * buf, uint idx, const byte * key, uint key_len, enum ha_rkey_function find_flag); int index_read_xt(byte * buf, uint idx, const byte * key, uint key_len, enum ha_rkey_function find_flag); int index_next(byte * buf); int index_next_same(byte * buf, const byte *key, uint length); int index_prev(byte * buf); int index_first(byte * buf); int index_last(byte * buf); int index_read_last(byte * buf, const byte * key, uint key_len); /* Sequential scan functions: */ int doStartTableScan(bool scan); //required int doEndTableScan(); int rnd_next(byte *buf); //required int rnd_pos(byte * buf, byte *pos); //required void position(const byte *record); //required #if MYSQL_VERSION_ID < 50114 void info(uint); #else int info(uint); #endif int extra(enum ha_extra_function operation); int reset(void); int external_lock(THD *thd, int lock_type); //required int start_stmt(THD *thd, thr_lock_type lock_type); void unlock_row(); int delete_all_rows(void); int repair(THD* thd, HA_CHECK_OPT* check_opt); int analyze(THD* thd); int optimize(THD* thd); int check(THD* thd); ha_rows records_in_range(uint inx, key_range *min_key, key_range *max_key); THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to, enum thr_lock_type lock_type); //required /* Foreign key support: */ //bool is_fk_defined_on_table_or_index(uint index); char* get_foreign_key_create_info(); #ifdef DRI_IS int get_foreign_key_list(THD *thd, List *f_key_list); //bool can_switch_engines(); uint referenced_by_foreign_key(); #endif void free_foreign_key_create_info(char* str); virtual bool get_error_message(int error, String *buf); }; /* From ha_pbxt.cc: */ #define XT_TAB_NAME_WITH_EXT_SIZE XT_TABLE_NAME_SIZE+4 //class THD; struct XTThread; struct XTDatabase; void xt_ha_unlock_table(struct XTThread *self, void *share); void xt_ha_close_global_database(XTThreadPtr self); void xt_ha_open_database_of_table(struct XTThread *self, XTPathStrPtr table_path); struct XTThread *xt_ha_set_current_thread(THD *thd, XTExceptionPtr e); void xt_ha_close_connection(THD* thd); struct XTThread *xt_ha_thd_to_self(THD* thd); int xt_ha_pbxt_to_mysql_error(int xt_err); int xt_ha_pbxt_thread_error_for_mysql(THD *thd, const XTThreadPtr self, int ignore_dup_key); void xt_ha_all_threads_close_database(XTThreadPtr self, XTDatabase *db); void ha_set_auto_increment(XTOpenTablePtr ot, Field *nr); /* * These hooks are suppossed to only be used by InnoDB: */ #ifndef DRIZZLED #ifdef INNODB_COMPATIBILITY_HOOKS extern "C" struct charset_info_st *thd_charset(MYSQL_THD thd); extern "C" char **thd_query(MYSQL_THD thd); extern "C" int thd_slave_thread(const MYSQL_THD thd); extern "C" int thd_binlog_format(const MYSQL_THD thd); extern "C" void thd_mark_transaction_to_rollback(MYSQL_THD thd, bool all); #else #define thd_charset(t) (t)->charset() #define thd_query(t) &(t)->query #define thd_slave_thread(t) (t)->slave_thread #define thd_binlog_format(t) (t)->variables.binlog_format #endif // INNODB_COMPATIBILITY_HOOKS */ #endif /* !DRIZZLED */ /* How to lock MySQL mutexes! */ #ifdef SAFE_MUTEX #if MYSQL_VERSION_ID < 60000 #if MYSQL_VERSION_ID < 50123 #define myxt_mutex_lock(x) safe_mutex_lock(x,__FILE__,__LINE__) #else #define myxt_mutex_lock(x) safe_mutex_lock(x,0,__FILE__,__LINE__) #endif #else #if MYSQL_VERSION_ID < 60004 #define myxt_mutex_lock(x) safe_mutex_lock(x,__FILE__,__LINE__) #else #define myxt_mutex_lock(x) safe_mutex_lock(x,0,__FILE__,__LINE__) #endif #endif #define myxt_mutex_t safe_mutex_t #define myxt_mutex_unlock(x) safe_mutex_unlock(x,__FILE__,__LINE__) #else // SAFE_MUTEX #ifdef MY_PTHREAD_FASTMUTEX #define myxt_mutex_lock(x) my_pthread_fastmutex_lock(x) #define myxt_mutex_t my_pthread_fastmutex_t #define myxt_mutex_unlock(x) pthread_mutex_unlock(&(x)->mutex) #else #define myxt_mutex_lock(x) pthread_mutex_lock(x) #define myxt_mutex_t pthread_mutex_t #define myxt_mutex_unlock(x) pthread_mutex_unlock(x) #endif #endif // SAFE_MUTEX #endif