1 /* Copyright (c) 2004, 2017, 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, version 2.0,
5   as published by the Free Software Foundation.
6 
7   This program is also distributed with certain software (including
8   but not limited to OpenSSL) that is licensed under separate terms,
9   as designated in a particular file or component or in included license
10   documentation.  The authors of MySQL hereby grant you an additional
11   permission to link the program and your derivative works with the
12   separately licensed software that they have included with MySQL.
13 
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License, version 2.0, for more details.
18 
19   You should have received a copy of the GNU General Public License
20   along with this program; if not, write to the Free Software
21   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
22 
23 /** @file ha_example.h
24 
25     @brief
26   The ha_example engine is a stubbed storage engine for example purposes only;
27   it does nothing at this point. Its purpose is to provide a source
28   code illustration of how to begin writing new storage engines; see also
29   /storage/example/ha_example.cc.
30 
31     @note
32   Please read ha_example.cc before reading this file.
33   Reminder: The example storage engine implements all methods that are
34   *required* to be implemented. For a full list of all methods that you can
35   implement, see handler.h.
36 
37    @see
38   /sql/handler.h and /storage/example/ha_example.cc
39 */
40 
41 #include <sys/types.h>
42 
43 #include "my_base.h" /* ha_rows */
44 #include "my_compiler.h"
45 #include "my_inttypes.h"
46 #include "sql/handler.h" /* handler */
47 #include "thr_lock.h"    /* THR_LOCK, THR_LOCK_DATA */
48 
49 /** @brief
50   Example_share is a class that will be shared among all open handlers.
51   This example implements the minimum of what you will probably need.
52 */
53 class Example_share : public Handler_share {
54  public:
55   THR_LOCK lock;
56   Example_share();
~Example_share()57   ~Example_share() { thr_lock_delete(&lock); }
58 };
59 
60 /** @brief
61   Class definition for the storage engine
62 */
63 class ha_example : public handler {
64   THR_LOCK_DATA lock;          ///< MySQL lock
65   Example_share *share;        ///< Shared lock info
66   Example_share *get_share();  ///< Get the share
67 
68  public:
69   ha_example(handlerton *hton, TABLE_SHARE *table_arg);
~ha_example()70   ~ha_example() {}
71 
72   /** @brief
73     The name that will be used for display purposes.
74    */
table_type()75   const char *table_type() const { return "EXAMPLE"; }
76 
77   /**
78     Replace key algorithm with one supported by SE, return the default key
79     algorithm for SE if explicit key algorithm was not provided.
80 
81     @sa handler::adjust_index_algorithm().
82   */
get_default_index_algorithm()83   virtual enum ha_key_alg get_default_index_algorithm() const {
84     return HA_KEY_ALG_HASH;
85   }
is_index_algorithm_supported(enum ha_key_alg key_alg)86   virtual bool is_index_algorithm_supported(enum ha_key_alg key_alg) const {
87     return key_alg == HA_KEY_ALG_HASH;
88   }
89 
90   /** @brief
91     This is a list of flags that indicate what functionality the storage engine
92     implements. The current table flags are documented in handler.h
93   */
table_flags()94   ulonglong table_flags() const {
95     /*
96       We are saying that this engine is just statement capable to have
97       an engine that can only handle statement-based logging. This is
98       used in testing.
99     */
100     return HA_BINLOG_STMT_CAPABLE;
101   }
102 
103   /** @brief
104     This is a bitmap of flags that indicates how the storage engine
105     implements indexes. The current index flags are documented in
106     handler.h. If you do not implement indexes, just return zero here.
107 
108       @details
109     part is the key part to check. First key part is 0.
110     If all_parts is set, MySQL wants to know the flags for the combined
111     index, up to and including 'part'.
112   */
index_flags(uint inx MY_ATTRIBUTE ((unused)),uint part MY_ATTRIBUTE ((unused)),bool all_parts MY_ATTRIBUTE ((unused)))113   ulong index_flags(uint inx MY_ATTRIBUTE((unused)),
114                     uint part MY_ATTRIBUTE((unused)),
115                     bool all_parts MY_ATTRIBUTE((unused))) const {
116     return 0;
117   }
118 
119   /** @brief
120     unireg.cc will call max_supported_record_length(), max_supported_keys(),
121     max_supported_key_parts(), uint max_supported_key_length()
122     to make sure that the storage engine can handle the data it is about to
123     send. Return *real* limits of your storage engine here; MySQL will do
124     min(your_limits, MySQL_limits) automatically.
125    */
max_supported_record_length()126   uint max_supported_record_length() const { return HA_MAX_REC_LENGTH; }
127 
128   /** @brief
129     unireg.cc will call this to make sure that the storage engine can handle
130     the data it is about to send. Return *real* limits of your storage engine
131     here; MySQL will do min(your_limits, MySQL_limits) automatically.
132 
133       @details
134     There is no need to implement ..._key_... methods if your engine doesn't
135     support indexes.
136    */
max_supported_keys()137   uint max_supported_keys() const { return 0; }
138 
139   /** @brief
140     unireg.cc will call this to make sure that the storage engine can handle
141     the data it is about to send. Return *real* limits of your storage engine
142     here; MySQL will do min(your_limits, MySQL_limits) automatically.
143 
144       @details
145     There is no need to implement ..._key_... methods if your engine doesn't
146     support indexes.
147    */
max_supported_key_parts()148   uint max_supported_key_parts() const { return 0; }
149 
150   /** @brief
151     unireg.cc will call this to make sure that the storage engine can handle
152     the data it is about to send. Return *real* limits of your storage engine
153     here; MySQL will do min(your_limits, MySQL_limits) automatically.
154 
155       @details
156     There is no need to implement ..._key_... methods if your engine doesn't
157     support indexes.
158    */
max_supported_key_length()159   uint max_supported_key_length() const { return 0; }
160 
161   /** @brief
162     Called in test_quick_select to determine if indexes should be used.
163   */
scan_time()164   virtual double scan_time() {
165     return (double)(stats.records + stats.deleted) / 20.0 + 10;
166   }
167 
168   /** @brief
169     This method will never be called if you do not implement indexes.
170   */
read_time(uint,uint,ha_rows rows)171   virtual double read_time(uint, uint, ha_rows rows) {
172     return (double)rows / 20.0 + 1;
173   }
174 
175   /*
176     Everything below are methods that we implement in ha_example.cc.
177 
178     Most of these methods are not obligatory, skip them and
179     MySQL will treat them as not implemented
180   */
181   /** @brief
182     We implement this in ha_example.cc; it's a required method.
183   */
184   int open(const char *name, int mode, uint test_if_locked,
185            const dd::Table *table_def);  // required
186 
187   /** @brief
188     We implement this in ha_example.cc; it's a required method.
189   */
190   int close(void);  // required
191 
192   /** @brief
193     We implement this in ha_example.cc. It's not an obligatory method;
194     skip it and and MySQL will treat it as not implemented.
195   */
196   int write_row(uchar *buf);
197 
198   /** @brief
199     We implement this in ha_example.cc. It's not an obligatory method;
200     skip it and and MySQL will treat it as not implemented.
201   */
202   int update_row(const uchar *old_data, uchar *new_data);
203 
204   /** @brief
205     We implement this in ha_example.cc. It's not an obligatory method;
206     skip it and and MySQL will treat it as not implemented.
207   */
208   int delete_row(const uchar *buf);
209 
210   /** @brief
211     We implement this in ha_example.cc. It's not an obligatory method;
212     skip it and and MySQL will treat it as not implemented.
213   */
214   int index_read_map(uchar *buf, const uchar *key, key_part_map keypart_map,
215                      enum ha_rkey_function find_flag);
216 
217   /** @brief
218     We implement this in ha_example.cc. It's not an obligatory method;
219     skip it and and MySQL will treat it as not implemented.
220   */
221   int index_next(uchar *buf);
222 
223   /** @brief
224     We implement this in ha_example.cc. It's not an obligatory method;
225     skip it and and MySQL will treat it as not implemented.
226   */
227   int index_prev(uchar *buf);
228 
229   /** @brief
230     We implement this in ha_example.cc. It's not an obligatory method;
231     skip it and and MySQL will treat it as not implemented.
232   */
233   int index_first(uchar *buf);
234 
235   /** @brief
236     We implement this in ha_example.cc. It's not an obligatory method;
237     skip it and and MySQL will treat it as not implemented.
238   */
239   int index_last(uchar *buf);
240 
241   /** @brief
242     Unlike index_init(), rnd_init() can be called two consecutive times
243     without rnd_end() in between (it only makes sense if scan=1). In this
244     case, the second call should prepare for the new table scan (e.g if
245     rnd_init() allocates the cursor, the second call should position the
246     cursor to the start of the table; no need to deallocate and allocate
247     it again. This is a required method.
248   */
249   int rnd_init(bool scan);  // required
250   int rnd_end();
251   int rnd_next(uchar *buf);             ///< required
252   int rnd_pos(uchar *buf, uchar *pos);  ///< required
253   void position(const uchar *record);   ///< required
254   int info(uint);                       ///< required
255   int extra(enum ha_extra_function operation);
256   int external_lock(THD *thd, int lock_type);  ///< required
257   int delete_all_rows(void);
258   ha_rows records_in_range(uint inx, key_range *min_key, key_range *max_key);
259   int delete_table(const char *from, const dd::Table *table_def);
260   int rename_table(const char *from, const char *to,
261                    const dd::Table *from_table_def, dd::Table *to_table_def);
262   int create(const char *name, TABLE *form, HA_CREATE_INFO *create_info,
263              dd::Table *table_def);  ///< required
264 
265   THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to,
266                              enum thr_lock_type lock_type);  ///< required
267 };
268