/* * Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html). */ #include "h2odbc.h" HINSTANCE m_dll = 0; /* static FILE* m_logfile=NULL; void trace(char* message,...) { if(m_logfile==NULL) { m_logfile=fopen("C:\\h2odbc.log","a+"); } va_list valist; va_start(valist,message); vfprintf(m_logfile,message, valist); fprintf(m_logfile,"\r\n"); va_end(valist); fflush(m_logfile); } */ bool initialized = false; bool traceOn = false; #define BUFFER_SIZE 1024 char tracePath[BUFFER_SIZE+1]; void initTrace() { if(initialized) { return; } char* key = "Software\\H2\\ODBC"; HKEY hk; DWORD dwDisp; if (RegCreateKeyEx(HKEY_CURRENT_USER, key, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL, &hk, &dwDisp) != ERROR_SUCCESS) { return; } if (RegOpenKeyEx(HKEY_CURRENT_USER, key, 0, KEY_QUERY_VALUE, &hk) != ERROR_SUCCESS) { initialized = true; return; } DWORD bufferSize = BUFFER_SIZE; if(RegQueryValueEx(hk, "LogFile", NULL, NULL, (BYTE*)tracePath, &bufferSize) != ERROR_SUCCESS) { RegCloseKey(hk); initialized = true; return; } tracePath[bufferSize] = 0; RegCloseKey(hk); traceOn = bufferSize > 0; initialized = true; } void trace(char* message,...) { initTrace(); if(!traceOn) { return; } FILE* log = fopen(tracePath,"a+"); va_list valist; va_start(valist,message); vfprintf(log,message, valist); fprintf(log,"\r\n"); va_end(valist); fflush(log); fclose(log); } int WINAPI DllMain(HINSTANCE hInst,DWORD fdwReason,PVOID pvReserved) { if(fdwReason==DLL_PROCESS_ATTACH) { m_dll=hInst; } return 1; } int _export FAR PASCAL libmain(HANDLE hModule,short cbHeapSize, SQLCHAR FAR *lszCmdLine) { trace("libmain"); m_dll = (HINSTANCE) hModule; return TRUE; } void Connection::appendStatement() { Statement* s=new Statement(this); m_stats.push_back(s); } void Connection::removeStatement(int i) { delete m_stats[i]; m_stats.erase(m_stats.begin()+i); } void Connection::open(string name, string user, string password) { trace("Connection::open"); m_name=name; m_user=user; m_password=password; trace("url=%s user=%s", (char*)m_name.data(), (char*)m_user.data()); string prefix = "jdbc:h2:odbc://"; if(strncmp((char*)name.data(), (char*)prefix.data(), prefix.length()) != 0) { trace("url does not start with prefix"); m_state == C_CLOSED; return; } string server = name.substr(prefix.length()); trace("server %s", (char*)server.data()); int dbnameIdx = server.find('/'); if(dbnameIdx <= 0) { trace("url does not contain '/'"); setError("Wrong URL format"); m_state == C_CLOSED; return; } string dbname = server.substr(dbnameIdx+1); trace("dbname %s", dbname.data()); server = server.substr(0, dbnameIdx); int portIdx = server.find(':'); trace("portIdx %d", portIdx); int port = 9082; if(portIdx != 0) { string portString = server.substr(portIdx+1); trace("portString %s", (char*)portString.data()); port = atoi((char*)portString.data()); trace("port %d", port); server = server.substr(0, portIdx); trace("server %s", server.data()); } m_socket = new Socket(server.data(), port); if(m_socket->isClosed()) { setError(E_08001); // unable to establish m_state == C_CLOSED; return; } m_socket->writeByte('C'); m_socket->writeString(dbname.data())->writeString(m_user.data())->writeString(m_password.data()); int result = m_socket->readByte(); if(result=='O') { trace("ok!"); m_state == C_OPEN; } else { trace("error"); setError(E_08004); // rejected m_state == C_CLOSED; } } void Connection::setAutoCommit(bool autocommit) { if(autocommit != m_autoCommit) { m_socket->writeByte('A'); m_socket->writeByte(autocommit ? '1' : '0'); m_autoCommit=autocommit; } } void Connection::commit() { m_socket->writeByte('A'); m_socket->writeByte('C'); } void Connection::rollback() { m_socket->writeByte('A'); m_socket->writeByte('R'); } void Connection::close() { if(m_state == C_OPEN) { m_socket->close(); m_state=C_CLOSED; } } string Connection::getNativeSQL(const char* sql) { Socket* s = m_socket; s->writeByte('M'); s->writeByte('N'); s->writeString(sql); string native = s->readString(); return native; } Environment* Environment::cast(void* pointer) { if(pointer==0) { return 0; } Environment* env=(Environment*)pointer; if(env->m_magic!=MAGIC_ENVIRONMENT) { return 0; } return env; } Connection* Connection::cast(void* pointer) { if(pointer==0) { return 0; } Connection* conn=(Connection*)pointer; if(conn->m_magic!=MAGIC_CONNECTION) { return 0; } return conn; } Connection::Connection(Environment* e) { m_magic = MAGIC_CONNECTION; m_environment = e; m_state = C_INIT; m_error = 0; } Connection::~Connection() { if(m_magic==MAGIC_CONNECTION) { m_magic=0; } else { trace("~Connection %d",m_magic); return; } } Environment::Environment() { m_magic=MAGIC_ENVIRONMENT; } Environment::~Environment() { if(m_magic==MAGIC_ENVIRONMENT) { m_magic=0; } else { trace("~Environment %d",m_magic); return; } } Connection* Environment::createConnection() { m_openConnections++; return new Connection(this); } void Environment::closeConnection(Connection* conn) { delete conn; m_openConnections--; }