/* HL7Daemon - SQL Manager Loads and manages SQL scripts */ #include #include #include "argvs.h" #include "scanner.h" #include "sqlmanager.h" #include "stringutils.h" #include "utils.h" #pragma hdrstop #include "util.h" #pragma warn -8060 using namespace std; //============================================================================= // // MCPP Library // // This provides a pre-processor for the SQL scripts. // // MCPP symbols - must match the mcpp source! typedef enum { MCPP_OUT, /* ~= fp_out */ MCPP_ERR, /* ~= fp_err */ MCPP_DBG, /* ~= fp_debug */ MCPP_NUM_OUTDEST, dummy = 0xffffffff // jhaley - make sure it's 32-bit. } OUTDEST; typedef void *(__cdecl *rwopen_t) (const char *, const char *); typedef void (__cdecl *rwcclose_t)(void *mem); typedef int (__cdecl *PMCPP_LIB_MAIN)(int, char **); typedef void (__cdecl *PMCPP_RESET_DEF_OUT_FUNC)(); typedef void (__cdecl *PMCPP_SET_OUT_FUNC)(int (*)(int, OUTDEST), int (*)(const char *, OUTDEST), int (*)(OUTDEST od, const char *, ...)); typedef void (__cdecl *PMCPP_USE_MEM_BUFFERS)(int); typedef char *(__cdecl *PMCPP_GET_MEM_BUFFER)(OUTDEST); typedef void (__cdecl *PMCPP_SETOPENCALLBACK)(rwopen_t); typedef void (__cdecl *PMCPP_SETCLOSECALLBACK)(rwcclose_t); typedef void *(__cdecl *PMCPP_OPENMEMORY)(void *, size_t); static PMCPP_LIB_MAIN mcpp_lib_main; static PMCPP_RESET_DEF_OUT_FUNC mcpp_reset_def_out_func; static PMCPP_SET_OUT_FUNC mcpp_set_out_func; static PMCPP_USE_MEM_BUFFERS mcpp_use_mem_buffers; static PMCPP_GET_MEM_BUFFER mcpp_get_mem_buffer; static PMCPP_SETOPENCALLBACK mcpp_setopencallback; static PMCPP_SETCLOSECALLBACK mcpp_setclosecallback; static PMCPP_OPENMEMORY mcpp_openmemory; #define LOADFUNC(type, func) \ if(!(func = reinterpret_cast(GetProcAddress(mcpp_lib, #func)))) \ return false // // open_callback // // This is the file open callback for the MCPP library. // static void * __cdecl open_callback(const char *fn, const char *mode) { string script = SQLManager::GetScript(fn); // duplicate the contents of the script if(script != "") { char *dupScript = strdup(script.c_str()); if(dupScript) return mcpp_openmemory(dupScript, script.length()); } return NULL; // failed } // // close_callback // // This is the file close callback for the MCPP library. // static void __cdecl close_callback(void *data) { if(data) free(data); } // // SQLManager::LoadMcpp // // Protected function, load the mcpp library if it's not already loaded. // bool SQLManager::LoadMcpp() { static HMODULE mcpp_lib; if(!mcpp_lib) { if(!(mcpp_lib = LoadLibrary("mcpp.dll"))) return false; LOADFUNC(PMCPP_LIB_MAIN, mcpp_lib_main); LOADFUNC(PMCPP_RESET_DEF_OUT_FUNC, mcpp_reset_def_out_func); LOADFUNC(PMCPP_SET_OUT_FUNC, mcpp_set_out_func); LOADFUNC(PMCPP_USE_MEM_BUFFERS, mcpp_use_mem_buffers); LOADFUNC(PMCPP_GET_MEM_BUFFER, mcpp_get_mem_buffer); LOADFUNC(PMCPP_SETOPENCALLBACK, mcpp_setopencallback); LOADFUNC(PMCPP_SETCLOSECALLBACK, mcpp_setclosecallback); LOADFUNC(PMCPP_OPENMEMORY, mcpp_openmemory); // Setup open and close callback functions mcpp_setopencallback(open_callback); mcpp_setclosecallback(close_callback); // Output to memory buffer mcpp_use_mem_buffers(MCPP_OUT); } return true; } // // SQLManager::scriptCallback // // Callback method for ScanForFiles, will load every .sql file in the directory // and map them by file name. // void SQLManager::scriptCallback(fileinfo &fi) { const char *text; const char *filepath = fi.GetFullyQualifiedName().c_str(); const char *filename = fi.filename.c_str(); AnsiString ext = ExtractFileExt(fi.filename); if(ext.LowerCase() != ".sql") return; if((text = LoadTextFile(filepath))) scripts[filename] = text; delete [] text; } // // SQLManager::loadScripts // // Load all scripts in the SQL query hive directory. // void SQLManager::loadScripts() { const char *dir; queue paths; if(!(dir = globalArgMgr->getParamTo("-sql"))) dir = ".\\sql"; paths.push(AnsiString(dir)); ScanForFiles(paths, this->scriptCallback); } // // SQLManager::haveScript // // Returns true if the script has been loaded, and false otherwise. // bool SQLManager::haveScript(const string &scriptName) const { return (scripts.find(scriptName) != scripts.end()); } // // SQLManager::getScript // // Return the contents of the script by name, if it exists. An empty string // is returned otherwise. // const string &SQLManager::getScript(const string &scriptName) const { static string foo; QueryMap::const_iterator itr = scripts.find(scriptName); if(itr != scripts.end()) return itr->second; else return foo; } // // VariableMapToArgvs // static char **VariableMapToArgvs(const SQLManager::VariableMap &variables, const string &infile, int &argc) { SQLManager::VariableMap::const_iterator vi; size_t numVars = variables.size() + 3; size_t curVar = 3; char **retarray = new char * [numVars]; retarray[0] = cpp_strdup("mcpp.exe"); retarray[1] = cpp_strdup("-P"); retarray[2] = cpp_strdup(infile.c_str()); for(vi = variables.begin(); vi != variables.end(); ++vi) { string argument = "-D " + vi->first + "=" + vi->second; retarray[curVar++] = cpp_strdup(argument.c_str()); } argc = static_cast(numVars); return retarray; } // // FreeArgvs // static void FreeArgvs(int argc, char **argv) { for(int i = 0; i < argc; i++) delete [] argv[i]; delete [] argv; } // // SQLManager::prepareScript // // Returns a copy of the script with all of the variables replaced in the // script's code with the values provided in the VariableMap. // void SQLManager::prepareScript(const string &scriptName, const VariableMap &variables, string &output) const { QueryMap::const_iterator qi = scripts.find(scriptName); if(qi != scripts.end()) { int argc; char **argv; char *result = NULL; argv = VariableMapToArgvs(variables, qi->first, argc); mcpp_lib_main(argc, argv); if((result = mcpp_get_mem_buffer(MCPP_OUT))) output = result; FreeArgvs(argc, argv); // FIXME: TEMPORARY DEBUG cout << output.c_str(); } } // // SQLManager::GetSQLManager // // Returns the global singleton instance of SQLManager. // SQLManager &SQLManager::GetSQLManager() { static SQLManager *theSQLMgr = NULL; if(!theSQLMgr) theSQLMgr = new SQLManager(); return *theSQLMgr; } // // SQLManager::LoadScripts // // Static convenience method to invoke loadScripts on the global singleton. // void SQLManager::LoadScripts() { if(!LoadMcpp()) DEBUGOUT(dbg_error, "WARNING: MCPP library failed to load!"); GetSQLManager().loadScripts(); // TEMPORARY string poop; PrepareScript("person_match.sql", VariableMap(), poop); } // // SQLManager::HaveScript // // Static convenience method to invoke haveScript on the global singleton. // bool SQLManager::HaveScript(const string &scriptName) { return GetSQLManager().haveScript(scriptName); } // // SQLManager::GetScript // // Static convenience method to invoke getScript on the global singleton. // const string &SQLManager::GetScript(const string &scriptName) { return GetSQLManager().getScript(scriptName); } // // SQLManager::PrepareScript // // Static convenience method to invoke prepareScript on the global singleton. // void SQLManager::PrepareScript(const string &scriptName, const VariableMap &variables, string &output) { GetSQLManager().prepareScript(scriptName, variables, output); } // EOF