MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ha_federated.h
1 /* Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
2 
3  This program is free software; you can redistribute it and/or modify
4  it under the terms of the GNU General Public License as published by
5  the Free Software Foundation; version 2 of the License.
6 
7  This program is distributed in the hope that it will be useful,
8  but WITHOUT ANY WARRANTY; without even the implied warranty of
9  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  GNU General Public License for more details.
11 
12  You should have received a copy of the GNU General Public License
13  along with this program; if not, write to the Free Software
14  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
15 
16 /*
17  Please read ha_exmple.cc before reading this file.
18  Please keep in mind that the federated storage engine implements all methods
19  that are required to be implemented. handler.h has a full list of methods
20  that you can implement.
21 */
22 
23 #include <mysql.h>
24 
25 /*
26  handler::print_error has a case statement for error numbers.
27  This value is (10000) is far out of range and will envoke the
28  default: case.
29  (Current error range is 120-159 from include/my_base.h)
30 */
31 #define HA_FEDERATED_ERROR_WITH_REMOTE_SYSTEM 10000
32 
33 #define FEDERATED_QUERY_BUFFER_SIZE STRING_BUFFER_USUAL_SIZE * 5
34 #define FEDERATED_RECORDS_IN_RANGE 2
35 #define FEDERATED_MAX_KEY_LENGTH 3500 // Same as innodb
36 
37 /*
38  FEDERATED_SHARE is a structure that will be shared amoung all open handlers
39  The example implements the minimum of what you will probably need.
40 */
41 typedef struct st_federated_share {
42  MEM_ROOT mem_root;
43 
44  bool parsed;
45  /* this key is unique db/tablename */
46  const char *share_key;
47  /*
48  the primary select query to be used in rnd_init
49  */
50  char *select_query;
51  /*
52  remote host info, parse_url supplies
53  */
54  char *server_name;
55  char *connection_string;
56  char *scheme;
57  char *connect_string;
58  char *hostname;
59  char *username;
60  char *password;
61  char *database;
62  char *table_name;
63  char *table;
64  char *socket;
65  char *sport;
66  int share_key_length;
67  ushort port;
68 
69  size_t table_name_length, server_name_length, connect_string_length, use_count;
70  mysql_mutex_t mutex;
71  THR_LOCK lock;
73 
74 /*
75  Class definition for the storage engine
76 */
77 class ha_federated: public handler
78 {
79  THR_LOCK_DATA lock; /* MySQL lock */
80  FEDERATED_SHARE *share; /* Shared lock info */
81  MYSQL *mysql; /* MySQL connection */
82  MYSQL_RES *stored_result;
86  DYNAMIC_ARRAY results;
87  bool position_called;
88  uint fetch_num; // stores the fetch num
89  MYSQL_ROW_OFFSET current_position; // Current position used by ::position()
90  int remote_error_number;
91  char remote_error_buf[FEDERATED_QUERY_BUFFER_SIZE];
92  bool ignore_duplicates, replace_duplicates;
93  bool insert_dup_update;
94  DYNAMIC_STRING bulk_insert;
95 
96 private:
97  /*
98  return 0 on success
99  return errorcode otherwise
100  */
101  uint convert_row_to_internal_format(uchar *buf, MYSQL_ROW row,
102  MYSQL_RES *result);
103  bool create_where_from_key(String *to, KEY *key_info,
104  const key_range *start_key,
105  const key_range *end_key,
106  bool records_in_range, bool eq_range);
107  int stash_remote_error();
108 
109  bool append_stmt_insert(String *query);
110 
111  int read_next(uchar *buf, MYSQL_RES *result);
112  int index_read_idx_with_result_set(uchar *buf, uint index,
113  const uchar *key,
114  uint key_len,
115  ha_rkey_function find_flag,
116  MYSQL_RES **result);
117  int real_query(const char *query, size_t length);
118  int real_connect();
119 public:
120  ha_federated(handlerton *hton, TABLE_SHARE *table_arg);
121  ~ha_federated() {}
122  /* The name that will be used for display purposes */
123  const char *table_type() const { return "FEDERATED"; }
124  /*
125  Next pointer used in transaction
126  */
127  ha_federated *trx_next;
128  /*
129  The name of the index type that will be used for display
130  don't implement this method unless you really have indexes
131  */
132  // perhaps get index type
133  const char *index_type(uint inx) { return "REMOTE"; }
134  const char **bas_ext() const;
135  /*
136  This is a list of flags that says what the storage engine
137  implements. The current table flags are documented in
138  handler.h
139  */
140  ulonglong table_flags() const
141  {
142  /* fix server to be able to get remote server table flags */
143  return (HA_PRIMARY_KEY_IN_READ_INDEX |
144  HA_PRIMARY_KEY_REQUIRED_FOR_POSITION | HA_FILE_BASED |
145  HA_REC_NOT_IN_SEQ | HA_AUTO_PART_KEY | HA_CAN_INDEX_BLOBS |
146  HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE |
147  HA_NO_PREFIX_CHAR_KEYS | HA_PRIMARY_KEY_REQUIRED_FOR_DELETE |
148  HA_NO_TRANSACTIONS /* until fixed by WL#2952 */ |
149  HA_PARTIAL_COLUMN_READ | HA_NULL_IN_KEY |
150  HA_CAN_REPAIR);
151  }
152  /*
153  This is a bitmap of flags that says how the storage engine
154  implements indexes. The current index flags are documented in
155  handler.h. If you do not implement indexes, just return zero
156  here.
157 
158  part is the key part to check. First key part is 0
159  If all_parts it's set, MySQL want to know the flags for the combined
160  index up to and including 'part'.
161  */
162  /* fix server to be able to get remote server index flags */
163  ulong index_flags(uint inx, uint part, bool all_parts) const
164  {
165  return (HA_READ_NEXT | HA_READ_RANGE | HA_READ_AFTER_KEY);
166  }
167  uint max_supported_record_length() const { return HA_MAX_REC_LENGTH; }
168  uint max_supported_keys() const { return MAX_KEY; }
169  uint max_supported_key_parts() const { return MAX_REF_PARTS; }
170  uint max_supported_key_length() const { return FEDERATED_MAX_KEY_LENGTH; }
171  uint max_supported_key_part_length() const { return FEDERATED_MAX_KEY_LENGTH; }
172  /*
173  Called in test_quick_select to determine if indexes should be used.
174  Normally, we need to know number of blocks . For federated we need to
175  know number of blocks on remote side, and number of packets and blocks
176  on the network side (?)
177  Talk to Kostja about this - how to get the
178  number of rows * ...
179  disk scan time on other side (block size, size of the row) + network time ...
180  The reason for "records * 1000" is that such a large number forces
181  this to use indexes "
182  */
183  double scan_time()
184  {
185  DBUG_PRINT("info", ("records %lu", (ulong) stats.records));
186  return (double)(stats.records*1000);
187  }
188  /*
189  The next method will never be called if you do not implement indexes.
190  */
191  double read_time(uint index, uint ranges, ha_rows rows)
192  {
193  /*
194  Per Brian, this number is bugus, but this method must be implemented,
195  and at a later date, he intends to document this issue for handler code
196  */
197  return (double) rows / 20.0+1;
198  }
199 
200  const key_map *keys_to_use_for_scanning() { return &key_map_full; }
201  /*
202  Everything below are methods that we implment in ha_federated.cc.
203 
204  Most of these methods are not obligatory, skip them and
205  MySQL will treat them as not implemented
206  */
207  int open(const char *name, int mode, uint test_if_locked); // required
208  int close(void); // required
209 
210  void start_bulk_insert(ha_rows rows);
211  int end_bulk_insert();
212  int write_row(uchar *buf);
213  int update_row(const uchar *old_data, uchar *new_data);
214  int delete_row(const uchar *buf);
215  int index_init(uint keynr, bool sorted);
216  ha_rows estimate_rows_upper_bound();
217  int index_read(uchar *buf, const uchar *key,
218  uint key_len, enum ha_rkey_function find_flag);
219  int index_read_idx(uchar *buf, uint idx, const uchar *key,
220  uint key_len, enum ha_rkey_function find_flag);
221  int index_next(uchar *buf);
222  int index_end();
223  int read_range_first(const key_range *start_key,
224  const key_range *end_key,
225  bool eq_range, bool sorted);
226  int read_range_next();
227  /*
228  unlike index_init(), rnd_init() can be called two times
229  without rnd_end() in between (it only makes sense if scan=1).
230  then the second call should prepare for the new table scan
231  (e.g if rnd_init allocates the cursor, second call should
232  position it to the start of the table, no need to deallocate
233  and allocate it again
234  */
235  int rnd_init(bool scan); //required
236  int rnd_end();
237  int rnd_next(uchar *buf); //required
238  int rnd_next_int(uchar *buf);
239  int rnd_pos(uchar *buf, uchar *pos); //required
240  void position(const uchar *record); //required
241  int info(uint); //required
242  int extra(ha_extra_function operation);
243 
244  void update_auto_increment(void);
245  int repair(THD* thd, HA_CHECK_OPT* check_opt);
246  int optimize(THD* thd, HA_CHECK_OPT* check_opt);
247 
248  int delete_all_rows(void);
249  int truncate();
250  int create(const char *name, TABLE *form,
251  HA_CREATE_INFO *create_info); //required
252  ha_rows records_in_range(uint inx, key_range *start_key,
253  key_range *end_key);
254  uint8 table_cache_type() { return HA_CACHE_TBL_NOCACHE; }
255 
256  THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to,
257  enum thr_lock_type lock_type); //required
258  bool get_error_message(int error, String *buf);
259 
260  MYSQL_RES *store_result(MYSQL *mysql);
261  void free_result();
262 
263  int external_lock(THD *thd, int lock_type);
264  int connection_commit();
265  int connection_rollback();
266  int connection_autocommit(bool state);
267  int execute_simple_query(const char *query, int len);
268  int reset(void);
269 };
270