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__) |
102 | extern "C" HINSTANCE s_hModule; // Saved module handle |
103 | #endif // !__WIN__ |
104 | |
105 | #if defined(JAVA_SUPPORT) || defined(CMGO_SUPPORT) |
106 | bool MongoEnabled(void); |
107 | #endif // JAVA_SUPPORT || CMGO_SUPPORT |
108 | |
109 | PQRYRES OEMColumns(PGLOBAL g, PTOS topt, char *tab, char *db, bool info); |
110 | |
111 | /***********************************************************************/ |
112 | /* Get the plugin directory. */ |
113 | /***********************************************************************/ |
114 | char *GetPluginDir(void) |
115 | { |
116 | return opt_plugin_dir; |
117 | } // end of GetPluginDir |
118 | |
119 | /***********************************************************************/ |
120 | /* Get a unique enum table type ID. */ |
121 | /***********************************************************************/ |
122 | TABTYPE 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 | /***********************************************************************/ |
169 | bool 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 | /***********************************************************************/ |
198 | bool 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 | /***********************************************************************/ |
223 | bool 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 | /***********************************************************************/ |
243 | bool 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 | /***********************************************************************/ |
265 | bool 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 | /***********************************************************************/ |
291 | int 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 | /***********************************************************************/ |
326 | uint 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 | /***********************************************************************/ |
353 | PQRYRES 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 | /***********************************************************************/ |
449 | CATALOG::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 | /***********************************************************************/ |
467 | MYCAT::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 | /***********************************************************************/ |
476 | void 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 | /***********************************************************************/ |
484 | PRELDEF 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 | /***********************************************************************/ |
501 | PRELDEF 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 | /***********************************************************************/ |
576 | PTDB 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 | /***********************************************************************/ |
613 | void MYCAT::ClearDB(PGLOBAL) |
614 | { |
615 | } // end of ClearDB |
616 | |
617 | /* ------------------------ End of MYCAT --------------------------- */ |
618 | |