Drizzled Public API Documentation

session.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 <algorithm>
00023 #include <bitset>
00024 #include <boost/make_shared.hpp>
00025 #include <boost/thread/condition_variable.hpp>
00026 #include <boost/thread/mutex.hpp>
00027 #include <boost/thread/shared_mutex.hpp>
00028 #include <boost/thread/thread.hpp>
00029 #include <map>
00030 #include <netdb.h>
00031 #include <string>
00032 #include <sys/resource.h>
00033 #include <sys/time.h>
00034 
00035 #include <drizzled/catalog/instance.h>
00036 #include <drizzled/catalog/local.h>
00037 #include <drizzled/copy_info.h>
00038 #include <drizzled/cursor.h>
00039 #include <drizzled/diagnostics_area.h>
00040 #include <drizzled/error.h>
00041 #include <drizzled/file_exchange.h>
00042 #include <drizzled/ha_data.h>
00043 #include <drizzled/identifier.h>
00044 #include <drizzled/named_savepoint.h>
00045 #include <drizzled/open_tables_state.h>
00046 #include <drizzled/plugin.h>
00047 #include <drizzled/plugin/authorization.h>
00048 #include <drizzled/pthread_globals.h>
00049 #include <drizzled/query_id.h>
00050 #include <drizzled/resource_context.h>
00051 #include <drizzled/session/property_map.h>
00052 #include <drizzled/session/state.h>
00053 #include <drizzled/session/table_messages.h>
00054 #include <drizzled/session/transactions.h>
00055 #include <drizzled/sql_error.h>
00056 #include <drizzled/sql_locale.h>
00057 #include <drizzled/statistics_variables.h>
00058 #include <drizzled/system_variables.h>
00059 #include <drizzled/system_variables.h>
00060 #include <drizzled/table_ident.h>
00061 #include <drizzled/transaction_context.h>
00062 #include <drizzled/util/storable.h>
00063 #include <drizzled/var.h>
00064 #include <drizzled/visibility.h>
00065 #include <drizzled/util/find_ptr.h>
00066 #include <drizzled/type/time.h>
00067 #include <drizzled/sql_lex.h>
00068 
00069 #define MIN_HANDSHAKE_SIZE      6
00070 
00071 namespace drizzled {
00072 
00073 namespace plugin
00074 {
00075   class Client;
00076   class Scheduler;
00077   class EventObserverList;
00078 }
00079 
00080 namespace message
00081 {
00082   class Transaction;
00083   class Statement;
00084   class Resultset;
00085 }
00086 
00087 namespace internal { struct st_my_thread_var; }
00088 
00089 namespace table 
00090 { 
00091   class Placeholder; 
00092   class Singular; 
00093 }
00094 
00095 class CopyField;
00096 class DrizzleXid;
00097 class Internal_error_handler;
00098 class Lex_input_stream;
00099 class TableShareInstance;
00100 class Table_ident;
00101 class Time_zone;
00102 class select_result;
00103 class user_var_entry;
00104 
00105 extern char internal_table_name[2];
00106 extern char empty_c_string[1];
00107 extern const char **errmesg;
00108 
00109 #define TC_HEURISTIC_RECOVER_COMMIT   1
00110 #define TC_HEURISTIC_RECOVER_ROLLBACK 2
00111 extern uint32_t tc_heuristic_recover;
00112 
00113 #define Session_SENTRY_MAGIC 0xfeedd1ff
00114 #define Session_SENTRY_GONE  0xdeadbeef
00115 
00116 extern DRIZZLED_API struct drizzle_system_variables global_system_variables;
00117 
00138 class DRIZZLED_API Session : public Open_tables_state
00139 {
00140 public:
00141   // Plugin storage in Session.
00142   typedef boost::shared_ptr<Session> shared_ptr;
00143   typedef Session& reference;
00144   typedef const Session& const_reference;
00145   typedef const Session* const_pointer;
00146   typedef Session* pointer;
00147 
00148   static shared_ptr make_shared(plugin::Client *client, catalog::Instance::shared_ptr instance_arg)
00149   {
00150     assert(instance_arg);
00151     return boost::make_shared<Session>(client, instance_arg);
00152   }
00153 
00154   /*
00155     MARK_COLUMNS_NONE:  Means mark_used_colums is not set and no indicator to
00156                         handler of fields used is set
00157     MARK_COLUMNS_READ:  Means a bit in read set is set to inform handler
00158                   that the field is to be read. If field list contains
00159                         duplicates, then session->dup_field is set to point
00160                         to the last found duplicate.
00161     MARK_COLUMNS_WRITE: Means a bit is set in write set to inform handler
00162       that it needs to update this field in write_row
00163                         and update_row.
00164   */
00165   enum enum_mark_columns mark_used_columns;
00166   inline void* calloc(size_t size)
00167   {
00168     void *ptr= mem_root->alloc_root(size);
00169     if (ptr)
00170       memset(ptr, 0, size);
00171     return ptr;
00172   }
00173   inline char *strmake(const char *str, size_t size)
00174   {
00175     return mem_root->strmake_root(str,size);
00176   }
00177 
00178   inline void *memdup_w_gap(const void *str, size_t size, uint32_t gap)
00179   {
00180     void *ptr= mem_root->alloc_root(size + gap);
00181     if (ptr)
00182       memcpy(ptr, str, size);
00183     return ptr;
00184   }
00186   void free_items();
00187 
00192   Item *free_list;
00193   memory::Root *mem_root; 
00195   memory::Root *getMemRoot()
00196   {
00197     return mem_root;
00198   }
00199 
00200   uint64_t getXaId()
00201   {
00202     return xa_id;
00203   }
00204 
00205   void setXaId(uint64_t in_xa_id)
00206   {
00207     xa_id= in_xa_id;
00208   }
00209 
00210 public:
00211   const LEX& lex() const;
00212   LEX& lex();
00213   enum_sql_command getSqlCommand() const;
00214 
00216   typedef boost::shared_ptr<const std::string> QueryString;
00217 
00218 private:
00219   boost::shared_ptr<std::string> query;
00220 
00221   // Never allow for a modification of this outside of the class. c_str()
00222   // requires under some setup non const, you must copy the QueryString in
00223   // order to use it.
00224 public:
00225   QueryString getQueryString() const
00226   {
00227     return query;
00228   }
00229 
00230   void resetQueryString()
00231   {
00232     query.reset();
00233     _state.reset();
00234   }
00235 
00236   /*
00237     We need to copy the lock on the string in order to make sure we have a stable string.
00238     Once this is done we can use it to build a const char* which can be handed off for
00239     a method to use (Innodb is currently the only engine using this).
00240   */
00241   const char *getQueryStringCopy(size_t &length)
00242   {
00243     QueryString tmp_string(getQueryString());
00244 
00245     if (not tmp_string)
00246     {
00247       length= 0;
00248       return NULL;
00249     }
00250 
00251     length= tmp_string->length();
00252     char *to_return= strmake(tmp_string->c_str(), tmp_string->length());
00253     return to_return;
00254   }
00255 
00256 private:
00257   session::State::shared_ptr  _state;
00258 
00259 public:
00260 
00261   session::State::const_shared_ptr state()
00262   {
00263     return _state;
00264   }
00265 
00278 private:
00279   util::string::shared_ptr _schema;
00280 
00281 public:
00282 
00283   util::string::const_shared_ptr schema() const
00284   {
00285     if (_schema)
00286       return _schema;
00287 
00288     return util::string::const_shared_ptr(new std::string(""));
00289   }
00290 
00291   /* current cache key */
00292   std::string query_cache_key;
00299   static const char * const DEFAULT_WHERE;
00300 
00301   memory::Root warn_root; 
00302 private:
00303   plugin::Client *client; 
00305 public:
00306 
00307   void setClient(plugin::Client *client_arg);
00308 
00309   plugin::Client *getClient()
00310   {
00311     return client;
00312   }
00313 
00314   plugin::Client *getClient() const
00315   {
00316     return client;
00317   }
00318 
00319   plugin::Scheduler *scheduler; 
00320   void *scheduler_arg; 
00322   typedef boost::unordered_map< std::string, user_var_entry *, util::insensitive_hash, util::insensitive_equal_to> UserVars;
00323 
00324 private:
00325   typedef std::pair< UserVars::iterator, UserVars::iterator > UserVarsRange;
00326   UserVars user_vars; 
00328 public:
00329   const UserVars &getUserVariables() const
00330   {
00331     return user_vars;
00332   }
00333 
00334   drizzle_system_variables variables; 
00336   enum_tx_isolation getTxIsolation()
00337   {
00338     return (enum_tx_isolation)variables.tx_isolation;
00339   }
00340 
00341   system_status_var status_var; 
00342   THR_LOCK_INFO lock_info; 
00343   THR_LOCK_OWNER main_lock_id; 
00344   THR_LOCK_OWNER *lock_id; 
00350   char *thread_stack;
00351 
00352 private:
00353   identifier::User::shared_ptr security_ctx;
00354 
00355   int32_t scoreboard_index;
00356 
00357   inline void checkSentry() const
00358   {
00359     assert(this->dbug_sentry == Session_SENTRY_MAGIC);
00360   }
00361 
00362 public:
00363   identifier::User::const_shared_ptr user() const
00364   {
00365     if (security_ctx)
00366       return security_ctx;
00367 
00368     return identifier::User::const_shared_ptr();
00369   }
00370 
00371   void setUser(identifier::User::shared_ptr arg)
00372   {
00373     security_ctx= arg;
00374   }
00375 
00376   int32_t getScoreboardIndex()
00377   {
00378     return scoreboard_index;
00379   }
00380 
00381   void setScoreboardIndex(int32_t in_scoreboard_index)
00382   {
00383     scoreboard_index= in_scoreboard_index;
00384   }
00385 
00389   bool isViewable(identifier::User::const_reference) const;
00390 
00391 private:
00397   const char *_where;
00398 
00399 public:
00400   const char *where()
00401   {
00402     return _where;
00403   }
00404 
00405   void setWhere(const char *arg)
00406   {
00407     _where= arg;
00408   }
00409 
00410   /*
00411     One thread can hold up to one named user-level lock. This variable
00412     points to a lock object if the lock is present. See item_func.cc and
00413     chapter 'Miscellaneous functions', for functions GET_LOCK, RELEASE_LOCK.
00414   */
00415   uint32_t dbug_sentry; 
00417 private:
00418   boost::thread::id boost_thread_id;
00419   boost_thread_shared_ptr _thread;
00420   boost::this_thread::disable_interruption *interrupt;
00421 
00422   internal::st_my_thread_var *mysys_var;
00423 
00424 public:
00425   boost_thread_shared_ptr &getThread()
00426   {
00427     return _thread;
00428   }
00429 
00430   void pushInterrupt(boost::this_thread::disable_interruption *interrupt_arg)
00431   {
00432     interrupt= interrupt_arg;
00433   }
00434 
00435   boost::this_thread::disable_interruption &getThreadInterupt()
00436   {
00437     assert(interrupt);
00438     return *interrupt;
00439   }
00440 
00441   internal::st_my_thread_var *getThreadVar()
00442   {
00443     return mysys_var;
00444   }
00445 
00450   enum enum_server_command command;
00451   uint32_t file_id; 
00452   /* @note the following three members should likely move to Client */
00453   uint32_t max_client_packet_length; 
00455 private:
00456   boost::posix_time::ptime _epoch;
00457   boost::posix_time::ptime _connect_time;
00458   boost::posix_time::ptime _start_timer;
00459   boost::posix_time::ptime _end_timer;
00460 
00461   boost::posix_time::ptime _user_time;
00462 public:
00463   uint64_t utime_after_lock; // This used by Innodb.
00464 
00465   void resetUserTime()
00466   {
00467     _user_time= boost::posix_time::not_a_date_time;
00468   }
00469 
00470   const boost::posix_time::ptime &start_timer() const
00471   {
00472     return _start_timer;
00473   }
00474 
00475   void getTimeDifference(boost::posix_time::time_duration &result_arg, const boost::posix_time::ptime &arg) const
00476   {
00477     result_arg=  arg - _start_timer;
00478   }
00479 
00480   thr_lock_type update_lock_default;
00481 
00482   /*
00483     Both of the following container points in session will be converted to an API.
00484   */
00485 
00486 private:
00487   /* container for handler's private per-connection data */
00488   std::vector<Ha_data> ha_data;
00489   /*
00490     Id of current query. Statement can be reused to execute several queries
00491     query_id is global in context of the whole MySQL server.
00492     ID is automatically generated from an atomic counter.
00493     It's used in Cursor code for various purposes: to check which columns
00494     from table are necessary for this select, to check if it's necessary to
00495     update auto-updatable fields (like auto_increment and timestamp).
00496   */
00497   query_id_t query_id;
00498   query_id_t warn_query_id;
00499 
00500 public:
00501   void **getEngineData(const plugin::MonitoredInTransaction *monitored);
00502   ResourceContext *getResourceContext(const plugin::MonitoredInTransaction *monitored,
00503                                       size_t index= 0);
00504 
00505   session::Transactions transaction;
00506 
00507   Field *dup_field;
00508   sigset_t signals;
00509 
00510 public:
00511   // As of right now we do not allow a concurrent execute to launch itself
00512   void setConcurrentExecute(bool arg)
00513   {
00514     concurrent_execute_allowed= arg;
00515   }
00516 
00517   bool isConcurrentExecuteAllowed() const
00518   {
00519     return concurrent_execute_allowed;
00520   }
00521 
00522   /*
00523     ALL OVER THIS FILE, "insert_id" means "*automatically generated* value for
00524     insertion into an auto_increment column".
00525   */
00534   uint64_t first_successful_insert_id_in_prev_stmt;
00540   uint64_t first_successful_insert_id_in_cur_stmt;
00568   Discrete_intervals_list auto_inc_intervals_in_cur_stmt_for_binlog;
00570   Discrete_intervals_list auto_inc_intervals_forced;
00571 
00572   uint64_t limit_found_rows;
00573   uint64_t options; 
00574   int64_t row_count_func; 
00576   int64_t rowCount() const
00577   {
00578     return row_count_func;
00579   }
00580 
00581   ha_rows cuted_fields; 
00587   ha_rows sent_row_count;
00588 
00592   ha_rows examined_row_count;
00593 
00603   table_map used_tables;
00604 
00613   List<DRIZZLE_ERROR> warn_list;
00614   uint32_t warn_count[(uint32_t) DRIZZLE_ERROR::WARN_LEVEL_END];
00615   uint32_t total_warn_count;
00616   Diagnostics_area main_da;
00617 
00618   ulong col_access;
00619 
00620   /* Statement id is thread-wide. This counter is used to generate ids */
00621   uint32_t statement_id_counter;
00622   uint32_t rand_saved_seed1;
00623   uint32_t rand_saved_seed2;
00628   uint32_t row_count;
00629 
00630   uint32_t getRowCount() const
00631   {
00632     return row_count;
00633   }
00634 
00635   session_id_t thread_id;
00636   uint32_t tmp_table;
00637   enum global_read_lock_t
00638   {
00639     NONE= 0,
00640     GOT_GLOBAL_READ_LOCK= 1,
00641     MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT= 2
00642   };
00643 private:
00644   global_read_lock_t _global_read_lock;
00645 
00646 public:
00647 
00648   global_read_lock_t isGlobalReadLock() const
00649   {
00650     return _global_read_lock;
00651   }
00652 
00653   void setGlobalReadLock(global_read_lock_t arg)
00654   {
00655     _global_read_lock= arg;
00656   }
00657 
00658   DrizzleLock *lockTables(Table **tables, uint32_t count, uint32_t flags);
00659   bool lockGlobalReadLock();
00660   bool lock_table_names(TableList *table_list);
00661   bool lock_table_names_exclusively(TableList *table_list);
00662   bool makeGlobalReadLockBlockCommit();
00663   bool abortLockForThread(Table *table);
00664   bool wait_if_global_read_lock(bool abort_on_refresh, bool is_not_commit);
00665   int lock_table_name(TableList *table_list);
00666   void abortLock(Table *table);
00667   void removeLock(Table *table);
00668   void unlockReadTables(DrizzleLock *sql_lock);
00669   void unlockSomeTables(Table **table, uint32_t count);
00670   void unlockTables(DrizzleLock *sql_lock);
00671   void startWaitingGlobalReadLock();
00672   void unlockGlobalReadLock();
00673 
00674 private:
00675   int unlock_external(Table **table, uint32_t count);
00676   int lock_external(Table **tables, uint32_t count);
00677   bool wait_for_locked_table_names(TableList *table_list);
00678   DrizzleLock *get_lock_data(Table **table_ptr, uint32_t count,
00679                              bool should_lock, Table **write_lock_used);
00680 public:
00681 
00682   uint32_t server_status;
00683   uint32_t open_options;
00684   uint32_t select_number; 
00685   /* variables.transaction_isolation is reset to this after each commit */
00686   enum_tx_isolation session_tx_isolation;
00687   enum_check_fields count_cuted_fields;
00688 
00689   enum killed_state_t
00690   {
00691     NOT_KILLED,
00692     KILL_BAD_DATA,
00693     KILL_CONNECTION,
00694     KILL_QUERY,
00695     KILLED_NO_VALUE /* means none of the above states apply */
00696   };
00697 private:
00698   killed_state_t volatile _killed;
00699 
00700 public:
00701 
00702   void setKilled(killed_state_t arg)
00703   {
00704     _killed= arg;
00705   }
00706 
00707   killed_state_t getKilled()
00708   {
00709     return _killed;
00710   }
00711 
00712   volatile killed_state_t *getKilledPtr() // Do not use this method, it is here for historical convience.
00713   {
00714     return &_killed;
00715   }
00716 
00717   bool is_admin_connection;
00718   bool some_tables_deleted;
00719   bool no_errors;
00720   bool password;
00728   bool is_fatal_error;
00734   bool transaction_rollback_request;
00746   bool is_fatal_sub_stmt_error;
00748   bool substitute_null_with_insert_id;
00749   bool cleanup_done;
00750 
00751 public:
00752   bool got_warning; 
00753   bool no_warnings_for_error; 
00755   bool derived_tables_processing;
00756 
00757   bool doing_tablespace_operation()
00758   {
00759     return tablespace_op;
00760   }
00761 
00762   void setDoingTablespaceOperation(bool doing)
00763   {
00764     tablespace_op= doing;
00765   }
00766 
00767 
00769   union
00770   {
00771     bool bool_value;
00772     uint32_t uint32_t_value;
00773     int32_t int32_t_value;
00774     uint64_t uint64_t_value;
00775   } sys_var_tmp;
00776 
00784   Lex_input_stream *m_lip;
00785 
00787   void *session_marker;
00788 
00790   Table *cached_table;
00791 
00800   inline void set_proc_info(const char *info)
00801   {
00802     proc_info= info;
00803   }
00804   inline const char* get_proc_info() const
00805   {
00806     return proc_info;
00807   }
00808 
00810   inline void setQueryId(query_id_t in_query_id)
00811   {
00812     query_id= in_query_id;
00813   }
00814 
00816   query_id_t getQueryId()  const
00817   {
00818     return query_id;
00819   }
00820 
00821 
00823   inline void setWarningQueryId(query_id_t in_query_id)
00824   {
00825     warn_query_id= in_query_id;
00826   }
00827 
00829   inline query_id_t getWarningQueryId()  const
00830   {
00831     return warn_query_id;
00832   }
00833 
00835   inline session_id_t getSessionId()  const
00836   {
00837     return thread_id;
00838   }
00839 
00841   inline uint32_t getServerId()  const
00842   {
00843     /* We return the global server ID. */
00844     return server_id;
00845   }
00846 
00848   inline my_xid getTransactionId()
00849   {
00850     return transaction.xid_state.xid.quick_get_my_xid();
00851   }
00888   inline void record_first_successful_insert_id_in_cur_stmt(uint64_t id_arg)
00889   {
00890     if (first_successful_insert_id_in_cur_stmt == 0)
00891       first_successful_insert_id_in_cur_stmt= id_arg;
00892   }
00893   inline uint64_t read_first_successful_insert_id_in_prev_stmt()
00894   {
00895     return first_successful_insert_id_in_prev_stmt;
00896   }
00902   inline void force_one_auto_inc_interval(uint64_t next_id)
00903   {
00904     auto_inc_intervals_forced.empty(); // in case of multiple SET INSERT_ID
00905     auto_inc_intervals_forced.append(next_id, UINT64_MAX, 0);
00906   }
00907 
00908   Session(plugin::Client *client_arg, catalog::Instance::shared_ptr catalog);
00909   virtual ~Session();
00910 
00911   void cleanup();
00924   void cleanup_after_query();
00925   bool storeGlobals();
00926   void awake(Session::killed_state_t state_to_set);
00936   bool initGlobals();
00937 
00944   void prepareForQueries();
00945 
00960   bool executeStatement();
00961 
00978   bool readAndStoreQuery(const char *in_packet, uint32_t in_packet_length);
00979 
00988   bool endTransaction(enum enum_mysql_completiontype completion);
00989   bool endActiveTransaction();
00990   bool startTransaction(start_transaction_option_t opt= START_TRANS_NO_OPTIONS);
00991   void markTransactionForRollback(bool all);
00992 
00998   bool authenticate();
00999 
01005   void run();
01006 
01010   static bool schedule(Session::shared_ptr&);
01011 
01012   static void unlink(session_id_t &session_id);
01013   static void unlink(Session::shared_ptr&);
01014 
01015   /*
01016     For enter_cond() / exit_cond() to work the mutex must be got before
01017     enter_cond(); this mutex is then released by exit_cond().
01018     Usage must be: lock mutex; enter_cond(); your code; exit_cond().
01019   */
01020   const char* enter_cond(boost::condition_variable_any &cond, boost::mutex &mutex, const char* msg);
01021   void exit_cond(const char* old_msg);
01022 
01023   type::Time::epoch_t query_start()
01024   {
01025     return getCurrentTimestampEpoch();
01026   }
01027 
01028   void set_time()
01029   {
01030     _end_timer= _start_timer= boost::posix_time::microsec_clock::universal_time();
01031     utime_after_lock= (_start_timer - _epoch).total_microseconds();
01032   }
01033 
01034   void set_time(time_t t) // This is done by a sys_var, as long as user_time is set, we will use that for all references to time
01035   {
01036     _user_time= boost::posix_time::from_time_t(t);
01037   }
01038 
01039   void set_time_after_lock()
01040   {
01041     utime_after_lock= (boost::posix_time::microsec_clock::universal_time() - _epoch).total_microseconds();
01042   }
01043 
01044   void set_end_timer()
01045   {
01046     _end_timer= boost::posix_time::microsec_clock::universal_time();
01047     status_var.execution_time_nsec+=(_end_timer - _start_timer).total_microseconds();
01048   }
01049 
01050   uint64_t getElapsedTime() const
01051   {
01052     return (_end_timer - _start_timer).total_microseconds();
01053   }
01054 
01058   type::Time::epoch_t getCurrentTimestamp(bool actual= true) const
01059   {
01060     return ((actual ? boost::posix_time::microsec_clock::universal_time() : _end_timer) - _epoch).total_microseconds();
01061   }
01062 
01063   // We may need to set user on this
01064   type::Time::epoch_t getCurrentTimestampEpoch() const
01065   {
01066     return ((_user_time.is_not_a_date_time() ? _start_timer : _user_time) - _epoch).total_seconds();
01067   }
01068 
01069   type::Time::epoch_t getCurrentTimestampEpoch(type::Time::usec_t &fraction_arg) const
01070   {
01071     if (not _user_time.is_not_a_date_time())
01072     {
01073       fraction_arg= 0;
01074       return (_user_time - _epoch).total_seconds();
01075     }
01076 
01077     fraction_arg= _start_timer.time_of_day().fractional_seconds() % 1000000;
01078     return (_start_timer - _epoch).total_seconds();
01079   }
01080 
01081   uint64_t found_rows() const
01082   {
01083     return limit_found_rows;
01084   }
01085 
01087   bool inTransaction() const
01088   {
01089     return server_status & SERVER_STATUS_IN_TRANS;
01090   }
01091 
01092   LEX_STRING *make_lex_string(LEX_STRING *lex_str,
01093                               const char* str, uint32_t length,
01094                               bool allocate_lex_string);
01095 
01096   LEX_STRING *make_lex_string(LEX_STRING *lex_str,
01097                               const std::string &str,
01098                               bool allocate_lex_string);
01099 
01100   int send_explain_fields(select_result *result);
01101 
01109   inline void clear_error(bool full= false)
01110   {
01111     if (main_da.is_error())
01112       main_da.reset_diagnostics_area();
01113 
01114     if (full)
01115     {
01116       drizzle_reset_errors(this, true);
01117     }
01118   }
01119 
01120   void clearDiagnostics()
01121   {
01122     main_da.reset_diagnostics_area();
01123   }
01124 
01130   inline void fatal_error()
01131   {
01132     assert(main_da.is_error());
01133     is_fatal_error= true;
01134   }
01148   inline bool is_error() const { return main_da.is_error(); }
01149   inline const CHARSET_INFO *charset() { return default_charset_info; }
01150 
01159   void end_statement();
01160   inline int killed_errno() const
01161   {
01162     killed_state_t killed_val; /* to cache the volatile 'killed' */
01163     return (killed_val= _killed) != KILL_BAD_DATA ? killed_val : 0;
01164   }
01165   void send_kill_message() const;
01166   /* return true if we will abort query if we make a warning now */
01167   inline bool abortOnWarning()
01168   {
01169     return abort_on_warning;
01170   }
01171 
01172   inline void setAbortOnWarning(bool arg)
01173   {
01174     abort_on_warning= arg;
01175   }
01176 
01177   void setAbort(bool arg);
01178   void lockOnSys();
01179   void set_status_var_init();
01180 
01198   void set_db(const std::string &new_db);
01199 
01200   /*
01201     Copy the current database to the argument. Use the current arena to
01202     allocate memory for a deep copy: current database may be freed after
01203     a statement is parsed but before it's executed.
01204   */
01205   bool copy_db_to(char **p_db, size_t *p_db_length);
01206 
01207 public:
01212   void push_internal_handler(Internal_error_handler *handler);
01213 
01220   virtual bool handle_error(drizzled::error_t sql_errno, const char *message,
01221                             DRIZZLE_ERROR::enum_warning_level level);
01222 
01226   void pop_internal_handler();
01227 
01241   void reset_for_next_command();
01242 
01251   void disconnect(enum error_t errcode= EE_OK);
01252 
01265   bool checkUser(const std::string &passwd, const std::string &db);
01266 
01271   uint64_t getConnectMicroseconds() const
01272   {
01273     return (_connect_time - _epoch).total_microseconds();
01274   }
01275 
01276   uint64_t getConnectSeconds() const
01277   {
01278     return (_connect_time - _epoch).total_seconds();
01279   }
01280 
01286   message::Transaction *getTransactionMessage() const
01287   {
01288     return transaction_message;
01289   }
01290 
01295   message::Statement *getStatementMessage() const
01296   {
01297     return statement_message;
01298   }
01299 
01304   message::Resultset *getResultsetMessage() const
01305   {
01306     return resultset;
01307   }
01314   void setTransactionMessage(message::Transaction *in_message)
01315   {
01316     transaction_message= in_message;
01317   }
01318 
01325   void setStatementMessage(message::Statement *in_message)
01326   {
01327     statement_message= in_message;
01328   }
01329 
01336   void setResultsetMessage(message::Resultset *in_message)
01337   {
01338     resultset= in_message;
01339   }
01345   void resetResultsetMessage()
01346   {
01347     resultset= NULL;
01348   }
01349 
01350 public:
01351   plugin::EventObserverList *getSessionObservers()
01352   {
01353     return session_event_observers;
01354   }
01355 
01356   void setSessionObservers(plugin::EventObserverList *observers)
01357   {
01358     session_event_observers= observers;
01359   }
01360 
01361   /* For schema event observers there is one set of observers per database. */
01362   plugin::EventObserverList *getSchemaObservers(const std::string &db_name)
01363   {
01364     if (schema_event_observers_t::mapped_type* i= find_ptr(schema_event_observers, db_name))
01365       return *i;
01366     return NULL;
01367   }
01368 
01369   void setSchemaObservers(const std::string &db_name, plugin::EventObserverList *observers)
01370   {
01371     schema_event_observers.erase(db_name);
01372     if (observers)
01373       schema_event_observers[db_name] = observers;
01374   }
01375 
01376 
01377  private:
01378 
01380   Internal_error_handler *m_internal_handler;
01389   memory::Root main_mem_root;
01390 
01409   void mark_used_tables_as_free_for_reuse(Table *table);
01410 
01411 public:
01412 
01414   inline void my_ok(ha_rows affected_rows= 0, ha_rows found_rows_arg= 0,
01415                     uint64_t passed_id= 0, const char *message= NULL)
01416   {
01417     main_da.set_ok_status(this, affected_rows, found_rows_arg, passed_id, message);
01418   }
01419 
01420 
01423   inline void my_eof()
01424   {
01425     main_da.set_eof_status(this);
01426   }
01427 
01428   bool add_item_to_list(Item *item);
01429   bool add_value_to_list(Item *value);
01430   bool add_order_to_list(Item *item, bool asc);
01431   bool add_group_to_list(Item *item, bool asc);
01432 
01433   void refresh_status();
01434   user_var_entry *getVariable(LEX_STRING &name, bool create_if_not_exists);
01435   user_var_entry *getVariable(const std::string  &name, bool create_if_not_exists);
01436   void setVariable(const std::string &name, const std::string &value);
01437 
01442   void close_thread_tables();
01443   void close_old_data_files(bool morph_locks= false,
01444                             bool send_refresh= false);
01445   void close_open_tables();
01446   void close_data_files_and_morph_locks(const identifier::Table &identifier);
01447 
01454   void close_tables_for_reopen(TableList **tables);
01455 
01456 
01471   bool openTablesLock(TableList *tables);
01472 
01473   int open_tables_from_list(TableList **start, uint32_t *counter, uint32_t flags= 0);
01474 
01475   Table *openTableLock(TableList *table_list, thr_lock_type lock_type);
01476   Table *openTable(TableList *table_list, bool *refresh, uint32_t flags= 0);
01477 
01478   void unlink_open_table(Table *find);
01479   void drop_open_table(Table *table, const identifier::Table &identifier);
01480   void close_cached_table(Table *table);
01481 
01482   /* Create a lock in the cache */
01483   table::Placeholder *table_cache_insert_placeholder(const identifier::Table &identifier);
01484   bool lock_table_name_if_not_cached(const identifier::Table &identifier, Table **table);
01485 
01486   session::TableMessages &getMessageCache()
01487   {
01488     return _table_message_cache;
01489   }
01490 
01491   /* Reopen operations */
01492   bool reopen_tables();
01493   bool close_cached_tables(TableList *tables, bool wait_for_refresh, bool wait_for_placeholders);
01494 
01495   void wait_for_condition(boost::mutex &mutex, boost::condition_variable_any &cond);
01496   int setup_conds(TableList *leaves, COND **conds);
01497   int lock_tables(TableList *tables, uint32_t count, bool *need_reopen);
01498 
01499   drizzled::util::Storable *getProperty(const std::string &arg)
01500   {
01501     return life_properties.getProperty(arg);
01502   }
01503 
01504   template<class T>
01505   void setProperty(const std::string &arg, T *value)
01506   {
01507     life_properties.setProperty(arg, value);
01508   }
01509 
01518   plugin::StorageEngine *getDefaultStorageEngine()
01519   {
01520     if (variables.storage_engine)
01521       return variables.storage_engine;
01522     return global_system_variables.storage_engine;
01523   }
01524 
01525   void get_xid(DrizzleXid *xid); // Innodb only
01526 
01527   table::Singular *getInstanceTable();
01528   table::Singular *getInstanceTable(List<CreateField> &field_list);
01529 
01530   void setUsage(bool arg)
01531   {
01532     use_usage= arg;
01533   }
01534 
01535   const rusage &getUsage()
01536   {
01537     return usage;
01538   }
01539 
01540   catalog::Instance::const_reference catalog() const
01541   {
01542     return *_catalog;
01543   }
01544 
01545   catalog::Instance::reference catalog()
01546   {
01547     return *_catalog;
01548   }
01549 
01550   bool arg_of_last_insert_id_function; // Tells if LAST_INSERT_ID(#) was called for the current statement
01551 private:
01552   class impl_c;
01553 
01554   bool free_cached_table(boost::mutex::scoped_lock &scopedLock);
01555 
01556   bool resetUsage()
01557   {
01558     return not getrusage(RUSAGE_THREAD, &usage);
01559   }
01560 
01561   session::TableMessages _table_message_cache;
01562   boost::scoped_ptr<impl_c> impl_;
01563   catalog::Instance::shared_ptr _catalog;
01564 
01566   message::Transaction *transaction_message;
01567   message::Statement *statement_message;
01568   /* Pointer to the current resultset of Select query */
01569   message::Resultset *resultset;
01570   plugin::EventObserverList *session_event_observers;
01571 
01572   /* Schema observers are mapped to databases. */
01573   typedef std::map<std::string, plugin::EventObserverList*> schema_event_observers_t;
01574   schema_event_observers_t schema_event_observers;
01575 
01576   uint64_t xa_id;
01577   const char *proc_info;
01578   bool abort_on_warning;
01579   bool concurrent_execute_allowed;
01580   bool tablespace_op; 
01581   bool use_usage;
01582   session::PropertyMap life_properties;
01583   std::vector<table::Singular *> temporary_shares;
01584   rusage usage;
01585 };
01586 
01587 #define ESCAPE_CHARS "ntrb0ZN" // keep synchronous with READ_INFO::unescape
01588 
01589 /* Bits in sql_command_flags */
01590 
01591 enum sql_command_flag_bits
01592 {
01593   CF_BIT_CHANGES_DATA,
01594   CF_BIT_HAS_ROW_COUNT,
01595   CF_BIT_STATUS_COMMAND,
01596   CF_BIT_SHOW_TABLE_COMMAND,
01597   CF_BIT_WRITE_LOGS_COMMAND,
01598   CF_BIT_SIZE
01599 };
01600 
01601 static const std::bitset<CF_BIT_SIZE> CF_CHANGES_DATA(1 << CF_BIT_CHANGES_DATA);
01602 static const std::bitset<CF_BIT_SIZE> CF_HAS_ROW_COUNT(1 << CF_BIT_HAS_ROW_COUNT);
01603 static const std::bitset<CF_BIT_SIZE> CF_STATUS_COMMAND(1 << CF_BIT_STATUS_COMMAND);
01604 static const std::bitset<CF_BIT_SIZE> CF_SHOW_TABLE_COMMAND(1 << CF_BIT_SHOW_TABLE_COMMAND);
01605 static const std::bitset<CF_BIT_SIZE> CF_WRITE_LOGS_COMMAND(1 << CF_BIT_WRITE_LOGS_COMMAND);
01606 
01607 namespace display  {
01608 const std::string &type(drizzled::Session::global_read_lock_t type);
01609 size_t max_string_length(drizzled::Session::global_read_lock_t type);
01610 
01611 } /* namespace display */
01612 
01613 } /* namespace drizzled */
01614