summaryrefslogtreecommitdiffstats
path: root/storage/connect/reldef.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'storage/connect/reldef.cpp')
-rw-r--r--storage/connect/reldef.cpp957
1 files changed, 957 insertions, 0 deletions
diff --git a/storage/connect/reldef.cpp b/storage/connect/reldef.cpp
new file mode 100644
index 00000000..9af9faa3
--- /dev/null
+++ b/storage/connect/reldef.cpp
@@ -0,0 +1,957 @@
+/************* RelDef CPP Program Source Code File (.CPP) **************/
+/* PROGRAM NAME: RELDEF */
+/* ------------- */
+/* Version 1.7 */
+/* */
+/* COPYRIGHT: */
+/* ---------- */
+/* (C) Copyright to the author Olivier BERTRAND 2004-2019 */
+/* */
+/* WHAT THIS PROGRAM DOES: */
+/* ----------------------- */
+/* This program are the DB definition related routines. */
+/* */
+/***********************************************************************/
+
+/***********************************************************************/
+/* Include relevant MariaDB header file. */
+/***********************************************************************/
+#include "my_global.h"
+#if defined(_WIN32)
+#include <sqlext.h>
+#else
+//#include <dlfcn.h> // dlopen(), dlclose(), dlsym() ...
+#include "osutil.h"
+//#include "sqlext.h"
+#endif
+#include "handler.h"
+
+/***********************************************************************/
+/* Include application header files */
+/* */
+/* global.h is header containing all global declarations. */
+/* plgdbsem.h is header containing DB application declarations. */
+/* catalog.h is header containing DB description declarations. */
+/***********************************************************************/
+#include "global.h"
+#include "plgdbsem.h"
+#include "reldef.h"
+#include "colblk.h"
+#include "tabcol.h"
+#include "filamap.h"
+#include "filamfix.h"
+#if defined(VCT_SUPPORT)
+#include "filamvct.h"
+#endif // VCT_SUPPORT
+#if defined(GZ_SUPPORT)
+#include "filamgz.h"
+#endif // GZ_SUPPORT
+#include "tabdos.h"
+#include "valblk.h"
+#include "tabmul.h"
+#include "ha_connect.h"
+#include "mycat.h"
+
+#if !defined(_WIN32)
+extern handlerton *connect_hton;
+#endif // !_WIN32
+
+/***********************************************************************/
+/* External function. */
+/***********************************************************************/
+USETEMP UseTemp(void);
+char *GetPluginDir(void);
+PQRYRES OEMColumns(PGLOBAL g, PTOS topt, char* tab, char* db, bool info);
+
+/***********************************************************************/
+/* OEMColumns: Get table column info for an OEM table. */
+/***********************************************************************/
+PQRYRES OEMColumns(PGLOBAL g, PTOS topt, char* tab, char* db, bool info)
+{
+ typedef PQRYRES(__stdcall* XCOLDEF) (PGLOBAL, void*, char*, char*, bool);
+ const char* module, * subtype;
+ char c, soname[_MAX_PATH], getname[40] = "Col";
+#if defined(_WIN32)
+ HANDLE hdll; /* Handle to the external DLL */
+#else // !_WIN32
+ void* hdll; /* Handle for the loaded shared library */
+#endif // !_WIN32
+ XCOLDEF coldef = NULL;
+ PQRYRES qrp = NULL;
+
+ module = topt->module;
+ subtype = topt->subtype;
+
+ if (!module || !subtype)
+ return NULL;
+
+ /*********************************************************************/
+ /* Ensure that the .dll doesn't have a path. */
+ /* This is done to ensure that only approved dll from the system */
+ /* directories are used (to make this even remotely secure). */
+ /*********************************************************************/
+ if (check_valid_path(module, strlen(module))) {
+ safe_strcpy(g->Message, sizeof(g->Message), "Module cannot contain a path");
+ return NULL;
+ }
+ else if (strlen(subtype)+1+3 >= sizeof(getname)) {
+ safe_strcpy(g->Message, sizeof(g->Message), "Subtype string too long");
+ return NULL;
+ }
+ else
+ PlugSetPath(soname, module, GetPluginDir());
+
+ // The exported name is always in uppercase
+ for (int i = 0; ; i++) {
+ c = subtype[i];
+ getname[i + 3] = toupper(c);
+ if (!c) break;
+ } // endfor i
+
+#if defined(_WIN32)
+ // Load the Dll implementing the table
+ if (!(hdll = LoadLibrary(soname))) {
+ char buf[256];
+ DWORD rc = GetLastError();
+
+ snprintf(g->Message, sizeof(g->Message), MSG(DLL_LOAD_ERROR), rc, soname);
+ FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS, NULL, rc, 0,
+ (LPTSTR)buf, sizeof(buf), NULL);
+ safe_strcat(g->Message, sizeof(g->Message), ": ");
+ safe_strcat(g->Message, sizeof(g->Message), buf);
+ return NULL;
+ } // endif hDll
+
+// Get the function returning an instance of the external DEF class
+ if (!(coldef = (XCOLDEF)GetProcAddress((HINSTANCE)hdll, getname))) {
+ snprintf(g->Message, sizeof(g->Message), MSG(PROCADD_ERROR), GetLastError(), getname);
+ FreeLibrary((HMODULE)hdll);
+ return NULL;
+ } // endif coldef
+#else // !_WIN32
+ const char* error = NULL;
+
+ // Load the desired shared library
+ if (!(hdll = dlopen(soname, RTLD_LAZY))) {
+ error = dlerror();
+ snprintf(g->Message, sizeof(g->Message), MSG(SHARED_LIB_ERR), soname, SVP(error));
+ return NULL;
+ } // endif Hdll
+
+// Get the function returning an instance of the external DEF class
+ if (!(coldef = (XCOLDEF)dlsym(hdll, getname))) {
+ error = dlerror();
+ snprintf(g->Message, sizeof(g->Message), MSG(GET_FUNC_ERR), getname, SVP(error));
+ dlclose(hdll);
+ return NULL;
+ } // endif coldef
+#endif // !_WIN32
+
+ // Just in case the external Get function does not set error messages
+ snprintf(g->Message, sizeof(g->Message), "Error getting column info from %s", subtype);
+
+ // Get the table column definition
+ qrp = coldef(g, topt, tab, db, info);
+
+#if defined(_WIN32)
+ FreeLibrary((HMODULE)hdll);
+#else // !_WIN32
+ dlclose(hdll);
+#endif // !_WIN32
+
+ return qrp;
+} // end of OEMColumns
+
+/* --------------------------- Class RELDEF -------------------------- */
+
+/***********************************************************************/
+/* RELDEF Constructor. */
+/***********************************************************************/
+RELDEF::RELDEF(void)
+ {
+ Next = NULL;
+ To_Cols = NULL;
+ Name = NULL;
+ Database = NULL;
+ Cat = NULL;
+ Hc = NULL;
+ } // end of RELDEF constructor
+
+/***********************************************************************/
+/* This function return a pointer to the Table Option Struct. */
+/***********************************************************************/
+PTOS RELDEF::GetTopt(void)
+ {
+ return Hc->GetTableOptionStruct();
+ } // end of GetTopt
+
+/***********************************************************************/
+/* This function sets an integer table information. */
+/***********************************************************************/
+bool RELDEF::SetIntCatInfo(PCSZ what, int n)
+ {
+ return Hc->SetIntegerOption(what, n);
+ } // end of SetIntCatInfo
+
+/***********************************************************************/
+/* This function returns integer table information. */
+/***********************************************************************/
+int RELDEF::GetIntCatInfo(PCSZ what, int idef)
+ {
+ int n= Hc->GetIntegerOption(what);
+
+ return (n == NO_IVAL) ? idef : n;
+ } // end of GetIntCatInfo
+
+/***********************************************************************/
+/* This function returns Boolean table information. */
+/***********************************************************************/
+bool RELDEF::GetBoolCatInfo(PCSZ what, bool bdef)
+ {
+ bool b= Hc->GetBooleanOption(what, bdef);
+
+ return b;
+ } // end of GetBoolCatInfo
+
+/***********************************************************************/
+/* This function returns size catalog information. */
+/***********************************************************************/
+int RELDEF::GetSizeCatInfo(PCSZ what, PCSZ sdef)
+ {
+ char c;
+ PCSZ s;
+ int i, n= 0;
+
+ if (!(s= Hc->GetStringOption(what)))
+ s= sdef;
+
+ if ((i= sscanf(s, " %d %c ", &n, &c)) == 2)
+ switch (toupper(c)) {
+ case 'M':
+ n *= 1024;
+ // fall through
+ case 'K':
+ n *= 1024;
+ } // endswitch c
+
+ return n;
+} // end of GetSizeCatInfo
+
+/***********************************************************************/
+/* This function sets char table information in buf. */
+/***********************************************************************/
+int RELDEF::GetCharCatInfo(PCSZ what, PCSZ sdef, char *buf, int size)
+ {
+ PCSZ s= Hc->GetStringOption(what);
+
+ strncpy(buf, ((s) ? s : sdef), size);
+ return size;
+ } // end of GetCharCatInfo
+
+/***********************************************************************/
+/* To be used by any TDB's. */
+/***********************************************************************/
+bool RELDEF::Partitioned(void)
+ {
+ return Hc->IsPartitioned();
+ } // end of Partitioned
+
+/***********************************************************************/
+/* This function returns string table information. */
+/* Default parameter is "*" to get the handler default. */
+/***********************************************************************/
+char *RELDEF::GetStringCatInfo(PGLOBAL g, PCSZ what, PCSZ sdef)
+ {
+ char *sval = NULL;
+ PCSZ name, s= Hc->GetStringOption(what, sdef);
+
+ if (s) {
+ if (!Hc->IsPartitioned() ||
+ (stricmp(what, "filename") && stricmp(what, "tabname")
+ && stricmp(what, "connect")))
+ sval= PlugDup(g, s);
+ else
+ sval= (char*)s;
+
+ } else if (!stricmp(what, "filename")) {
+ // Return default file name
+ PCSZ ftype= Hc->GetStringOption("Type", "*");
+ int i, n;
+
+ if (IsFileType(GetTypeID(ftype))) {
+ name= Hc->GetPartName();
+ sval= (char*)PlugSubAlloc(g, NULL, strlen(name) + 12);
+ snprintf(sval, strlen(name) + 12, "%s.", name);
+ n= strlen(sval);
+
+ // Fold ftype to lower case
+ for (i= 0; i < 12; i++)
+ if (!ftype[i]) {
+ sval[n+i]= 0;
+ break;
+ } else
+ sval[n+i]= tolower(ftype[i]);
+
+ } // endif FileType
+
+ } // endif s
+
+ return sval;
+ } // end of GetStringCatInfo
+
+/* --------------------------- Class TABDEF -------------------------- */
+
+/***********************************************************************/
+/* TABDEF Constructor. */
+/***********************************************************************/
+TABDEF::TABDEF(void)
+ {
+ Schema = NULL;
+ Desc = NULL;
+ Recfm = RECFM_DFLT;
+ Catfunc = FNC_NO;
+ Card = 0;
+ Elemt = 0;
+ Sort = 0;
+ Multiple = 0;
+ Degree = 0;
+ Pseudo = 0;
+ Read_Only = false;
+ m_data_charset = NULL;
+ csname = NULL;
+ } // end of TABDEF constructor
+
+/***********************************************************************/
+/* Return the table format. */
+/***********************************************************************/
+RECFM TABDEF::GetTableFormat(const char* type)
+{
+ RECFM recfm = Recfm;
+
+ if (Catfunc != FNC_NO)
+ recfm = RECFM_NAF;
+ else if (recfm == RECFM_DFLT)
+ // Default format depends on the table type
+ switch (GetTypeID(type)) {
+ case TAB_DOS: recfm = RECFM_VAR; break;
+ case TAB_CSV: recfm = RECFM_CSV; break;
+ case TAB_FMT: recfm = RECFM_FMT; break;
+ case TAB_FIX: recfm = RECFM_FIX; break;
+ case TAB_BIN: recfm = RECFM_BIN; break;
+ case TAB_VEC: recfm = RECFM_VCT; break;
+ case TAB_DBF: recfm = RECFM_DBF; break;
+ case TAB_XML: recfm = RECFM_XML; break;
+ case TAB_DIR: recfm = RECFM_DIR; break;
+ default: recfm = RECFM_NAF; break;
+ } // endswitch type
+
+ return recfm;
+} // end of GetTableFormat
+
+/***********************************************************************/
+/* Define: initialize the table definition block from XDB file. */
+/***********************************************************************/
+bool TABDEF::Define(PGLOBAL g, PCATLG cat,
+ LPCSTR name, LPCSTR schema, LPCSTR am)
+{
+ Hc = ((MYCAT*)cat)->GetHandler();
+ Name = (PSZ)name;
+ Schema = (PSZ)Hc->GetDBName(schema);
+ Cat = cat;
+ Catfunc = GetFuncID(GetStringCatInfo(g, "Catfunc", NULL));
+ Elemt = GetIntCatInfo("Elements", 0);
+ Multiple = GetIntCatInfo("Multiple", 0);
+ Degree = GetIntCatInfo("Degree", 0);
+ Read_Only = GetBoolCatInfo("ReadOnly", false);
+ const char *data_charset_name= GetStringCatInfo(g, "Data_charset", NULL);
+ m_data_charset= data_charset_name ?
+ get_charset_by_csname(data_charset_name, MY_CS_PRIMARY,
+ MYF(MY_UTF8_IS_UTF8MB3)):
+ NULL;
+ csname = GetStringCatInfo(g, "Table_charset", NULL);
+
+ // Do the definition of AM specific fields
+ if (DefineAM(g, am, 0))
+ return true;
+
+ // Get The column definitions
+ if (stricmp(am, "OEM") && GetColCatInfo(g) < 0)
+ return true;
+
+ Hc->tshp = NULL; // TO BE CHECKED
+ return false;
+} // end of Define
+
+/***********************************************************************/
+/* This function returns the database data path. */
+/***********************************************************************/
+PCSZ TABDEF::GetPath(void)
+ {
+ return (Database) ? Database : (Hc) ? Hc->GetDataPath() : NULL;
+ } // end of GetPath
+
+/***********************************************************************/
+/* This function returns column table information. */
+/***********************************************************************/
+int TABDEF::GetColCatInfo(PGLOBAL g)
+ {
+ char *type = GetStringCatInfo(g, "Type", "*");
+ char c, fty, eds;
+ int i, n, loff, poff, nof, nlg;
+ void *field = NULL;
+ RECFM trf;
+ PCOLDEF cdp, lcdp = NULL, tocols= NULL;
+ PCOLINFO pcf= (PCOLINFO)PlugSubAlloc(g, NULL, sizeof(COLINFO));
+
+ memset(pcf, 0, sizeof(COLINFO));
+
+ // Get the table format
+ trf = GetTableFormat(type);
+
+ // Take care of the column definitions
+ i= poff= nof= nlg= 0;
+
+#if defined(_WIN32)
+ // Offsets of HTML and DIR tables start from 0, DBF at 1
+ loff= (trf == RECFM_DBF) ? 1 : (trf == RECFM_XML || trf == RECFM_DIR) ? -1 : 0;
+#else // !_WIN32
+ // Offsets of HTML tables start from 0, DIR and DBF at 1
+ loff = (trf == RECFM_DBF || trf == RECFM_DIR) ? 1 : (trf == RECFM_XML) ? -1 : 0;
+#endif // !_WIN32
+
+ while (true) {
+ // Default Offset depends on table format
+ switch (trf ) {
+ case RECFM_VAR:
+ case RECFM_FIX:
+ case RECFM_BIN:
+ case RECFM_VCT:
+ case RECFM_DBF:
+ poff= loff + nof; // Default next offset
+ nlg= MY_MAX(nlg, poff); // Default lrecl
+ break;
+ case RECFM_CSV:
+ case RECFM_FMT:
+ nlg+= nof;
+ /* falls through */
+ case RECFM_DIR:
+ case RECFM_XML:
+ poff= loff + (pcf->Flags & U_VIRTUAL ? 0 : 1);
+ break;
+ //case RECFM_INI:
+ //case RECFM_MAC:
+ //case RECFM_TBL:
+ //case RECFM_XCL:
+ //case RECFM_OCCUR:
+ //case RECFM_PRX:
+ case RECFM_OEM:
+ poff = 0; // Offset represents an independant flag
+ break;
+ default: // PLG ODBC JDBC MYSQL WMI...
+ poff = 0; // NA
+ break;
+ } // endswitch trf
+
+// do {
+ field= Hc->GetColumnOption(g, field, pcf);
+// } while (field && (*pcf->Name =='*' /*|| pcf->Flags & U_VIRTUAL*/));
+
+ if (trf == RECFM_DBF && pcf->Type == TYPE_DATE && !pcf->Datefmt) {
+ // DBF date format defaults to 'YYYMMDD'
+ pcf->Datefmt= "YYYYMMDD";
+ pcf->Length= 8;
+ } // endif trf
+
+ if (!field)
+ break;
+
+ // Allocate the column description block
+ cdp= new(g) COLDEF;
+
+ if ((nof= cdp->Define(g, NULL, pcf, poff)) < 0)
+ return -1; // Error, probably unhandled type
+ else
+ loff= cdp->GetOffset();
+
+ switch (trf ) {
+ case RECFM_VCT:
+ cdp->SetOffset(0); // Not to have shift
+ /* falls through */
+ case RECFM_BIN:
+ // BIN/VEC are packed by default
+ if (nof) {
+ // Field width is the internal representation width
+ // that can also depend on the column format
+ fty = cdp->Decode ? 'C' : 'X';
+ eds = 0;
+ n = 0;
+
+ if (cdp->Fmt && !cdp->Decode) {
+ for (i = 0; cdp->Fmt[i]; i++) {
+ c = toupper(cdp->Fmt[i]);
+
+ if (isdigit(c))
+ n = (n * 10 + (c - '0'));
+ else if (c == 'L' || c == 'B' || c == 'H')
+ eds = c;
+ else
+ fty = c;
+
+ } // endfor i
+
+ } // endif Fmt
+
+ if (n)
+ nof = n;
+ else switch (fty) {
+ case 'X':
+ if (eds && IsTypeChar(cdp->Buf_Type))
+ nof = sizeof(longlong);
+ else
+ nof= cdp->Clen;
+
+ break;
+ case 'C': break;
+ case 'R':
+ case 'F': nof = sizeof(float); break;
+ case 'I': nof = sizeof(int); break;
+ case 'D': nof = sizeof(double); break;
+ case 'S': nof = sizeof(short); break;
+ case 'T': nof = sizeof(char); break;
+ case 'G': nof = sizeof(longlong); break;
+ default: /* Wrong format */
+ snprintf(g->Message, sizeof(g->Message), "Invalid format %c", fty);
+ return -1;
+ } // endswitch fty
+
+ } // endif nof
+
+ default:
+ break;
+ } // endswitch trf
+
+ if (lcdp)
+ lcdp->SetNext(cdp);
+ else
+ tocols= cdp;
+
+ lcdp= cdp;
+ i++;
+ } // endwhile
+
+ // Degree is the the number of defined columns (informational)
+ if (i != GetDegree())
+ SetDegree(i);
+
+ if (GetDefType() == TYPE_AM_DOS) {
+ int ending, recln= 0;
+
+ ending = Hc->GetIntegerOption("Ending");
+
+ // Calculate the default record size
+ switch (trf ) {
+ case RECFM_FIX:
+ case RECFM_BIN:
+ recln= nlg + ending; // + length of line ending
+ break;
+ case RECFM_VCT:
+ recln= nlg;
+
+// if ((k= (pak < 0) ? 8 : pak) > 1)
+ // See above for detailed comment
+ // Round up lrecl to multiple of 8 or pak
+// recln= ((recln + k - 1) / k) * k;
+
+ break;
+ case RECFM_VAR:
+ case RECFM_DBF:
+ recln= nlg;
+ break;
+ case RECFM_CSV:
+ case RECFM_FMT:
+ // The number of separators (assuming an extra one can exist)
+// recln= poff * ((qotd) ? 3 : 1); to be investigated
+ recln= nlg + poff * 3; // To be safe
+ default:
+ break;
+ } // endswitch trf
+
+ // lrecl must be at least recln to avoid buffer overflow
+ if (trace(1))
+ htrc("Lrecl: Calculated=%d defined=%d\n",
+ recln, Hc->GetIntegerOption("Lrecl"));
+
+ recln = MY_MAX(recln, Hc->GetIntegerOption("Lrecl"));
+ Hc->SetIntegerOption("Lrecl", recln);
+ ((PDOSDEF)this)->SetLrecl(recln);
+
+ if (trace(1))
+ htrc("Lrecl set to %d\n", recln);
+
+ } // endif TYPE
+
+ // Attach the column definition to the tabdef
+ SetCols(tocols);
+ return poff;
+ } // end of GetColCatInfo
+
+/***********************************************************************/
+/* SetIndexInfo: retrieve index description from the table structure. */
+/***********************************************************************/
+void TABDEF::SetIndexInfo(void)
+ {
+ // Attach new index(es)
+ SetIndx(Hc->GetIndexInfo());
+ } // end of SetIndexInfo
+
+/* --------------------------- Class OEMDEF -------------------------- */
+
+/***********************************************************************/
+/* GetXdef: get the external TABDEF from OEM module. */
+/***********************************************************************/
+PTABDEF OEMDEF::GetXdef(PGLOBAL g)
+ {
+ typedef PTABDEF (__stdcall *XGETDEF) (PGLOBAL, void *);
+ char c, soname[_MAX_PATH], getname[40] = "Get";
+ PTABDEF xdefp;
+ XGETDEF getdef = NULL;
+ PCATLG cat = Cat;
+
+ /*********************************************************************/
+ /* Ensure that the module name doesn't have a path. */
+ /* This is done to ensure that only approved libs from the system */
+ /* directories are used (to make this even remotely secure). */
+ /*********************************************************************/
+ if (check_valid_path(Module, strlen(Module))) {
+ safe_strcpy(g->Message, sizeof(g->Message), "Module cannot contain a path");
+ return NULL;
+ } else
+// PlugSetPath(soname, Module, GetPluginDir()); // Crashes on Fedora
+ snprintf(soname, sizeof(soname), "%s%s", GetPluginDir(), Module);
+
+#if defined(_WIN32)
+ // Is the DLL already loaded?
+ if (!Hdll && !(Hdll = GetModuleHandle(soname)))
+ // No, load the Dll implementing the function
+ if (!(Hdll = LoadLibrary(soname))) {
+ char buf[256];
+ DWORD rc = GetLastError();
+
+ snprintf(g->Message, sizeof(g->Message), MSG(DLL_LOAD_ERROR), rc, soname);
+ FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS, NULL, rc, 0,
+ (LPTSTR)buf, sizeof(buf), NULL);
+ safe_strcat(g->Message, sizeof(g->Message), ": ");
+ safe_strcat(g->Message, sizeof(g->Message), buf);
+ return NULL;
+ } // endif hDll
+
+ // The exported name is always in uppercase
+ for (int i = 0; ; i++) {
+ c = Subtype[i];
+ getname[i + 3] = toupper(c);
+ if (!c) break;
+ } // endfor i
+
+ // Get the function returning an instance of the external DEF class
+ if (!(getdef = (XGETDEF)GetProcAddress((HINSTANCE)Hdll, getname))) {
+ char buf[256];
+ DWORD rc = GetLastError();
+
+ snprintf(g->Message, sizeof(g->Message), MSG(PROCADD_ERROR), rc, getname);
+ FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
+ FORMAT_MESSAGE_IGNORE_INSERTS, NULL, rc, 0,
+ (LPTSTR)buf, sizeof(buf), NULL);
+ safe_strcat(g->Message, sizeof(g->Message), ": ");
+ safe_strcat(g->Message, sizeof(g->Message), buf);
+ FreeLibrary((HMODULE)Hdll);
+ return NULL;
+ } // endif getdef
+#else // !_WIN32
+ const char *error = NULL;
+
+#if 0 // Don't know what all this stuff does
+ Dl_info dl_info;
+
+ // The OEM lib must retrieve exported CONNECT variables
+ if (dladdr(&connect_hton, &dl_info)) {
+ if (dlopen(dl_info.dli_fname, RTLD_NOLOAD | RTLD_NOW | RTLD_GLOBAL) == 0) {
+ error = dlerror();
+ snprintf(g->Message, sizeof(g->Message), "dlopen failed: %s, OEM not supported", SVP(error));
+ return NULL;
+ } // endif dlopen
+
+ } else {
+ error = dlerror();
+ snprintf(g->Message, sizeof(g->Message), "dladdr failed: %s, OEM not supported", SVP(error));
+ return NULL;
+ } // endif dladdr
+#endif // 0
+
+ // Load the desired shared library
+ if (!Hdll && !(Hdll = dlopen(soname, RTLD_LAZY))) {
+ error = dlerror();
+ snprintf(g->Message, sizeof(g->Message), MSG(SHARED_LIB_ERR), soname, SVP(error));
+ return NULL;
+ } // endif Hdll
+
+ // The exported name is always in uppercase
+ for (int i = 0; ; i++) {
+ c = Subtype[i];
+ getname[i + 3] = toupper(c);
+ if (!c) break;
+ } // endfor i
+
+ // Get the function returning an instance of the external DEF class
+ if (!(getdef = (XGETDEF)dlsym(Hdll, getname))) {
+ error = dlerror();
+ snprintf(g->Message, sizeof(g->Message), MSG(GET_FUNC_ERR), getname, SVP(error));
+ dlclose(Hdll);
+ return NULL;
+ } // endif getdef
+#endif // !_WIN32
+
+ // Just in case the external Get function does not set error messages
+ snprintf(g->Message, sizeof(g->Message), MSG(DEF_ALLOC_ERROR), Subtype);
+
+ // Get the table definition block
+ if (!(xdefp = getdef(g, NULL)))
+ return NULL;
+
+ // Have the external class do its complete definition
+ if (!cat->Cbuf) {
+ // Suballocate a temporary buffer for the entire column section
+ cat->Cblen = GetSizeCatInfo("Colsize", "8K");
+ cat->Cbuf = (char*)PlugSubAlloc(g, NULL, cat->Cblen);
+ } // endif Cbuf
+
+ // Ok, return external block
+ return xdefp;
+ } // end of GetXdef
+
+#if 0
+/***********************************************************************/
+/* DeleteTableFile: Delete an OEM table file if applicable. */
+/***********************************************************************/
+bool OEMDEF::DeleteTableFile(PGLOBAL g)
+ {
+ if (!Pxdef)
+ Pxdef = GetXdef(g);
+
+ return (Pxdef) ? Pxdef->DeleteTableFile(g) : true;
+ } // end of DeleteTableFile
+#endif // 0
+
+/***********************************************************************/
+/* Define: initialize the table definition block from XDB file. */
+/***********************************************************************/
+bool OEMDEF::DefineAM(PGLOBAL g, LPCSTR, int)
+ {
+ Module = GetStringCatInfo(g, "Module", "");
+ Subtype = GetStringCatInfo(g, "Subtype", Module);
+
+ if (!*Module)
+ Module = Subtype;
+
+ char *desc = (char*)PlugSubAlloc(g, NULL, strlen(Module)
+ + strlen(Subtype) + 3);
+ sprintf(desc, "%s(%s)", Module, Subtype);
+ Desc = desc;
+
+ // If define block not here yet, get it now
+ if (!Pxdef && !(Pxdef = GetXdef(g)))
+ return true; // Error
+
+ // Here "OEM" should be replace by a more useful value
+ return Pxdef->Define(g, Cat, Name, Schema, Subtype);
+ } // end of DefineAM
+
+/***********************************************************************/
+/* GetTable: makes a new Table Description Block. */
+/***********************************************************************/
+PTDB OEMDEF::GetTable(PGLOBAL g, MODE mode)
+ {
+ PTDB tdbp = NULL;
+
+ // If define block not here yet, get it now
+ if (!Pxdef && !(Pxdef = GetXdef(g)))
+ return NULL; // Error
+
+ /*********************************************************************/
+ /* Allocate a TDB of the proper type. */
+ /* Column blocks will be allocated only when needed. */
+ /*********************************************************************/
+ if (!(tdbp = Pxdef->GetTable(g, mode)))
+ return NULL;
+ else if (Multiple && tdbp->GetFtype() == RECFM_OEM)
+ tdbp = new(g) TDBMUL(tdbp); // No block optimization yet
+
+#if 0
+ /*********************************************************************/
+ /* The OEM table is based on a file type (currently DOS+ only) */
+ /*********************************************************************/
+ assert (rfm == RECFM_VAR || rfm == RECFM_FIX ||
+ rfm == RECFM_BIN || rfm == RECFM_VCT);
+
+ PTXF txfp = NULL;
+ PDOSDEF defp = (PDOSDEF)Pxdef;
+ bool map = defp->Mapped && mode != MODE_INSERT &&
+ !(UseTemp() == TMP_FORCE &&
+ (mode == MODE_UPDATE || mode == MODE_DELETE));
+ int cmpr = defp->Compressed;
+
+ /*********************************************************************/
+ /* Allocate table and file processing class of the proper type. */
+ /* Column blocks will be allocated only when needed. */
+ /*********************************************************************/
+ if (!((PTDBDOS)tdbp)->GetTxfp()) {
+ if (cmpr) {
+#if defined(GZ_SUPPORT)
+ if (cmpr == 1)
+ txfp = new(g) GZFAM(defp);
+ else
+ txfp = new(g) ZLBFAM(defp);
+#else // !GZ_SUPPORT
+ safe_strcpy(g->Message, sizeof(g->Message), "Compress not supported");
+ return NULL;
+#endif // !GZ_SUPPORT
+ } else if (rfm == RECFM_VAR) {
+ if (map)
+ txfp = new(g) MAPFAM(defp);
+ else
+ txfp = new(g) DOSFAM(defp);
+
+ } else if (rfm == RECFM_FIX || rfm == RECFM_BIN) {
+ if (map)
+ txfp = new(g) MPXFAM(defp);
+ else
+ txfp = new(g) FIXFAM(defp);
+ } else if (rfm == RECFM_VCT) {
+#if defined(VCT_SUPPORT)
+ assert(Pxdef->GetDefType() == TYPE_AM_VCT);
+
+ if (map)
+ txfp = new(g) VCMFAM((PVCTDEF)defp);
+ else
+ txfp = new(g) VCTFAM((PVCTDEF)defp);
+#else // !VCT_SUPPORT
+ safe_strcpy(g->Message, sizeof(g->Message), "VCT no more supported");
+ return NULL;
+#endif // !VCT_SUPPORT
+ } // endif's
+
+ ((PTDBDOS)tdbp)->SetTxfp(txfp);
+ } // endif Txfp
+
+ if (Multiple)
+ tdbp = new(g) TDBMUL(tdbp);
+#endif // 0
+ return tdbp;
+ } // end of GetTable
+
+/* --------------------------- Class COLCRT -------------------------- */
+
+/***********************************************************************/
+/* COLCRT Constructors. */
+/***********************************************************************/
+COLCRT::COLCRT(PSZ name)
+ {
+ Next = NULL;
+ Name = name;
+ Desc = NULL;
+ Decode = NULL;
+ Fmt = NULL;
+ Offset = -1;
+ Long = -1;
+ Precision = -1;
+ Freq = -1;
+ Key = -1;
+ Scale = -1;
+ Opt = -1;
+ DataType = '*';
+ } // end of COLCRT constructor for table creation
+
+COLCRT::COLCRT(void)
+ {
+ Next = NULL;
+ Name = NULL;
+ Desc = NULL;
+ Decode = NULL;
+ Fmt = NULL;
+ Offset = 0;
+ Long = 0;
+ Precision = 0;
+ Freq = 0;
+ Key = 0;
+ Scale = 0;
+ Opt = 0;
+ DataType = '*';
+ } // end of COLCRT constructor for table & view definition
+
+/* --------------------------- Class COLDEF -------------------------- */
+
+/***********************************************************************/
+/* COLDEF Constructor. */
+/***********************************************************************/
+COLDEF::COLDEF(void) : COLCRT()
+ {
+ To_Min = NULL;
+ To_Max = NULL;
+ To_Pos = NULL;
+ Xdb2 = FALSE;
+ To_Bmap = NULL;
+ To_Dval = NULL;
+ Ndv = 0;
+ Nbm = 0;
+ Buf_Type = TYPE_ERROR;
+ Clen = 0;
+ Poff = 0;
+ memset(&F, 0, sizeof(FORMAT));
+ Flags = 0;
+ } // end of COLDEF constructor
+
+/***********************************************************************/
+/* Define: initialize a column definition from a COLINFO structure. */
+/***********************************************************************/
+int COLDEF::Define(PGLOBAL g, void *, PCOLINFO cfp, int poff)
+ {
+ Name = (PSZ)PlugDup(g, cfp->Name);
+
+ if (!(cfp->Flags & U_SPECIAL)) {
+ Poff = poff;
+ Buf_Type = cfp->Type;
+
+ if ((Clen = GetTypeSize(Buf_Type, cfp->Length)) < 0) {
+ snprintf(g->Message, sizeof(g->Message), MSG(BAD_COL_TYPE), GetTypeName(Buf_Type), Name);
+ return -1;
+ } // endswitch
+
+ safe_strcpy(F.Type, sizeof(F.Type), GetFormatType(Buf_Type));
+ F.Length = cfp->Length;
+ F.Prec = cfp->Scale;
+ Offset = (cfp->Offset < 0) ? poff : cfp->Offset;
+ Precision = cfp->Precision;
+ Scale = cfp->Scale;
+ Long = cfp->Length;
+ Opt = cfp->Opt;
+ Key = cfp->Key;
+ Freq = cfp->Freq;
+
+ if (cfp->Remark && *cfp->Remark)
+ Desc = (PSZ)PlugDup(g, cfp->Remark);
+
+ if (cfp->Datefmt)
+ Decode = (PSZ)PlugDup(g, cfp->Datefmt);
+
+ } else
+ Offset = poff;
+
+ if (cfp->Fieldfmt)
+ Fmt = (PSZ)PlugDup(g, cfp->Fieldfmt);
+
+ Flags = cfp->Flags;
+ return (Flags & (U_VIRTUAL|U_SPECIAL)) ? 0 : Long;
+ } // end of Define
+
+/* ------------------------- End of RelDef --------------------------- */