diff options
Diffstat (limited to 'storage/connect/reldef.cpp')
-rw-r--r-- | storage/connect/reldef.cpp | 278 |
1 files changed, 198 insertions, 80 deletions
diff --git a/storage/connect/reldef.cpp b/storage/connect/reldef.cpp index 8ba8aac3621..ffe5f77661d 100644 --- a/storage/connect/reldef.cpp +++ b/storage/connect/reldef.cpp @@ -1,11 +1,11 @@ /************* RelDef CPP Program Source Code File (.CPP) **************/ /* PROGRAM NAME: RELDEF */ /* ------------- */ -/* Version 1.6 */ +/* Version 1.7 */ /* */ /* COPYRIGHT: */ /* ---------- */ -/* (C) Copyright to the author Olivier BERTRAND 2004-2016 */ +/* (C) Copyright to the author Olivier BERTRAND 2004-2019 */ /* */ /* WHAT THIS PROGRAM DOES: */ /* ----------------------- */ @@ -61,6 +61,102 @@ extern handlerton *connect_hton; /***********************************************************************/ 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(__WIN__) + HANDLE hdll; /* Handle to the external DLL */ +#else // !__WIN__ + void* hdll; /* Handle for the loaded shared library */ +#endif // !__WIN__ + 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))) { + strcpy(g->Message, "Module cannot contain a path"); + 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(__WIN__) + // Load the Dll implementing the table + if (!(hdll = LoadLibrary(soname))) { + char buf[256]; + DWORD rc = GetLastError(); + + sprintf(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); + strcat(strcat(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))) { + sprintf(g->Message, MSG(PROCADD_ERROR), GetLastError(), getname); + FreeLibrary((HMODULE)hdll); + return NULL; + } // endif coldef +#else // !__WIN__ + const char* error = NULL; + + // Load the desired shared library + if (!(hdll = dlopen(soname, RTLD_LAZY))) { + error = dlerror(); + sprintf(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(); + sprintf(g->Message, MSG(GET_FUNC_ERR), getname, SVP(error)); + dlclose(hdll); + return NULL; + } // endif coldef +#endif // !__WIN__ + + // Just in case the external Get function does not set error messages + sprintf(g->Message, "Error getting column info from %s", subtype); + + // Get the table column definition + qrp = coldef(g, topt, tab, db, info); + +#if defined(__WIN__) + FreeLibrary((HMODULE)hdll); +#else // !__WIN__ + dlclose(hdll); +#endif // !__WIN__ + + return qrp; +} // end of OEMColumns /* --------------------------- Class RELDEF -------------------------- */ @@ -208,6 +304,7 @@ TABDEF::TABDEF(void) { Schema = NULL; Desc = NULL; + Recfm = RECFM_DFLT; Catfunc = FNC_NO; Card = 0; Elemt = 0; @@ -221,11 +318,40 @@ TABDEF::TABDEF(void) } // end of TABDEF constructor /***********************************************************************/ +/* Return the table format. */ +/***********************************************************************/ +RECFM TABDEF::GetTableFormat(const char* type) +{ + RECFM recfm = Recfm; + + if (recfm == RECFM_DFLT) { + // Default format depends on the table type + TABTYPE tc = (Catfunc == FNC_NO) ? GetTypeID(type) : TAB_PRX; + + switch (tc) { + 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 + + } // endif recfm + + 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) - { +{ int poff = 0; Hc = ((MYCAT*)cat)->GetHandler(); @@ -243,13 +369,17 @@ bool TABDEF::Define(PGLOBAL g, PCATLG cat, NULL; csname = GetStringCatInfo(g, "Table_charset", NULL); - // Get The column definitions - if ((poff = GetColCatInfo(g)) < 0) - return true; + // Do the definition of AM specific fields + if (DefineAM(g, am, 0)) + return true; - // Do the definition of AM specific fields - return DefineAM(g, am, poff); - } // end of Define + // 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. */ @@ -264,71 +394,71 @@ PCSZ TABDEF::GetPath(void) /***********************************************************************/ int TABDEF::GetColCatInfo(PGLOBAL g) { - char *type= GetStringCatInfo(g, "Type", "*"); + char *type = GetStringCatInfo(g, "Type", "*"); char c, fty, eds; int i, n, loff, poff, nof, nlg; - void *field= NULL; - TABTYPE tc; - PCOLDEF cdp, lcdp= NULL, tocols= NULL; + 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 a unique char identifier for type - tc= (Catfunc == FNC_NO) ? GetTypeID(type) : TAB_PRX; + // Get the table format + trf = GetTableFormat(type); // Take care of the column definitions i= poff= nof= nlg= 0; #if defined(__WIN__) // Offsets of HTML and DIR tables start from 0, DBF at 1 - loff= (tc == TAB_DBF) ? 1 : (tc == TAB_XML || tc == TAB_DIR) ? -1 : 0; + loff= (trf == RECFM_DBF) ? 1 : (trf == RECFM_XML || trf == RECFM_DIR) ? -1 : 0; #else // !__WIN__ // Offsets of HTML tables start from 0, DIR and DBF at 1 - loff = (tc == TAB_DBF || tc == TAB_DIR) ? 1 : (tc == TAB_XML) ? -1 : 0; + loff = (trf == RECFM_DBF || trf == RECFM_DIR) ? 1 : (trf == RECFM_XML) ? -1 : 0; #endif // !__WIN__ while (true) { - // Default Offset depends on table type - switch (tc) { - case TAB_DOS: - case TAB_FIX: - case TAB_BIN: - case TAB_VEC: - case TAB_DBF: + // 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 TAB_CSV: - case TAB_FMT: + case RECFM_CSV: + case RECFM_FMT: nlg+= nof; - case TAB_DIR: - case TAB_XML: + case RECFM_DIR: + case RECFM_XML: poff= loff + (pcf->Flags & U_VIRTUAL ? 0 : 1); break; - case TAB_INI: - case TAB_MAC: - case TAB_TBL: - case TAB_XCL: - case TAB_OCCUR: - case TAB_PRX: - case TAB_OEM: + //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: // VCT PLG ODBC JDBC MYSQL WMI... + default: // PLG ODBC JDBC MYSQL WMI... poff = 0; // NA break; - } // endswitch tc + } // endswitch trf // do { field= Hc->GetColumnOption(g, field, pcf); // } while (field && (*pcf->Name =='*' /*|| pcf->Flags & U_VIRTUAL*/)); - if (tc == TAB_DBF && pcf->Type == TYPE_DATE && !pcf->Datefmt) { + if (trf == RECFM_DBF && pcf->Type == TYPE_DATE && !pcf->Datefmt) { // DBF date format defaults to 'YYYMMDD' pcf->Datefmt= "YYYYMMDD"; pcf->Length= 8; - } // endif tc + } // endif trf if (!field) break; @@ -341,10 +471,10 @@ int TABDEF::GetColCatInfo(PGLOBAL g) else loff= cdp->GetOffset(); - switch (tc) { - case TAB_VEC: + switch (trf ) { + case RECFM_VCT: cdp->SetOffset(0); // Not to have shift - case TAB_BIN: + case RECFM_BIN: // BIN/VEC are packed by default if (nof) { // Field width is the internal representation width @@ -395,7 +525,7 @@ int TABDEF::GetColCatInfo(PGLOBAL g) default: break; - } // endswitch tc + } // endswitch trf if (lcdp) lcdp->SetNext(cdp); @@ -413,21 +543,15 @@ int TABDEF::GetColCatInfo(PGLOBAL g) if (GetDefType() == TYPE_AM_DOS) { int ending, recln= 0; - // Was commented because sometimes ending is 0 even when - // not specified (for instance if quoted is specified) -// if ((ending= Hc->GetIntegerOption("Ending")) < 0) { - if ((ending= Hc->GetIntegerOption("Ending")) <= 0) { - ending= (tc == TAB_BIN || tc == TAB_VEC) ? 0 : CRLF; - Hc->SetIntegerOption("Ending", ending); - } // endif ending + ending = Hc->GetIntegerOption("Ending"); // Calculate the default record size - switch (tc) { - case TAB_FIX: - case TAB_BIN: + switch (trf ) { + case RECFM_FIX: + case RECFM_BIN: recln= nlg + ending; // + length of line ending break; - case TAB_VEC: + case RECFM_VCT: recln= nlg; // if ((k= (pak < 0) ? 8 : pak) > 1) @@ -436,18 +560,18 @@ int TABDEF::GetColCatInfo(PGLOBAL g) // recln= ((recln + k - 1) / k) * k; break; - case TAB_DOS: - case TAB_DBF: + case RECFM_VAR: + case RECFM_DBF: recln= nlg; break; - case TAB_CSV: - case TAB_FMT: + 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 tc + } // endswitch trf // lrecl must be at least recln to avoid buffer overflow if (trace(1)) @@ -461,7 +585,7 @@ int TABDEF::GetColCatInfo(PGLOBAL g) if (trace(1)) htrc("Lrecl set to %d\n", recln); - } // endif Lrecl + } // endif TYPE // Attach the column definition to the tabdef SetCols(tocols); @@ -500,7 +624,8 @@ PTABDEF OEMDEF::GetXdef(PGLOBAL g) return NULL; } else // PlugSetPath(soname, Module, GetPluginDir()); // Crashes on Fedora - strncat(strcpy(soname, GetPluginDir()), Module, _MAX_PATH); + strncat(strcpy(soname, GetPluginDir()), Module, + sizeof(soname) - strlen(soname) - 1); #if defined(__WIN__) // Is the DLL already loaded? @@ -596,10 +721,6 @@ PTABDEF OEMDEF::GetXdef(PGLOBAL g) cat->Cbuf = (char*)PlugSubAlloc(g, NULL, cat->Cblen); } // endif Cbuf - // Here "OEM" should be replace by a more useful value - if (xdefp->Define(g, cat, Name, Schema, "OEM")) - return NULL; - // Ok, return external block return xdefp; } // end of GetXdef @@ -622,7 +743,7 @@ bool OEMDEF::DeleteTableFile(PGLOBAL g) /***********************************************************************/ bool OEMDEF::DefineAM(PGLOBAL g, LPCSTR, int) { - Module = GetStringCatInfo(g, "Module", ""); + Module = GetStringCatInfo(g, "Module", ""); Subtype = GetStringCatInfo(g, "Subtype", Module); if (!*Module) @@ -632,7 +753,13 @@ bool OEMDEF::DefineAM(PGLOBAL g, LPCSTR, int) + strlen(Subtype) + 3); sprintf(desc, "%s(%s)", Module, Subtype); Desc = desc; - return false; + + // 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 /***********************************************************************/ @@ -640,7 +767,6 @@ bool OEMDEF::DefineAM(PGLOBAL g, LPCSTR, int) /***********************************************************************/ PTDB OEMDEF::GetTable(PGLOBAL g, MODE mode) { - RECFM rfm; PTDB tdbp = NULL; // If define block not here yet, get it now @@ -653,18 +779,10 @@ PTDB OEMDEF::GetTable(PGLOBAL g, MODE mode) /*********************************************************************/ if (!(tdbp = Pxdef->GetTable(g, mode))) return NULL; - else - rfm = tdbp->GetFtype(); - - if (rfm == RECFM_NAF) - return tdbp; - else if (rfm == RECFM_OEM) { - if (Multiple) - tdbp = new(g) TDBMUL(tdbp); // No block optimization yet - - return tdbp; - } // endif OEM + 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) */ /*********************************************************************/ @@ -723,7 +841,7 @@ PTDB OEMDEF::GetTable(PGLOBAL g, MODE mode) if (Multiple) tdbp = new(g) TDBMUL(tdbp); - +#endif // 0 return tdbp; } // end of GetTable |