1/* Copyright (C) MariaDB Corporation Ab
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 Street, Fifth Floor, Boston, MA 02111-1301 USA */
15
16/** @file ha_connect.h
17 Author Olivier Bertrand
18
19 @brief
20 The ha_connect engine is a prototype storage engine to access external data.
21
22 @see
23 /sql/handler.h and /storage/connect/ha_connect.cc
24*/
25
26#ifdef USE_PRAGMA_INTERFACE
27#pragma interface /* gcc class implementation */
28#endif
29
30/****************************************************************************/
31/* mycat.h contains the TOS, PTOS, ha_table_option_struct declarations. */
32/****************************************************************************/
33#include "mycat.h"
34
35/****************************************************************************/
36/* Structures used to pass info between CONNECT and ha_connect. */
37/****************************************************************************/
38typedef struct _create_xinfo {
39 char *Type; /* Retrieved from table comment */
40 char *Filename; /* Set if not standard */
41 char *IndexFN; /* Set if not standard */
42 ulonglong Maxrows; /* Estimated max nb of rows */
43 ulong Lrecl; /* Set if not default */
44 ulong Elements; /* Number of lines in blocks */
45 bool Fixed; /* False for DOS type */
46 void *Pcf; /* To list of columns */
47 void *Pxdf; /* To list of indexes */
48} CRXINFO, *PCXF;
49
50typedef struct _xinfo {
51 ulonglong data_file_length; /* Length of data file */
52 ha_rows records; /* Records in table */
53 ulong mean_rec_length; /* Physical record length */
54 char *data_file_name; /* Physical file name */
55} XINFO, *PXF;
56
57class XCHK : public BLOCK {
58public:
59 XCHK(void) {oldsep= newsep= false;
60 oldopn= newopn= NULL;
61 oldpix= newpix= NULL;}
62
63 inline char *SetName(PGLOBAL g, PCSZ name) {return PlugDup(g, name);}
64
65 bool oldsep; // Sepindex before create/alter
66 bool newsep; // Sepindex after create/alter
67 char *oldopn; // Optname before create/alter
68 char *newopn; // Optname after create/alter
69 PIXDEF oldpix; // The indexes before create/alter
70 PIXDEF newpix; // The indexes after create/alter
71}; // end of class XCHK
72
73typedef class XCHK *PCHK;
74typedef class user_connect *PCONNECT;
75typedef struct ha_field_option_struct FOS, *PFOS;
76typedef struct ha_index_option_struct XOS, *PXOS;
77
78extern handlerton *connect_hton;
79
80/**
81 structure for CREATE TABLE options (table options)
82
83 These can be specified in the CREATE TABLE:
84 CREATE TABLE ( ... ) {...here...}
85
86 ------ Was moved to mycat.h ------
87 */
88
89/**
90 structure for CREATE TABLE options (field options)
91
92 These can be specified in the CREATE TABLE per field:
93 CREATE TABLE ( field ... {...here...}, ... )
94*/
95struct ha_field_option_struct
96{
97 ulonglong offset;
98 ulonglong freq;
99 ulonglong fldlen;
100 uint opt;
101 const char *dateformat;
102 const char *fieldformat;
103 char *special;
104};
105
106/*
107 index options can be declared similarly
108 using the ha_index_option_struct structure.
109
110 Their values can be specified in the CREATE TABLE per index:
111 CREATE TABLE ( field ..., .., INDEX .... *here*, ... )
112*/
113struct ha_index_option_struct
114{
115 bool dynamic;
116 bool mapped;
117};
118
119/** @brief
120 CONNECT_SHARE is a structure that will be shared among all open handlers.
121 This example implements the minimum of what you will probably need.
122*/
123class CONNECT_SHARE : public Handler_share {
124public:
125 mysql_mutex_t mutex;
126 THR_LOCK lock;
127 CONNECT_SHARE()
128 {
129 thr_lock_init(&lock);
130 }
131 ~CONNECT_SHARE()
132 {
133 thr_lock_delete(&lock);
134 mysql_mutex_destroy(&mutex);
135 }
136};
137
138typedef class ha_connect *PHC;
139
140/** @brief
141 Class definition for the storage engine
142*/
143class ha_connect: public handler
144{
145 THR_LOCK_DATA lock; ///< MySQL lock
146 CONNECT_SHARE *share; ///< Shared lock info
147 CONNECT_SHARE *get_share();
148
149protected:
150 char *PlugSubAllocStr(PGLOBAL g, void *memp, const char *str, size_t length)
151 {
152 char *ptr= (char*)PlgDBSubAlloc(g, memp, length + 1);
153
154 if (ptr) {
155 memcpy(ptr, str, length);
156 ptr[length]= '\0';
157 } // endif ptr
158
159 return ptr;
160 } // end of PlugSubAllocStr
161
162public:
163 ha_connect(handlerton *hton, TABLE_SHARE *table_arg);
164 ~ha_connect();
165
166 // CONNECT Implementation
167//static bool connect_init(void);
168//static bool connect_end(void);
169 TABTYPE GetRealType(PTOS pos= NULL);
170 char *GetRealString(PCSZ s);
171 PCSZ GetStringOption(PCSZ opname, PCSZ sdef= NULL);
172 PTOS GetTableOptionStruct(TABLE_SHARE *s= NULL);
173 bool GetBooleanOption(PCSZ opname, bool bdef);
174 bool SetBooleanOption(PCSZ opname, bool b);
175 int GetIntegerOption(PCSZ opname);
176 bool GetIndexOption(KEY *kp, PCSZ opname);
177 bool CheckString(PCSZ str1, PCSZ str2);
178 bool SameString(TABLE *tab, PCSZ opn);
179 bool SetIntegerOption(PCSZ opname, int n);
180 bool SameInt(TABLE *tab, PCSZ opn);
181 bool SameBool(TABLE *tab, PCSZ opn);
182 bool FileExists(const char *fn, bool bf);
183 bool NoFieldOptionChange(TABLE *tab);
184 PFOS GetFieldOptionStruct(Field *fp);
185 void *GetColumnOption(PGLOBAL g, void *field, PCOLINFO pcf);
186 PXOS GetIndexOptionStruct(KEY *kp);
187 PIXDEF GetIndexInfo(TABLE_SHARE *s= NULL);
188 bool CheckVirtualIndex(TABLE_SHARE *s);
189 PCSZ GetDBName(PCSZ name);
190 PCSZ GetTableName(void);
191 char *GetPartName(void);
192//int GetColNameLen(Field *fp);
193//char *GetColName(Field *fp);
194//void AddColName(char *cp, Field *fp);
195 TABLE *GetTable(void) {return table;}
196 bool IsSameIndex(PIXDEF xp1, PIXDEF xp2);
197 bool IsPartitioned(void);
198 bool IsUnique(uint n);
199 PCSZ GetDataPath(void) {return datapath;}
200
201 bool SetDataPath(PGLOBAL g, PCSZ path);
202 PTDB GetTDB(PGLOBAL g);
203 int OpenTable(PGLOBAL g, bool del= false);
204 bool CheckColumnList(PGLOBAL g);
205 bool IsOpened(void);
206 int CloseTable(PGLOBAL g);
207 int MakeRecord(char *buf);
208 int ScanRecord(PGLOBAL g, const uchar *buf);
209 int CheckRecord(PGLOBAL g, const uchar *oldbuf, const uchar *newbuf);
210 int ReadIndexed(uchar *buf, OPVAL op, const key_range *kr= NULL);
211 bool IsIndexed(Field *fp);
212 bool MakeKeyWhere(PGLOBAL g, PSTRG qry, OPVAL op, char q,
213 const key_range *kr);
214//inline char *Strz(LEX_STRING &ls);
215 key_range start_key;
216
217
218 /** @brief
219 The name that will be used for display purposes.
220 */
221 const char *table_type() const {return "CONNECT";}
222
223 /** @brief
224 The name of the index type that will be used for display.
225 Don't implement this method unless you really have indexes.
226 */
227 const char *index_type(uint inx);
228
229 /** @brief
230 The file extensions.
231 */
232//const char **bas_ext() const;
233
234 /**
235 Check if a storage engine supports a particular alter table in-place
236 @note Called without holding thr_lock.c lock.
237 */
238 virtual enum_alter_inplace_result
239 check_if_supported_inplace_alter(TABLE *altered_table,
240 Alter_inplace_info *ha_alter_info);
241
242 /** @brief
243 This is a list of flags that indicate what functionality the storage engine
244 implements. The current table flags are documented in handler.h
245 */
246 ulonglong table_flags() const;
247
248 /** @brief
249 This is a bitmap of flags that indicates how the storage engine
250 implements indexes. The current index flags are documented in
251 handler.h. If you do not implement indexes, just return zero here.
252
253 @details
254 part is the key part to check. First key part is 0.
255 If all_parts is set, MySQL wants to know the flags for the combined
256 index, up to and including 'part'.
257 */
258 ulong index_flags(uint inx, uint part, bool all_parts) const;
259
260 /** @brief
261 unireg.cc will call max_supported_record_length(), max_supported_keys(),
262 max_supported_key_parts(), uint max_supported_key_length()
263 to make sure that the storage engine can handle the data it is about to
264 send. Return *real* limits of your storage engine here; MySQL will do
265 min(your_limits, MySQL_limits) automatically.
266 */
267 uint max_supported_record_length() const { return HA_MAX_REC_LENGTH; }
268
269 /** @brief
270 unireg.cc will call this to make sure that the storage engine can handle
271 the data it is about to send. Return *real* limits of your storage engine
272 here; MySQL will do min(your_limits, MySQL_limits) automatically.
273
274 @details
275 There is no need to implement ..._key_... methods if your engine doesn't
276 support indexes.
277 */
278 uint max_supported_keys() const { return 10; }
279
280 /** @brief
281 unireg.cc will call this to make sure that the storage engine can handle
282 the data it is about to send. Return *real* limits of your storage engine
283 here; MySQL will do min(your_limits, MySQL_limits) automatically.
284
285 @details
286 There is no need to implement ..._key_... methods if your engine doesn't
287 support indexes.
288 */
289 uint max_supported_key_parts() const { return 10; }
290
291 /** @brief
292 unireg.cc will call this to make sure that the storage engine can handle
293 the data it is about to send. Return *real* limits of your storage engine
294 here; MySQL will do min(your_limits, MySQL_limits) automatically.
295
296 @details
297 There is no need to implement ..._key_... methods if your engine doesn't
298 support indexes.
299 */
300 uint max_supported_key_length() const { return 255; }
301
302 /** @brief
303 Called in test_quick_select to determine if indexes should be used.
304 */
305 virtual double scan_time() { return (double) (stats.records+stats.deleted) / 20.0+10; }
306
307 /** @brief
308 This method will never be called if you do not implement indexes.
309 */
310 virtual double read_time(uint, uint, ha_rows rows)
311 { return (double) rows / 20.0+1; }
312
313 /*
314 Everything below are methods that we implement in ha_connect.cc.
315
316 Most of these methods are not obligatory, skip them and
317 MySQL will treat them as not implemented
318 */
319 virtual bool get_error_message(int error, String *buf);
320
321 /**
322 Push condition down to the table handler.
323
324 @param cond Condition to be pushed. The condition tree must not be
325 modified by the by the caller.
326
327 @return
328 The 'remainder' condition that caller must use to filter out records.
329 NULL means the handler will not return rows that do not match the
330 passed condition.
331
332 @note
333 The pushed conditions form a stack (from which one can remove the
334 last pushed condition using cond_pop).
335 The table handler filters out rows using (pushed_cond1 AND pushed_cond2
336 AND ... AND pushed_condN)
337 or less restrictive condition, depending on handler's capabilities.
338
339 handler->ha_reset() call empties the condition stack.
340 Calls to rnd_init/rnd_end, index_init/index_end etc do not affect the
341 condition stack.
342 */
343virtual const COND *cond_push(const COND *cond);
344PCFIL CheckCond(PGLOBAL g, PCFIL filp, const Item *cond);
345const char *GetValStr(OPVAL vop, bool neg);
346PFIL CondFilter(PGLOBAL g, Item *cond);
347//PFIL CheckFilter(PGLOBAL g);
348
349/** admin commands - called from mysql_admin_table */
350virtual int check(THD* thd, HA_CHECK_OPT* check_opt)
351{
352 // TODO: implement it
353 return HA_ADMIN_OK; // Just to avoid error message with checktables
354} // end of check
355
356 /**
357 Number of rows in table. It will only be called if
358 (table_flags() & (HA_HAS_RECORDS | HA_STATS_RECORDS_IS_EXACT)) != 0
359 */
360 virtual ha_rows records();
361
362 /**
363 Type of table for caching query
364 CONNECT should not use caching because its tables are external
365 data prone to me modified out of MariaDB
366 */
367 virtual uint8 table_cache_type(void)
368 {
369#if defined(MEMORY_TRACE)
370 // Temporary until bug MDEV-4771 is fixed
371 return HA_CACHE_TBL_NONTRANSACT;
372#else
373 return HA_CACHE_TBL_NOCACHE;
374#endif
375 }
376
377 /** @brief
378 We implement this in ha_connect.cc; it's a required method.
379 */
380 int open(const char *name, int mode, uint test_if_locked); // required
381
382 /** @brief
383 We implement this in ha_connect.cc; it's a required method.
384 */
385 int close(void); // required
386
387 /** @brief
388 We implement this in ha_connect.cc. It's not an obligatory method;
389 skip it and and MySQL will treat it as not implemented.
390 */
391 int write_row(uchar *buf);
392
393 /** @brief
394 We implement this in ha_connect.cc. It's not an obligatory method;
395 skip it and and MySQL will treat it as not implemented.
396 */
397 int update_row(const uchar *old_data, const uchar *new_data);
398
399 /** @brief
400 We implement this in ha_connect.cc. It's not an obligatory method;
401 skip it and and MySQL will treat it as not implemented.
402 */
403 int delete_row(const uchar *buf);
404
405 // Added to the connect handler
406 int index_init(uint idx, bool sorted);
407 int index_end();
408 int index_read(uchar * buf, const uchar * key, uint key_len,
409 enum ha_rkey_function find_flag);
410 int index_next_same(uchar *buf, const uchar *key, uint keylen);
411
412 /** @brief
413 We implement this in ha_connect.cc. It's not an obligatory method;
414 skip it and and MySQL will treat it as not implemented.
415 */
416//int index_read_map(uchar *buf, const uchar *key,
417// key_part_map keypart_map, enum ha_rkey_function find_flag);
418
419 /** @brief
420 We implement this in ha_connect.cc. It's not an obligatory method;
421 skip it and and MySQL will treat it as not implemented.
422 */
423 int index_next(uchar *buf);
424
425 /** @brief
426 We implement this in ha_connect.cc. It's not an obligatory method;
427 skip it and and MySQL will treat it as not implemented.
428 */
429int index_prev(uchar *buf);
430
431 /** @brief
432 We implement this in ha_connect.cc. It's not an obligatory method;
433 skip it and and MySQL will treat it as not implemented.
434 */
435 int index_first(uchar *buf);
436
437 /** @brief
438 We implement this in ha_connect.cc. It's not an obligatory method;
439 skip it and and MySQL will treat it as not implemented.
440 */
441 int index_last(uchar *buf);
442
443 /* Index condition pushdown implementation */
444//Item *idx_cond_push(uint keyno, Item* idx_cond);
445
446 /** @brief
447 Unlike index_init(), rnd_init() can be called two consecutive times
448 without rnd_end() in between (it only makes sense if scan=1). In this
449 case, the second call should prepare for the new table scan (e.g if
450 rnd_init() allocates the cursor, the second call should position the
451 cursor to the start of the table; no need to deallocate and allocate
452 it again. This is a required method.
453 */
454 int rnd_init(bool scan); //required
455 int rnd_end();
456 int rnd_next(uchar *buf); ///< required
457 int rnd_pos(uchar *buf, uchar *pos); ///< required
458 void position(const uchar *record); ///< required
459 int info(uint); ///< required
460 int extra(enum ha_extra_function operation);
461 int start_stmt(THD *thd, thr_lock_type lock_type);
462 int external_lock(THD *thd, int lock_type); ///< required
463 int delete_all_rows(void);
464 ha_rows records_in_range(uint inx, key_range *min_key,
465 key_range *max_key);
466 /**
467 These methods can be overridden, but their default implementation
468 provide useful functionality.
469 */
470 int rename_table(const char *from, const char *to);
471 /**
472 Delete a table in the engine. Called for base as well as temporary
473 tables.
474 */
475 int delete_table(const char *name);
476 /**
477 Called by delete_table and rename_table
478 */
479 int delete_or_rename_table(const char *from, const char *to);
480 int create(const char *name, TABLE *form,
481 HA_CREATE_INFO *create_info); ///< required
482 bool check_if_incompatible_data(HA_CREATE_INFO *info,
483 uint table_changes);
484
485 THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to,
486 enum thr_lock_type lock_type); ///< required
487 int optimize(THD* thd, HA_CHECK_OPT* check_opt);
488
489 /**
490 * Multi Range Read interface
491 */
492 int multi_range_read_init(RANGE_SEQ_IF *seq, void *seq_init_param,
493 uint n_ranges, uint mode, HANDLER_BUFFER *buf);
494 int multi_range_read_next(range_id_t *range_info);
495 ha_rows multi_range_read_info_const(uint keyno, RANGE_SEQ_IF *seq,
496 void *seq_init_param,
497 uint n_ranges, uint *bufsz,
498 uint *flags, Cost_estimate *cost);
499 ha_rows multi_range_read_info(uint keyno, uint n_ranges, uint keys,
500 uint key_parts, uint *bufsz,
501 uint *flags, Cost_estimate *cost);
502 int multi_range_read_explain_info(uint mrr_mode, char *str, size_t size);
503
504 int reset(void) {ds_mrr.dsmrr_close(); return 0;}
505
506 /* Index condition pushdown implementation */
507// Item *idx_cond_push(uint keyno, Item* idx_cond);
508private:
509 DsMrr_impl ds_mrr;
510
511protected:
512 bool check_privileges(THD *thd, PTOS options, const char *dbn, bool quick=false);
513 MODE CheckMode(PGLOBAL g, THD *thd, MODE newmode, bool *chk, bool *cras);
514 char *GetDBfromName(const char *name);
515
516 // Members
517 static ulong num; // Tracable handler number
518 PCONNECT xp; // To user_connect associated class
519 ulong hnum; // The number of this handler
520 query_id_t valid_query_id; // The one when tdbp was allocated
521 query_id_t creat_query_id; // The one when handler was allocated
522 PCSZ datapath; // Is the Path of DB data directory
523 PTDB tdbp; // To table class object
524 PVAL sdvalin1; // Used to convert date values
525 PVAL sdvalin2; // Used to convert date values
526 PVAL sdvalin3; // Used to convert date values
527 PVAL sdvalin4; // Used to convert date values
528 PVAL sdvalout; // Used to convert date values
529 bool istable; // True for table handler
530 char partname[65]; // The partition name
531 MODE xmod; // Table mode
532 XINFO xinfo; // The table info structure
533 bool valid_info; // True if xinfo is valid
534 bool stop; // Used when creating index
535 bool alter; // True when converting to other engine
536 bool mrr; // True when getting index positions
537 bool nox; // True when index should not be made
538 bool abort; // True after error in UPDATE/DELETE
539 int indexing; // Type of indexing for CONNECT
540 int locked; // Table lock
541 MY_BITMAP *part_id; // Columns used for partition func
542 THR_LOCK_DATA lock_data;
543
544public:
545 TABLE_SHARE *tshp; // Used by called tables
546 char *data_file_name;
547 char *index_file_name;
548 uint int_table_flags; // Inherited from MyISAM
549 bool enable_activate_all_index; // Inherited from MyISAM
550}; // end of ha_connect class definition
551