1 | /************* RelDef CPP Program Source Code File (.CPP) **************/ |
2 | /* PROGRAM NAME: RELDEF */ |
3 | /* ------------- */ |
4 | /* Version 1.6 */ |
5 | /* */ |
6 | /* COPYRIGHT: */ |
7 | /* ---------- */ |
8 | /* (C) Copyright to the author Olivier BERTRAND 2004-2016 */ |
9 | /* */ |
10 | /* WHAT THIS PROGRAM DOES: */ |
11 | /* ----------------------- */ |
12 | /* This program are the DB definition related routines. */ |
13 | /* */ |
14 | /***********************************************************************/ |
15 | |
16 | /***********************************************************************/ |
17 | /* Include relevant MariaDB header file. */ |
18 | /***********************************************************************/ |
19 | #include "my_global.h" |
20 | #if defined(__WIN__) |
21 | #include <sqlext.h> |
22 | #else |
23 | #include <dlfcn.h> // dlopen(), dlclose(), dlsym() ... |
24 | #include "osutil.h" |
25 | //#include "sqlext.h" |
26 | #endif |
27 | #include "handler.h" |
28 | |
29 | /***********************************************************************/ |
30 | /* Include application header files */ |
31 | /* */ |
32 | /* global.h is header containing all global declarations. */ |
33 | /* plgdbsem.h is header containing DB application declarations. */ |
34 | /* catalog.h is header containing DB description declarations. */ |
35 | /***********************************************************************/ |
36 | #include "global.h" |
37 | #include "plgdbsem.h" |
38 | #include "reldef.h" |
39 | #include "colblk.h" |
40 | #include "tabcol.h" |
41 | #include "filamap.h" |
42 | #include "filamfix.h" |
43 | #if defined(VCT_SUPPORT) |
44 | #include "filamvct.h" |
45 | #endif // VCT_SUPPORT |
46 | #if defined(GZ_SUPPORT) |
47 | #include "filamgz.h" |
48 | #endif // GZ_SUPPORT |
49 | #include "tabdos.h" |
50 | #include "valblk.h" |
51 | #include "tabmul.h" |
52 | #include "ha_connect.h" |
53 | #include "mycat.h" |
54 | |
55 | #if !defined(__WIN__) |
56 | extern handlerton *connect_hton; |
57 | #endif // !__WIN__ |
58 | |
59 | /***********************************************************************/ |
60 | /* External function. */ |
61 | /***********************************************************************/ |
62 | USETEMP UseTemp(void); |
63 | char *GetPluginDir(void); |
64 | |
65 | /* --------------------------- Class RELDEF -------------------------- */ |
66 | |
67 | /***********************************************************************/ |
68 | /* RELDEF Constructor. */ |
69 | /***********************************************************************/ |
70 | RELDEF::RELDEF(void) |
71 | { |
72 | Next = NULL; |
73 | To_Cols = NULL; |
74 | Name = NULL; |
75 | Database = NULL; |
76 | Cat = NULL; |
77 | Hc = NULL; |
78 | } // end of RELDEF constructor |
79 | |
80 | /***********************************************************************/ |
81 | /* This function return a pointer to the Table Option Struct. */ |
82 | /***********************************************************************/ |
83 | PTOS RELDEF::GetTopt(void) |
84 | { |
85 | return Hc->GetTableOptionStruct(); |
86 | } // end of GetTopt |
87 | |
88 | /***********************************************************************/ |
89 | /* This function sets an integer table information. */ |
90 | /***********************************************************************/ |
91 | bool RELDEF::SetIntCatInfo(PCSZ what, int n) |
92 | { |
93 | return Hc->SetIntegerOption(what, n); |
94 | } // end of SetIntCatInfo |
95 | |
96 | /***********************************************************************/ |
97 | /* This function returns integer table information. */ |
98 | /***********************************************************************/ |
99 | int RELDEF::GetIntCatInfo(PCSZ what, int idef) |
100 | { |
101 | int n= Hc->GetIntegerOption(what); |
102 | |
103 | return (n == NO_IVAL) ? idef : n; |
104 | } // end of GetIntCatInfo |
105 | |
106 | /***********************************************************************/ |
107 | /* This function returns Boolean table information. */ |
108 | /***********************************************************************/ |
109 | bool RELDEF::GetBoolCatInfo(PCSZ what, bool bdef) |
110 | { |
111 | bool b= Hc->GetBooleanOption(what, bdef); |
112 | |
113 | return b; |
114 | } // end of GetBoolCatInfo |
115 | |
116 | /***********************************************************************/ |
117 | /* This function returns size catalog information. */ |
118 | /***********************************************************************/ |
119 | int RELDEF::GetSizeCatInfo(PCSZ what, PCSZ sdef) |
120 | { |
121 | char c; |
122 | PCSZ s; |
123 | int i, n= 0; |
124 | |
125 | if (!(s= Hc->GetStringOption(what))) |
126 | s= sdef; |
127 | |
128 | if ((i= sscanf(s, " %d %c " , &n, &c)) == 2) |
129 | switch (toupper(c)) { |
130 | case 'M': |
131 | n *= 1024; |
132 | // fall through |
133 | case 'K': |
134 | n *= 1024; |
135 | } // endswitch c |
136 | |
137 | return n; |
138 | } // end of GetSizeCatInfo |
139 | |
140 | /***********************************************************************/ |
141 | /* This function sets char table information in buf. */ |
142 | /***********************************************************************/ |
143 | int RELDEF::GetCharCatInfo(PCSZ what, PCSZ sdef, char *buf, int size) |
144 | { |
145 | PCSZ s= Hc->GetStringOption(what); |
146 | |
147 | strncpy(buf, ((s) ? s : sdef), size); |
148 | return size; |
149 | } // end of GetCharCatInfo |
150 | |
151 | /***********************************************************************/ |
152 | /* To be used by any TDB's. */ |
153 | /***********************************************************************/ |
154 | bool RELDEF::Partitioned(void) |
155 | { |
156 | return Hc->IsPartitioned(); |
157 | } // end of Partitioned |
158 | |
159 | /***********************************************************************/ |
160 | /* This function returns string table information. */ |
161 | /* Default parameter is "*" to get the handler default. */ |
162 | /***********************************************************************/ |
163 | char *RELDEF::GetStringCatInfo(PGLOBAL g, PCSZ what, PCSZ sdef) |
164 | { |
165 | char *sval = NULL; |
166 | PCSZ name, s= Hc->GetStringOption(what, sdef); |
167 | |
168 | if (s) { |
169 | if (!Hc->IsPartitioned() || |
170 | (stricmp(what, "filename" ) && stricmp(what, "tabname" ) |
171 | && stricmp(what, "connect" ))) |
172 | sval= PlugDup(g, s); |
173 | else |
174 | sval= (char*)s; |
175 | |
176 | } else if (!stricmp(what, "filename" )) { |
177 | // Return default file name |
178 | PCSZ ftype= Hc->GetStringOption("Type" , "*" ); |
179 | int i, n; |
180 | |
181 | if (IsFileType(GetTypeID(ftype))) { |
182 | name= Hc->GetPartName(); |
183 | sval= (char*)PlugSubAlloc(g, NULL, strlen(name) + 12); |
184 | strcat(strcpy(sval, name), "." ); |
185 | n= strlen(sval); |
186 | |
187 | // Fold ftype to lower case |
188 | for (i= 0; i < 12; i++) |
189 | if (!ftype[i]) { |
190 | sval[n+i]= 0; |
191 | break; |
192 | } else |
193 | sval[n+i]= tolower(ftype[i]); |
194 | |
195 | } // endif FileType |
196 | |
197 | } // endif s |
198 | |
199 | return sval; |
200 | } // end of GetStringCatInfo |
201 | |
202 | /* --------------------------- Class TABDEF -------------------------- */ |
203 | |
204 | /***********************************************************************/ |
205 | /* TABDEF Constructor. */ |
206 | /***********************************************************************/ |
207 | TABDEF::TABDEF(void) |
208 | { |
209 | Schema = NULL; |
210 | Desc = NULL; |
211 | Catfunc = FNC_NO; |
212 | Card = 0; |
213 | Elemt = 0; |
214 | Sort = 0; |
215 | Multiple = 0; |
216 | Degree = 0; |
217 | Pseudo = 0; |
218 | Read_Only = false; |
219 | m_data_charset = NULL; |
220 | csname = NULL; |
221 | } // end of TABDEF constructor |
222 | |
223 | /***********************************************************************/ |
224 | /* Define: initialize the table definition block from XDB file. */ |
225 | /***********************************************************************/ |
226 | bool TABDEF::Define(PGLOBAL g, PCATLG cat, |
227 | LPCSTR name, LPCSTR schema, LPCSTR am) |
228 | { |
229 | int poff = 0; |
230 | |
231 | Hc = ((MYCAT*)cat)->GetHandler(); |
232 | Name = (PSZ)name; |
233 | Schema = (PSZ)Hc->GetDBName(schema); |
234 | Cat = cat; |
235 | Catfunc = GetFuncID(GetStringCatInfo(g, "Catfunc" , NULL)); |
236 | Elemt = GetIntCatInfo("Elements" , 0); |
237 | Multiple = GetIntCatInfo("Multiple" , 0); |
238 | Degree = GetIntCatInfo("Degree" , 0); |
239 | Read_Only = GetBoolCatInfo("ReadOnly" , false); |
240 | const char *data_charset_name= GetStringCatInfo(g, "Data_charset" , NULL); |
241 | m_data_charset= data_charset_name ? |
242 | get_charset_by_csname(data_charset_name, MY_CS_PRIMARY, 0): |
243 | NULL; |
244 | csname = GetStringCatInfo(g, "Table_charset" , NULL); |
245 | |
246 | // Get The column definitions |
247 | if ((poff = GetColCatInfo(g)) < 0) |
248 | return true; |
249 | |
250 | // Do the definition of AM specific fields |
251 | return DefineAM(g, am, poff); |
252 | } // end of Define |
253 | |
254 | /***********************************************************************/ |
255 | /* This function returns the database data path. */ |
256 | /***********************************************************************/ |
257 | PCSZ TABDEF::GetPath(void) |
258 | { |
259 | return (Database) ? Database : (Hc) ? Hc->GetDataPath() : NULL; |
260 | } // end of GetPath |
261 | |
262 | /***********************************************************************/ |
263 | /* This function returns column table information. */ |
264 | /***********************************************************************/ |
265 | int TABDEF::GetColCatInfo(PGLOBAL g) |
266 | { |
267 | char *type= GetStringCatInfo(g, "Type" , "*" ); |
268 | char c, fty, eds; |
269 | int i, n, loff, poff, nof, nlg; |
270 | void *field= NULL; |
271 | TABTYPE tc; |
272 | PCOLDEF cdp, lcdp= NULL, tocols= NULL; |
273 | PCOLINFO pcf= (PCOLINFO)PlugSubAlloc(g, NULL, sizeof(COLINFO)); |
274 | |
275 | memset(pcf, 0, sizeof(COLINFO)); |
276 | |
277 | // Get a unique char identifier for type |
278 | tc= (Catfunc == FNC_NO) ? GetTypeID(type) : TAB_PRX; |
279 | |
280 | // Take care of the column definitions |
281 | i= poff= nof= nlg= 0; |
282 | |
283 | #if defined(__WIN__) |
284 | // Offsets of HTML and DIR tables start from 0, DBF at 1 |
285 | loff= (tc == TAB_DBF) ? 1 : (tc == TAB_XML || tc == TAB_DIR) ? -1 : 0; |
286 | #else // !__WIN__ |
287 | // Offsets of HTML tables start from 0, DIR and DBF at 1 |
288 | loff = (tc == TAB_DBF || tc == TAB_DIR) ? 1 : (tc == TAB_XML) ? -1 : 0; |
289 | #endif // !__WIN__ |
290 | |
291 | while (true) { |
292 | // Default Offset depends on table type |
293 | switch (tc) { |
294 | case TAB_DOS: |
295 | case TAB_FIX: |
296 | case TAB_BIN: |
297 | case TAB_VEC: |
298 | case TAB_DBF: |
299 | poff= loff + nof; // Default next offset |
300 | nlg= MY_MAX(nlg, poff); // Default lrecl |
301 | break; |
302 | case TAB_CSV: |
303 | case TAB_FMT: |
304 | nlg+= nof; |
305 | case TAB_DIR: |
306 | case TAB_XML: |
307 | poff= loff + (pcf->Flags & U_VIRTUAL ? 0 : 1); |
308 | break; |
309 | case TAB_INI: |
310 | case TAB_MAC: |
311 | case TAB_TBL: |
312 | case TAB_XCL: |
313 | case TAB_OCCUR: |
314 | case TAB_PRX: |
315 | case TAB_OEM: |
316 | poff = 0; // Offset represents an independant flag |
317 | break; |
318 | default: // VCT PLG ODBC JDBC MYSQL WMI... |
319 | poff = 0; // NA |
320 | break; |
321 | } // endswitch tc |
322 | |
323 | // do { |
324 | field= Hc->GetColumnOption(g, field, pcf); |
325 | // } while (field && (*pcf->Name =='*' /*|| pcf->Flags & U_VIRTUAL*/)); |
326 | |
327 | if (tc == TAB_DBF && pcf->Type == TYPE_DATE && !pcf->Datefmt) { |
328 | // DBF date format defaults to 'YYYMMDD' |
329 | pcf->Datefmt= "YYYYMMDD" ; |
330 | pcf->Length= 8; |
331 | } // endif tc |
332 | |
333 | if (!field) |
334 | break; |
335 | |
336 | // Allocate the column description block |
337 | cdp= new(g) COLDEF; |
338 | |
339 | if ((nof= cdp->Define(g, NULL, pcf, poff)) < 0) |
340 | return -1; // Error, probably unhandled type |
341 | else |
342 | loff= cdp->GetOffset(); |
343 | |
344 | switch (tc) { |
345 | case TAB_VEC: |
346 | cdp->SetOffset(0); // Not to have shift |
347 | case TAB_BIN: |
348 | // BIN/VEC are packed by default |
349 | if (nof) { |
350 | // Field width is the internal representation width |
351 | // that can also depend on the column format |
352 | fty = cdp->Decode ? 'C' : 'X'; |
353 | eds = 0; |
354 | n = 0; |
355 | |
356 | if (cdp->Fmt && !cdp->Decode) { |
357 | for (i = 0; cdp->Fmt[i]; i++) { |
358 | c = toupper(cdp->Fmt[i]); |
359 | |
360 | if (isdigit(c)) |
361 | n = (n * 10 + (c - '0')); |
362 | else if (c == 'L' || c == 'B' || c == 'H') |
363 | eds = c; |
364 | else |
365 | fty = c; |
366 | |
367 | } // endfor i |
368 | |
369 | } // endif Fmt |
370 | |
371 | if (n) |
372 | nof = n; |
373 | else switch (fty) { |
374 | case 'X': |
375 | if (eds && IsTypeChar(cdp->Buf_Type)) |
376 | nof = sizeof(longlong); |
377 | else |
378 | nof= cdp->Clen; |
379 | |
380 | break; |
381 | case 'C': break; |
382 | case 'R': |
383 | case 'F': nof = sizeof(float); break; |
384 | case 'I': nof = sizeof(int); break; |
385 | case 'D': nof = sizeof(double); break; |
386 | case 'S': nof = sizeof(short); break; |
387 | case 'T': nof = sizeof(char); break; |
388 | case 'G': nof = sizeof(longlong); break; |
389 | default: /* Wrong format */ |
390 | sprintf(g->Message, "Invalid format %c" , fty); |
391 | return -1; |
392 | } // endswitch fty |
393 | |
394 | } // endif nof |
395 | |
396 | default: |
397 | break; |
398 | } // endswitch tc |
399 | |
400 | if (lcdp) |
401 | lcdp->SetNext(cdp); |
402 | else |
403 | tocols= cdp; |
404 | |
405 | lcdp= cdp; |
406 | i++; |
407 | } // endwhile |
408 | |
409 | // Degree is the the number of defined columns (informational) |
410 | if (i != GetDegree()) |
411 | SetDegree(i); |
412 | |
413 | if (GetDefType() == TYPE_AM_DOS) { |
414 | int ending, recln= 0; |
415 | |
416 | // Was commented because sometimes ending is 0 even when |
417 | // not specified (for instance if quoted is specified) |
418 | // if ((ending= Hc->GetIntegerOption("Ending")) < 0) { |
419 | if ((ending= Hc->GetIntegerOption("Ending" )) <= 0) { |
420 | ending= (tc == TAB_BIN || tc == TAB_VEC) ? 0 : CRLF; |
421 | Hc->SetIntegerOption("Ending" , ending); |
422 | } // endif ending |
423 | |
424 | // Calculate the default record size |
425 | switch (tc) { |
426 | case TAB_FIX: |
427 | case TAB_BIN: |
428 | recln= nlg + ending; // + length of line ending |
429 | break; |
430 | case TAB_VEC: |
431 | recln= nlg; |
432 | |
433 | // if ((k= (pak < 0) ? 8 : pak) > 1) |
434 | // See above for detailed comment |
435 | // Round up lrecl to multiple of 8 or pak |
436 | // recln= ((recln + k - 1) / k) * k; |
437 | |
438 | break; |
439 | case TAB_DOS: |
440 | case TAB_DBF: |
441 | recln= nlg; |
442 | break; |
443 | case TAB_CSV: |
444 | case TAB_FMT: |
445 | // The number of separators (assuming an extra one can exist) |
446 | // recln= poff * ((qotd) ? 3 : 1); to be investigated |
447 | recln= nlg + poff * 3; // To be safe |
448 | default: |
449 | break; |
450 | } // endswitch tc |
451 | |
452 | // lrecl must be at least recln to avoid buffer overflow |
453 | if (trace(1)) |
454 | htrc("Lrecl: Calculated=%d defined=%d\n" , |
455 | recln, Hc->GetIntegerOption("Lrecl" )); |
456 | |
457 | recln = MY_MAX(recln, Hc->GetIntegerOption("Lrecl" )); |
458 | Hc->SetIntegerOption("Lrecl" , recln); |
459 | ((PDOSDEF)this)->SetLrecl(recln); |
460 | } // endif Lrecl |
461 | |
462 | // Attach the column definition to the tabdef |
463 | SetCols(tocols); |
464 | return poff; |
465 | } // end of GetColCatInfo |
466 | |
467 | /***********************************************************************/ |
468 | /* SetIndexInfo: retrieve index description from the table structure. */ |
469 | /***********************************************************************/ |
470 | void TABDEF::SetIndexInfo(void) |
471 | { |
472 | // Attach new index(es) |
473 | SetIndx(Hc->GetIndexInfo()); |
474 | } // end of SetIndexInfo |
475 | |
476 | /* --------------------------- Class OEMDEF -------------------------- */ |
477 | |
478 | /***********************************************************************/ |
479 | /* GetXdef: get the external TABDEF from OEM module. */ |
480 | /***********************************************************************/ |
481 | PTABDEF OEMDEF::GetXdef(PGLOBAL g) |
482 | { |
483 | typedef PTABDEF (__stdcall *XGETDEF) (PGLOBAL, void *); |
484 | char c, soname[_MAX_PATH], getname[40] = "Get" ; |
485 | PTABDEF xdefp; |
486 | XGETDEF getdef = NULL; |
487 | PCATLG cat = Cat; |
488 | |
489 | /*********************************************************************/ |
490 | /* Ensure that the .dll doesn't have a path. */ |
491 | /* This is done to ensure that only approved dll from the system */ |
492 | /* directories are used (to make this even remotely secure). */ |
493 | /*********************************************************************/ |
494 | if (check_valid_path(Module, strlen(Module))) { |
495 | strcpy(g->Message, "Module cannot contain a path" ); |
496 | return NULL; |
497 | } else |
498 | PlugSetPath(soname, Module, GetPluginDir()); |
499 | |
500 | #if defined(__WIN__) |
501 | // Is the DLL already loaded? |
502 | if (!Hdll && !(Hdll = GetModuleHandle(soname))) |
503 | // No, load the Dll implementing the function |
504 | if (!(Hdll = LoadLibrary(soname))) { |
505 | char buf[256]; |
506 | DWORD rc = GetLastError(); |
507 | |
508 | sprintf(g->Message, MSG(DLL_LOAD_ERROR), rc, soname); |
509 | FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | |
510 | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, rc, 0, |
511 | (LPTSTR)buf, sizeof(buf), NULL); |
512 | strcat(strcat(g->Message, ": " ), buf); |
513 | return NULL; |
514 | } // endif hDll |
515 | |
516 | // The exported name is always in uppercase |
517 | for (int i = 0; ; i++) { |
518 | c = Subtype[i]; |
519 | getname[i + 3] = toupper(c); |
520 | if (!c) break; |
521 | } // endfor i |
522 | |
523 | // Get the function returning an instance of the external DEF class |
524 | if (!(getdef = (XGETDEF)GetProcAddress((HINSTANCE)Hdll, getname))) { |
525 | sprintf(g->Message, MSG(PROCADD_ERROR), GetLastError(), getname); |
526 | FreeLibrary((HMODULE)Hdll); |
527 | return NULL; |
528 | } // endif getdef |
529 | #else // !__WIN__ |
530 | const char *error = NULL; |
531 | |
532 | #if 0 // Don't know what all this stuff does |
533 | Dl_info dl_info; |
534 | |
535 | // The OEM lib must retrieve exported CONNECT variables |
536 | if (dladdr(&connect_hton, &dl_info)) { |
537 | if (dlopen(dl_info.dli_fname, RTLD_NOLOAD | RTLD_NOW | RTLD_GLOBAL) == 0) { |
538 | error = dlerror(); |
539 | sprintf(g->Message, "dlopen failed: %s, OEM not supported" , SVP(error)); |
540 | return NULL; |
541 | } // endif dlopen |
542 | |
543 | } else { |
544 | error = dlerror(); |
545 | sprintf(g->Message, "dladdr failed: %s, OEM not supported" , SVP(error)); |
546 | return NULL; |
547 | } // endif dladdr |
548 | #endif // 0 |
549 | |
550 | // Load the desired shared library |
551 | if (!Hdll && !(Hdll = dlopen(soname, RTLD_LAZY))) { |
552 | error = dlerror(); |
553 | sprintf(g->Message, MSG(SHARED_LIB_ERR), soname, SVP(error)); |
554 | return NULL; |
555 | } // endif Hdll |
556 | |
557 | // The exported name is always in uppercase |
558 | for (int i = 0; ; i++) { |
559 | c = Subtype[i]; |
560 | getname[i + 3] = toupper(c); |
561 | if (!c) break; |
562 | } // endfor i |
563 | |
564 | // Get the function returning an instance of the external DEF class |
565 | if (!(getdef = (XGETDEF)dlsym(Hdll, getname))) { |
566 | error = dlerror(); |
567 | sprintf(g->Message, MSG(GET_FUNC_ERR), getname, SVP(error)); |
568 | dlclose(Hdll); |
569 | return NULL; |
570 | } // endif getdef |
571 | #endif // !__WIN__ |
572 | |
573 | // Just in case the external Get function does not set error messages |
574 | sprintf(g->Message, MSG(DEF_ALLOC_ERROR), Subtype); |
575 | |
576 | // Get the table definition block |
577 | if (!(xdefp = getdef(g, NULL))) |
578 | return NULL; |
579 | |
580 | // Have the external class do its complete definition |
581 | if (!cat->Cbuf) { |
582 | // Suballocate a temporary buffer for the entire column section |
583 | cat->Cblen = GetSizeCatInfo("Colsize" , "8K" ); |
584 | cat->Cbuf = (char*)PlugSubAlloc(g, NULL, cat->Cblen); |
585 | } // endif Cbuf |
586 | |
587 | // Here "OEM" should be replace by a more useful value |
588 | if (xdefp->Define(g, cat, Name, Schema, "OEM" )) |
589 | return NULL; |
590 | |
591 | // Ok, return external block |
592 | return xdefp; |
593 | } // end of GetXdef |
594 | |
595 | #if 0 |
596 | /***********************************************************************/ |
597 | /* DeleteTableFile: Delete an OEM table file if applicable. */ |
598 | /***********************************************************************/ |
599 | bool OEMDEF::DeleteTableFile(PGLOBAL g) |
600 | { |
601 | if (!Pxdef) |
602 | Pxdef = GetXdef(g); |
603 | |
604 | return (Pxdef) ? Pxdef->DeleteTableFile(g) : true; |
605 | } // end of DeleteTableFile |
606 | #endif // 0 |
607 | |
608 | /***********************************************************************/ |
609 | /* Define: initialize the table definition block from XDB file. */ |
610 | /***********************************************************************/ |
611 | bool OEMDEF::DefineAM(PGLOBAL g, LPCSTR, int) |
612 | { |
613 | Module = GetStringCatInfo(g, "Module" , "" ); |
614 | Subtype = GetStringCatInfo(g, "Subtype" , Module); |
615 | |
616 | if (!*Module) |
617 | Module = Subtype; |
618 | |
619 | char *desc = (char*)PlugSubAlloc(g, NULL, strlen(Module) |
620 | + strlen(Subtype) + 3); |
621 | sprintf(desc, "%s(%s)" , Module, Subtype); |
622 | Desc = desc; |
623 | return false; |
624 | } // end of DefineAM |
625 | |
626 | /***********************************************************************/ |
627 | /* GetTable: makes a new Table Description Block. */ |
628 | /***********************************************************************/ |
629 | PTDB OEMDEF::GetTable(PGLOBAL g, MODE mode) |
630 | { |
631 | RECFM rfm; |
632 | PTDB tdbp = NULL; |
633 | |
634 | // If define block not here yet, get it now |
635 | if (!Pxdef && !(Pxdef = GetXdef(g))) |
636 | return NULL; // Error |
637 | |
638 | /*********************************************************************/ |
639 | /* Allocate a TDB of the proper type. */ |
640 | /* Column blocks will be allocated only when needed. */ |
641 | /*********************************************************************/ |
642 | if (!(tdbp = Pxdef->GetTable(g, mode))) |
643 | return NULL; |
644 | else |
645 | rfm = tdbp->GetFtype(); |
646 | |
647 | if (rfm == RECFM_NAF) |
648 | return tdbp; |
649 | else if (rfm == RECFM_OEM) { |
650 | if (Multiple) |
651 | tdbp = new(g) TDBMUL(tdbp); // No block optimization yet |
652 | |
653 | return tdbp; |
654 | } // endif OEM |
655 | |
656 | /*********************************************************************/ |
657 | /* The OEM table is based on a file type (currently DOS+ only) */ |
658 | /*********************************************************************/ |
659 | assert (rfm == RECFM_VAR || rfm == RECFM_FIX || |
660 | rfm == RECFM_BIN || rfm == RECFM_VCT); |
661 | |
662 | PTXF txfp = NULL; |
663 | PDOSDEF defp = (PDOSDEF)Pxdef; |
664 | bool map = defp->Mapped && mode != MODE_INSERT && |
665 | !(UseTemp() == TMP_FORCE && |
666 | (mode == MODE_UPDATE || mode == MODE_DELETE)); |
667 | int cmpr = defp->Compressed; |
668 | |
669 | /*********************************************************************/ |
670 | /* Allocate table and file processing class of the proper type. */ |
671 | /* Column blocks will be allocated only when needed. */ |
672 | /*********************************************************************/ |
673 | if (!((PTDBDOS)tdbp)->GetTxfp()) { |
674 | if (cmpr) { |
675 | #if defined(GZ_SUPPORT) |
676 | if (cmpr == 1) |
677 | txfp = new(g) GZFAM(defp); |
678 | else |
679 | txfp = new(g) ZLBFAM(defp); |
680 | #else // !GZ_SUPPORT |
681 | strcpy(g->Message, "Compress not supported" ); |
682 | return NULL; |
683 | #endif // !GZ_SUPPORT |
684 | } else if (rfm == RECFM_VAR) { |
685 | if (map) |
686 | txfp = new(g) MAPFAM(defp); |
687 | else |
688 | txfp = new(g) DOSFAM(defp); |
689 | |
690 | } else if (rfm == RECFM_FIX || rfm == RECFM_BIN) { |
691 | if (map) |
692 | txfp = new(g) MPXFAM(defp); |
693 | else |
694 | txfp = new(g) FIXFAM(defp); |
695 | } else if (rfm == RECFM_VCT) { |
696 | #if defined(VCT_SUPPORT) |
697 | assert(Pxdef->GetDefType() == TYPE_AM_VCT); |
698 | |
699 | if (map) |
700 | txfp = new(g) VCMFAM((PVCTDEF)defp); |
701 | else |
702 | txfp = new(g) VCTFAM((PVCTDEF)defp); |
703 | #else // !VCT_SUPPORT |
704 | strcpy(g->Message, "VCT no more supported" ); |
705 | return NULL; |
706 | #endif // !VCT_SUPPORT |
707 | } // endif's |
708 | |
709 | ((PTDBDOS)tdbp)->SetTxfp(txfp); |
710 | } // endif Txfp |
711 | |
712 | if (Multiple) |
713 | tdbp = new(g) TDBMUL(tdbp); |
714 | |
715 | return tdbp; |
716 | } // end of GetTable |
717 | |
718 | /* --------------------------- Class COLCRT -------------------------- */ |
719 | |
720 | /***********************************************************************/ |
721 | /* COLCRT Constructors. */ |
722 | /***********************************************************************/ |
723 | COLCRT::COLCRT(PSZ name) |
724 | { |
725 | Next = NULL; |
726 | Name = name; |
727 | Desc = NULL; |
728 | Decode = NULL; |
729 | Fmt = NULL; |
730 | Offset = -1; |
731 | Long = -1; |
732 | Precision = -1; |
733 | Freq = -1; |
734 | Key = -1; |
735 | Scale = -1; |
736 | Opt = -1; |
737 | DataType = '*'; |
738 | } // end of COLCRT constructor for table creation |
739 | |
740 | COLCRT::COLCRT(void) |
741 | { |
742 | Next = NULL; |
743 | Name = NULL; |
744 | Desc = NULL; |
745 | Decode = NULL; |
746 | Fmt = NULL; |
747 | Offset = 0; |
748 | Long = 0; |
749 | Precision = 0; |
750 | Freq = 0; |
751 | Key = 0; |
752 | Scale = 0; |
753 | Opt = 0; |
754 | DataType = '*'; |
755 | } // end of COLCRT constructor for table & view definition |
756 | |
757 | /* --------------------------- Class COLDEF -------------------------- */ |
758 | |
759 | /***********************************************************************/ |
760 | /* COLDEF Constructor. */ |
761 | /***********************************************************************/ |
762 | COLDEF::COLDEF(void) : COLCRT() |
763 | { |
764 | To_Min = NULL; |
765 | To_Max = NULL; |
766 | To_Pos = NULL; |
767 | Xdb2 = FALSE; |
768 | To_Bmap = NULL; |
769 | To_Dval = NULL; |
770 | Ndv = 0; |
771 | Nbm = 0; |
772 | Buf_Type = TYPE_ERROR; |
773 | Clen = 0; |
774 | Poff = 0; |
775 | memset(&F, 0, sizeof(FORMAT)); |
776 | Flags = 0; |
777 | } // end of COLDEF constructor |
778 | |
779 | /***********************************************************************/ |
780 | /* Define: initialize a column definition from a COLINFO structure. */ |
781 | /***********************************************************************/ |
782 | int COLDEF::Define(PGLOBAL g, void *, PCOLINFO cfp, int poff) |
783 | { |
784 | Name = (PSZ)PlugDup(g, cfp->Name); |
785 | |
786 | if (!(cfp->Flags & U_SPECIAL)) { |
787 | Poff = poff; |
788 | Buf_Type = cfp->Type; |
789 | |
790 | if ((Clen = GetTypeSize(Buf_Type, cfp->Length)) < 0) { |
791 | sprintf(g->Message, MSG(BAD_COL_TYPE), GetTypeName(Buf_Type), Name); |
792 | return -1; |
793 | } // endswitch |
794 | |
795 | strcpy(F.Type, GetFormatType(Buf_Type)); |
796 | F.Length = cfp->Length; |
797 | F.Prec = cfp->Scale; |
798 | Offset = (cfp->Offset < 0) ? poff : cfp->Offset; |
799 | Precision = cfp->Precision; |
800 | Scale = cfp->Scale; |
801 | Long = cfp->Length; |
802 | Opt = cfp->Opt; |
803 | Key = cfp->Key; |
804 | Freq = cfp->Freq; |
805 | |
806 | if (cfp->Remark && *cfp->Remark) |
807 | Desc = (PSZ)PlugDup(g, cfp->Remark); |
808 | |
809 | if (cfp->Datefmt) |
810 | Decode = (PSZ)PlugDup(g, cfp->Datefmt); |
811 | |
812 | } else |
813 | Offset = poff; |
814 | |
815 | if (cfp->Fieldfmt) |
816 | Fmt = (PSZ)PlugDup(g, cfp->Fieldfmt); |
817 | |
818 | Flags = cfp->Flags; |
819 | return (Flags & (U_VIRTUAL|U_SPECIAL)) ? 0 : Long; |
820 | } // end of Define |
821 | |
822 | /* ------------------------- End of RelDef --------------------------- */ |
823 | |