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/*************** Mycat CC Program Source Code File (.CC) ***************/
17/* PROGRAM NAME: MYCAT */
18/* ------------- */
19/* Version 1.6 */
20/* */
21/* Author: Olivier Bertrand 2012 - 2018 */
22/* */
23/* WHAT THIS PROGRAM DOES: */
24/* ----------------------- */
25/* This program are the DB description related routines. */
26/***********************************************************************/
27
28/***********************************************************************/
29/* Include relevant MariaDB header file. */
30/***********************************************************************/
31#define DONT_DEFINE_VOID
32#include <my_global.h>
33
34#if defined(UNIX)
35#include <unistd.h>
36#include <string.h>
37#endif
38#include "handler.h"
39#undef OFFSET
40
41/***********************************************************************/
42/* Include application header files */
43/* */
44/* global.h is header containing all global declarations. */
45/* plgdbsem.h is header containing DB application declarations. */
46/* tabdos.h is header containing TDBDOS classes declarations. */
47/* MYCAT.h is header containing DB description declarations. */
48/***********************************************************************/
49#if defined(UNIX)
50#include "osutil.h"
51#endif // UNIX
52#include "global.h"
53#include "plgdbsem.h"
54//#include "reldef.h"
55#include "xtable.h"
56#include "tabext.h"
57#include "tabcol.h"
58#include "filamtxt.h"
59#include "tabdos.h"
60#include "tabfmt.h"
61#if defined(VCT_SUPPORT)
62#include "tabvct.h"
63#endif // VCT_SUPPORT
64#include "tabsys.h"
65#if defined(__WIN__)
66#include "tabmac.h"
67#include "tabwmi.h"
68#endif // __WIN__
69//#include "tabtbl.h"
70#include "tabxcl.h"
71#include "tabtbl.h"
72#include "taboccur.h"
73#include "tabmul.h"
74#include "tabmysql.h"
75#if defined(ODBC_SUPPORT)
76#define NODBC
77#include "tabodbc.h"
78#endif // ODBC_SUPPORT
79#if defined(JAVA_SUPPORT)
80#define NJDBC
81#include "tabjdbc.h"
82#endif // JAVA_SUPPORT
83#include "tabpivot.h"
84#include "tabvir.h"
85#include "tabjson.h"
86#include "ha_connect.h"
87#if defined(XML_SUPPORT)
88#include "tabxml.h"
89#endif // XML_SUPPORT
90#if defined(JAVA_SUPPORT) || defined(CMGO_SUPPORT)
91#include "mongo.h"
92#endif // JAVA_SUPPORT || CMGO_SUPPORT
93#if defined(ZIP_SUPPORT)
94#include "tabzip.h"
95#endif // ZIP_SUPPORT
96#include "mycat.h"
97
98/***********************************************************************/
99/* Extern static variables. */
100/***********************************************************************/
101#if defined(__WIN__)
102extern "C" HINSTANCE s_hModule; // Saved module handle
103#endif // !__WIN__
104
105#if defined(JAVA_SUPPORT) || defined(CMGO_SUPPORT)
106bool MongoEnabled(void);
107#endif // JAVA_SUPPORT || CMGO_SUPPORT
108
109PQRYRES OEMColumns(PGLOBAL g, PTOS topt, char *tab, char *db, bool info);
110
111/***********************************************************************/
112/* Get the plugin directory. */
113/***********************************************************************/
114char *GetPluginDir(void)
115{
116 return opt_plugin_dir;
117} // end of GetPluginDir
118
119/***********************************************************************/
120/* Get a unique enum table type ID. */
121/***********************************************************************/
122TABTYPE GetTypeID(const char *type)
123 {
124 return (!type) ? TAB_UNDEF
125 : (!stricmp(type, "DOS")) ? TAB_DOS
126 : (!stricmp(type, "FIX")) ? TAB_FIX
127 : (!stricmp(type, "BIN")) ? TAB_BIN
128 : (!stricmp(type, "CSV")) ? TAB_CSV
129 : (!stricmp(type, "FMT")) ? TAB_FMT
130 : (!stricmp(type, "DBF")) ? TAB_DBF
131#if defined(XML_SUPPORT)
132 : (!stricmp(type, "XML")) ? TAB_XML
133#endif
134 : (!stricmp(type, "INI")) ? TAB_INI
135 : (!stricmp(type, "VEC")) ? TAB_VEC
136#if defined(ODBC_SUPPORT)
137 : (!stricmp(type, "ODBC")) ? TAB_ODBC
138#endif
139#if defined(JAVA_SUPPORT)
140 : (!stricmp(type, "JDBC")) ? TAB_JDBC
141#endif
142#if defined(JAVA_SUPPORT) || defined(CMGO_SUPPORT)
143 : (!stricmp(type, "MONGO") && MongoEnabled()) ? TAB_MONGO
144#endif
145 : (!stricmp(type, "MYSQL")) ? TAB_MYSQL
146 : (!stricmp(type, "MYPRX")) ? TAB_MYSQL
147 : (!stricmp(type, "DIR")) ? TAB_DIR
148#if defined(__WIN__)
149 : (!stricmp(type, "MAC")) ? TAB_MAC
150 : (!stricmp(type, "WMI")) ? TAB_WMI
151#endif
152 : (!stricmp(type, "TBL")) ? TAB_TBL
153 : (!stricmp(type, "XCOL")) ? TAB_XCL
154 : (!stricmp(type, "OCCUR")) ? TAB_OCCUR
155 : (!stricmp(type, "CATLG")) ? TAB_PRX // Legacy
156 : (!stricmp(type, "PROXY")) ? TAB_PRX
157 : (!stricmp(type, "PIVOT")) ? TAB_PIVOT
158 : (!stricmp(type, "VIR")) ? TAB_VIR
159 : (!stricmp(type, "JSON")) ? TAB_JSON
160#if defined(ZIP_SUPPORT)
161 : (!stricmp(type, "ZIP")) ? TAB_ZIP
162#endif
163 : (!stricmp(type, "OEM")) ? TAB_OEM : TAB_NIY;
164 } // end of GetTypeID
165
166/***********************************************************************/
167/* Return true for table types based on file. */
168/***********************************************************************/
169bool IsFileType(TABTYPE type)
170 {
171 bool isfile;
172
173 switch (type) {
174 case TAB_DOS:
175 case TAB_FIX:
176 case TAB_BIN:
177 case TAB_CSV:
178 case TAB_FMT:
179 case TAB_DBF:
180 case TAB_XML:
181 case TAB_INI:
182 case TAB_VEC:
183 case TAB_JSON:
184// case TAB_ZIP:
185 isfile= true;
186 break;
187 default:
188 isfile= false;
189 break;
190 } // endswitch type
191
192 return isfile;
193 } // end of IsFileType
194
195/***********************************************************************/
196/* Return true for table types returning exact row count. */
197/***********************************************************************/
198bool IsExactType(TABTYPE type)
199 {
200 bool exact;
201
202 switch (type) {
203 case TAB_FIX:
204 case TAB_BIN:
205 case TAB_DBF:
206// case TAB_XML: depends on Multiple || Xpand || Coltype
207// case TAB_JSON: depends on Multiple || Xpand || Coltype
208 case TAB_VEC:
209 case TAB_VIR:
210 exact= true;
211 break;
212 default:
213 exact= false;
214 break;
215 } // endswitch type
216
217 return exact;
218 } // end of IsExactType
219
220/***********************************************************************/
221/* Return true for table types accepting null fields. */
222/***********************************************************************/
223bool IsTypeNullable(TABTYPE type)
224 {
225 bool nullable;
226
227 switch (type) {
228 case TAB_MAC:
229 case TAB_DIR:
230 nullable= false;
231 break;
232 default:
233 nullable= true;
234 break;
235 } // endswitch type
236
237 return nullable;
238 } // end of IsTypeNullable
239
240/***********************************************************************/
241/* Return true for fixed record length tables. */
242/***********************************************************************/
243bool IsTypeFixed(TABTYPE type)
244 {
245 bool fix;
246
247 switch (type) {
248 case TAB_FIX:
249 case TAB_BIN:
250 case TAB_VEC:
251// case TAB_DBF: ???
252 fix= true;
253 break;
254 default:
255 fix= false;
256 break;
257 } // endswitch type
258
259 return fix;
260 } // end of IsTypeFixed
261
262/***********************************************************************/
263/* Return true for table indexable by XINDEX. */
264/***********************************************************************/
265bool IsTypeIndexable(TABTYPE type)
266 {
267 bool idx;
268
269 switch (type) {
270 case TAB_DOS:
271 case TAB_CSV:
272 case TAB_FMT:
273 case TAB_FIX:
274 case TAB_BIN:
275 case TAB_VEC:
276 case TAB_DBF:
277 case TAB_JSON:
278 idx= true;
279 break;
280 default:
281 idx= false;
282 break;
283 } // endswitch type
284
285 return idx;
286 } // end of IsTypeIndexable
287
288/***********************************************************************/
289/* Return index type: 0 NO, 1 XINDEX, 2 REMOTE. */
290/***********************************************************************/
291int GetIndexType(TABTYPE type)
292 {
293 int xtyp;
294
295 switch (type) {
296 case TAB_DOS:
297 case TAB_CSV:
298 case TAB_FMT:
299 case TAB_FIX:
300 case TAB_BIN:
301 case TAB_VEC:
302 case TAB_DBF:
303 case TAB_JSON:
304 xtyp= 1;
305 break;
306 case TAB_MYSQL:
307 case TAB_ODBC:
308 case TAB_JDBC:
309 case TAB_MONGO:
310 xtyp= 2;
311 break;
312 case TAB_VIR:
313 xtyp= 3;
314 break;
315 default:
316 xtyp= 0;
317 break;
318 } // endswitch type
319
320 return xtyp;
321 } // end of GetIndexType
322
323/***********************************************************************/
324/* Get a unique enum catalog function ID. */
325/***********************************************************************/
326uint GetFuncID(const char *func)
327 {
328 uint fnc;
329
330 if (!func)
331 fnc= FNC_NO;
332 else if (!strnicmp(func, "col", 3))
333 fnc= FNC_COL;
334 else if (!strnicmp(func, "tab", 3))
335 fnc= FNC_TABLE;
336 else if (!stricmp(func, "dsn") ||
337 !strnicmp(func, "datasource", 10) ||
338 !strnicmp(func, "source", 6) ||
339 !strnicmp(func, "sqldatasource", 13))
340 fnc= FNC_DSN;
341 else if (!strnicmp(func, "driver", 6) ||
342 !strnicmp(func, "sqldriver", 9))
343 fnc= FNC_DRIVER;
344 else
345 fnc= FNC_NIY;
346
347 return fnc;
348 } // end of GetFuncID
349
350/***********************************************************************/
351/* OEMColumn: Get table column info for an OEM table. */
352/***********************************************************************/
353PQRYRES OEMColumns(PGLOBAL g, PTOS topt, char *tab, char *db, bool info)
354 {
355 typedef PQRYRES (__stdcall *XCOLDEF) (PGLOBAL, void*, char*, char*, bool);
356 const char *module, *subtype;
357 char c, soname[_MAX_PATH], getname[40] = "Col";
358#if defined(__WIN__)
359 HANDLE hdll; /* Handle to the external DLL */
360#else // !__WIN__
361 void *hdll; /* Handle for the loaded shared library */
362#endif // !__WIN__
363 XCOLDEF coldef = NULL;
364 PQRYRES qrp = NULL;
365
366 module = topt->module;
367 subtype = topt->subtype;
368
369 if (!module || !subtype)
370 return NULL;
371
372 /*********************************************************************/
373 /* Ensure that the .dll doesn't have a path. */
374 /* This is done to ensure that only approved dll from the system */
375 /* directories are used (to make this even remotely secure). */
376 /*********************************************************************/
377 if (check_valid_path(module, strlen(module))) {
378 strcpy(g->Message, "Module cannot contain a path");
379 return NULL;
380 } else
381 PlugSetPath(soname, module, GetPluginDir());
382
383 // The exported name is always in uppercase
384 for (int i = 0; ; i++) {
385 c = subtype[i];
386 getname[i + 3] = toupper(c);
387 if (!c) break;
388 } // endfor i
389
390#if defined(__WIN__)
391 // Load the Dll implementing the table
392 if (!(hdll = LoadLibrary(soname))) {
393 char buf[256];
394 DWORD rc = GetLastError();
395
396 sprintf(g->Message, MSG(DLL_LOAD_ERROR), rc, soname);
397 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
398 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, rc, 0,
399 (LPTSTR)buf, sizeof(buf), NULL);
400 strcat(strcat(g->Message, ": "), buf);
401 return NULL;
402 } // endif hDll
403
404 // Get the function returning an instance of the external DEF class
405 if (!(coldef = (XCOLDEF)GetProcAddress((HINSTANCE)hdll, getname))) {
406 sprintf(g->Message, MSG(PROCADD_ERROR), GetLastError(), getname);
407 FreeLibrary((HMODULE)hdll);
408 return NULL;
409 } // endif coldef
410#else // !__WIN__
411 const char *error = NULL;
412
413 // Load the desired shared library
414 if (!(hdll = dlopen(soname, RTLD_LAZY))) {
415 error = dlerror();
416 sprintf(g->Message, MSG(SHARED_LIB_ERR), soname, SVP(error));
417 return NULL;
418 } // endif Hdll
419
420 // Get the function returning an instance of the external DEF class
421 if (!(coldef = (XCOLDEF)dlsym(hdll, getname))) {
422 error = dlerror();
423 sprintf(g->Message, MSG(GET_FUNC_ERR), getname, SVP(error));
424 dlclose(hdll);
425 return NULL;
426 } // endif coldef
427#endif // !__WIN__
428
429 // Just in case the external Get function does not set error messages
430 sprintf(g->Message, "Error getting column info from %s", subtype);
431
432 // Get the table column definition
433 qrp = coldef(g, topt, tab, db, info);
434
435#if defined(__WIN__)
436 FreeLibrary((HMODULE)hdll);
437#else // !__WIN__
438 dlclose(hdll);
439#endif // !__WIN__
440
441 return qrp;
442 } // end of OEMColumns
443
444/* ------------------------- Class CATALOG --------------------------- */
445
446/***********************************************************************/
447/* CATALOG Constructor. */
448/***********************************************************************/
449CATALOG::CATALOG(void)
450 {
451#if defined(__WIN__)
452//DataPath= ".\\";
453#else // !__WIN__
454//DataPath= "./";
455#endif // !__WIN__
456 memset(&Ctb, 0, sizeof(CURTAB));
457 Cbuf= NULL;
458 Cblen= 0;
459 DefHuge= false;
460 } // end of CATALOG constructor
461
462/* -------------------------- Class MYCAT ---------------------------- */
463
464/***********************************************************************/
465/* MYCAT Constructor. */
466/***********************************************************************/
467MYCAT::MYCAT(PHC hc) : CATALOG()
468 {
469 Hc= hc;
470 DefHuge= false;
471 } // end of MYCAT constructor
472
473/***********************************************************************/
474/* Nothing to do for CONNECT. */
475/***********************************************************************/
476void MYCAT::Reset(void)
477 {
478 } // end of Reset
479
480/***********************************************************************/
481/* GetTableDesc: retrieve a table descriptor. */
482/* Look for a table descriptor matching the name and type. */
483/***********************************************************************/
484PRELDEF MYCAT::GetTableDesc(PGLOBAL g, PTABLE tablep,
485 LPCSTR type, PRELDEF *)
486 {
487 if (trace(1))
488 printf("GetTableDesc: name=%s am=%s\n", tablep->GetName(), SVP(type));
489
490 // If not specified get the type of this table
491 if (!type)
492 type= Hc->GetStringOption("Type","*");
493
494 return MakeTableDesc(g, tablep, type);
495 } // end of GetTableDesc
496
497/***********************************************************************/
498/* MakeTableDesc: make a table/view description. */
499/* Note: caller must check if name already exists before calling it. */
500/***********************************************************************/
501PRELDEF MYCAT::MakeTableDesc(PGLOBAL g, PTABLE tablep, LPCSTR am)
502 {
503 TABTYPE tc;
504 LPCSTR name = (PSZ)PlugDup(g, tablep->GetName());
505 LPCSTR schema = (PSZ)PlugDup(g, tablep->GetSchema());
506 PRELDEF tdp= NULL;
507
508 if (trace(1))
509 printf("MakeTableDesc: name=%s schema=%s am=%s\n",
510 name, SVP(schema), SVP(am));
511
512 /*********************************************************************/
513 /* Get a unique enum identifier for types. */
514 /*********************************************************************/
515 tc= GetTypeID(am);
516
517 switch (tc) {
518 case TAB_FIX:
519 case TAB_BIN:
520 case TAB_DBF:
521 case TAB_DOS: tdp= new(g) DOSDEF; break;
522 case TAB_CSV:
523 case TAB_FMT: tdp= new(g) CSVDEF; break;
524 case TAB_INI: tdp= new(g) INIDEF; break;
525 case TAB_DIR: tdp= new(g) DIRDEF; break;
526#if defined(XML_SUPPORT)
527 case TAB_XML: tdp= new(g) XMLDEF; break;
528#endif // XML_SUPPORT
529#if defined(VCT_SUPPORT)
530 case TAB_VEC: tdp = new(g) VCTDEF; break;
531#endif // VCT_SUPPORT
532#if defined(ODBC_SUPPORT)
533 case TAB_ODBC: tdp= new(g) ODBCDEF; break;
534#endif // ODBC_SUPPORT
535#if defined(JAVA_SUPPORT)
536 case TAB_JDBC: tdp= new(g) JDBCDEF; break;
537#endif // JAVA_SUPPORT
538#if defined(__WIN__)
539 case TAB_MAC: tdp= new(g) MACDEF; break;
540 case TAB_WMI: tdp= new(g) WMIDEF; break;
541#endif // __WIN__
542 case TAB_OEM: tdp= new(g) OEMDEF; break;
543 case TAB_TBL: tdp= new(g) TBLDEF; break;
544 case TAB_XCL: tdp= new(g) XCLDEF; break;
545 case TAB_PRX: tdp= new(g) PRXDEF; break;
546 case TAB_OCCUR: tdp= new(g) OCCURDEF; break;
547 case TAB_MYSQL: tdp= new(g) MYSQLDEF; break;
548 case TAB_PIVOT: tdp= new(g) PIVOTDEF; break;
549 case TAB_VIR: tdp= new(g) VIRDEF; break;
550 case TAB_JSON: tdp= new(g) JSONDEF; break;
551#if defined(ZIP_SUPPORT)
552 case TAB_ZIP: tdp = new(g) ZIPDEF; break;
553#endif // ZIP_SUPPORT
554#if defined(JAVA_SUPPORT) || defined(CMGO_SUPPORT)
555 case TAB_MONGO:
556 if (MongoEnabled()) {
557 tdp = new(g) MGODEF;
558 break;
559 } // endif enabled
560 // fall through
561#endif // JAVA_SUPPORT || CMGO_SUPPORT
562 default:
563 sprintf(g->Message, MSG(BAD_TABLE_TYPE), am, name);
564 } // endswitch
565
566 // Do make the table/view definition
567 if (tdp && tdp->Define(g, this, name, schema, am))
568 tdp= NULL;
569
570 return tdp;
571 } // end of MakeTableDesc
572
573/***********************************************************************/
574/* Initialize a Table Description Block construction. */
575/***********************************************************************/
576PTDB MYCAT::GetTable(PGLOBAL g, PTABLE tablep, MODE mode, LPCSTR type)
577 {
578 PRELDEF tdp;
579 PTDB tdbp= NULL;
580// LPCSTR name= tablep->GetName();
581
582 if (trace(1))
583 printf("GetTableDB: name=%s\n", tablep->GetName());
584
585 // Look for the description of the requested table
586 tdp= GetTableDesc(g, tablep, type);
587
588 if (tdp) {
589 if (trace(1))
590 printf("tdb=%p type=%s\n", tdp, tdp->GetType());
591
592 if (tablep->GetSchema())
593 tdp->Database = SetPath(g, tablep->GetSchema());
594
595 tdbp= tdp->GetTable(g, mode);
596 } // endif tdp
597
598 if (tdbp) {
599 if (trace(1))
600 printf("tdbp=%p name=%s amtype=%d\n", tdbp, tdbp->GetName(),
601 tdbp->GetAmType());
602 tablep->SetTo_Tdb(tdbp);
603 tdbp->SetTable(tablep);
604 tdbp->SetMode(mode);
605 } // endif tdbp
606
607 return (tdbp);
608 } // end of GetTable
609
610/***********************************************************************/
611/* ClearDB: Terminates Database usage. */
612/***********************************************************************/
613void MYCAT::ClearDB(PGLOBAL)
614 {
615 } // end of ClearDB
616
617/* ------------------------ End of MYCAT --------------------------- */
618