提交 e5880d3c authored 作者: Thomas Mueller's avatar Thomas Mueller

--no commit message

--no commit message
上级 5ec72128
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
*/
#include "h2odbc.h"
typedef struct {
char name[MAX_STRING_LEN+1];
char url[MAX_STRING_LEN+1];
char user[MAX_STRING_LEN+1];
char password[MAX_STRING_LEN+1];
} DNSConfiguration;
BOOL INSTAPI ConfigDriver(HWND hwndParent,
WORD fRequest, LPCSTR lpszDriver,
LPCSTR lpszArgs, LPSTR lpszMsg,
WORD cbMsgMax, WORD *pcbMsgOut) {
trace("ConfigDriver");
switch(fRequest) {
case ODBC_INSTALL_DRIVER:
case ODBC_CONFIG_DRIVER:
case ODBC_REMOVE_DRIVER:
return TRUE;
}
return FALSE;
}
LONG CALLBACK ConfigDlgProc(HWND hdlg,WORD wMsg,WPARAM wParam,LPARAM lParam) {
DNSConfiguration* config;
switch (wMsg) {
case WM_INITDIALOG:
config=(DNSConfiguration*)lParam;
SetDlgItemText(hdlg,IDC_NAME,config->name);
SetDlgItemText(hdlg,IDC_URL,config->url);
SetDlgItemText(hdlg,IDC_USER,config->user);
SetDlgItemText(hdlg,IDC_PASSWORD,config->password);
SetWindowLong(hdlg, GWL_USERDATA, (LONG) lParam );
return TRUE;
case WM_COMMAND:
switch (LOWORD(wParam)) {
case IDOK:
config=(DNSConfiguration*)GetWindowLong(hdlg,GWL_USERDATA);
GetDlgItemText(hdlg,IDC_NAME,config->name,MAX_STRING_LEN);
GetDlgItemText(hdlg,IDC_URL,config->url,MAX_STRING_LEN);
GetDlgItemText(hdlg,IDC_USER,config->user,MAX_STRING_LEN);
GetDlgItemText(hdlg,IDC_PASSWORD,config->password,MAX_STRING_LEN);
EndDialog(hdlg, wParam);
return TRUE;
case IDCANCEL:
EndDialog(hdlg, wParam);
return TRUE;
}
break;
}
return FALSE;
}
BOOL INSTAPI ConfigDSN(HWND hwndParent,
WORD fRequest, LPCSTR lpszDriver,
LPCSTR lpszAttributes) {
trace("ConfigDSN");
char* begin=strstr(lpszAttributes,"DSN=");
int len=0;
char name[MAX_STRING_LEN+1];
name[0]=0;
DNSConfiguration configuration;
configuration.name[0]=0;
configuration.url[0]=0;
configuration.user[0]=0;
configuration.password[0]=0;
if(begin) {
trace(" begin");
begin+=4;
char* end=strstr(begin,";");
int len;
if(end==NULL) {
len=strlen(begin);
} else {
len=end-begin;
}
if(len>MAX_STRING_LEN) {
len=MAX_STRING_LEN;
}
strncpy(name, begin, len+1);
strncpy(configuration.name, begin, len+1);
}
if(fRequest==ODBC_REMOVE_DSN) {
trace(" ODBC_REMOVE_DSN");
return SQLRemoveDSNFromIni(name);
}
if(fRequest==ODBC_CONFIG_DSN) {
trace(" ODBC_CONFIG_DSN");
SQLGetPrivateProfileString(
name,
"URL", "", configuration.url, MAX_STRING_LEN,
"ODBC.INI");
SQLGetPrivateProfileString(
name,
"User", "", configuration.user, MAX_STRING_LEN,
"ODBC.INI");
SQLGetPrivateProfileString(
name,
"Password", "", configuration.password, MAX_STRING_LEN,
"ODBC.INI");
} else if(fRequest==ODBC_ADD_DSN) {
// ok
trace(" ODBC_ADD_DSN");
} else {
// error
trace(" ?");
return FALSE;
}
HMODULE module = GetModuleHandle("h2odbc");
if(hwndParent) {
int result=DialogBoxParam(module,
MAKEINTRESOURCE(IDD_CONFIG),
hwndParent,
(DLGPROC)ConfigDlgProc,
(LPARAM)&configuration);
if(result != IDOK) {
trace(" result != IDOK, %d lastError=%d", result, GetLastError());
return TRUE;
}
}
trace(" SQLRemoveDSNFromIni...");
SQLRemoveDSNFromIni(name);
SQLWriteDSNToIni(configuration.name,lpszDriver);
SQLWritePrivateProfileString(
configuration.name, "URL", configuration.url,
"ODBC.INI");
SQLWritePrivateProfileString(
configuration.name, "User", configuration.user,
"ODBC.INI");
SQLWritePrivateProfileString(
configuration.name, "Password", configuration.password,
"ODBC.INI");
// TODO: temp hack (because m_dll is 0?)
// SQLRemoveDSNFromIni(name);
// SQLWriteDSNToIni("Test",lpszDriver);
// SQLWritePrivateProfileString(
// configuration.name, "URL", "jdbc:h2:localhost:9082",
// "ODBC.INI");
// SQLWritePrivateProfileString(
// configuration.name, "User", "sa",
// "ODBC.INI");
// SQLWritePrivateProfileString(
// configuration.name, "Password", "123",
// "ODBC.INI");
trace(" return TRUE");
return TRUE;
}
LIBRARY h2odbc
EXPORTS
DllMain
ConfigDriver
ConfigDSN
SQLAllocHandle
SQLBindCol
SQLBindParameter
SQLCancel
SQLCloseCursor
SQLColAttribute
SQLColumns
SQLConnect
SQLCopyDesc
SQLDescribeCol
SQLDriverConnect
SQLDisconnect
SQLEndTran
SQLExecDirect
SQLExecute
SQLFetch
SQLFetchScroll
SQLFreeHandle
SQLFreeStmt
SQLGetConnectAttr
SQLGetCursorName
SQLGetData
SQLGetDescField
SQLGetDescRec
SQLGetDiagField
SQLGetDiagRec
SQLGetEnvAttr
SQLGetInfo
SQLGetStmtAttr
SQLGetTypeInfo
SQLNumResultCols
SQLNativeSql
SQLNumParams
SQLParamData
SQLPrepare
SQLPutData
SQLRowCount
SQLSetConnectAttr
SQLSetCursorName
SQLSetDescField
SQLSetDescRec
SQLSetEnvAttr
SQLSetStmtAttr
SQLSpecialColumns
SQLStatistics
SQLTables
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
*/
#include <winsock.h>
#include <windows.h>
#include <odbcinst.h>
#include <sqlext.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string>
#include <vector>
#include "resource.h"
using namespace std;
const int MAX_STRING_LEN=511;
void initSockets();
void trace(char* message,...);
void setString(char* dest, int dest_len, SQLCHAR *source, SQLSMALLINT source_len);
void returnString(SQLCHAR* dest, SQLSMALLINT dest_len, SQLSMALLINT* dest_pt, const char* source);
void returnString(SQLPOINTER dest, SQLINTEGER dest_len, SQLINTEGER* dest_pt, const char* source);
void returnInt(SQLPOINTER InfoValue, SQLINTEGER* LengthPtr, SQLUINTEGER value);
void returnInt(SQLPOINTER NumericPtr, int value);
void returnInt(SQLPOINTER InfoValue, SQLSMALLINT* LengthPtr, SQLUINTEGER value);
void returnSmall(SQLPOINTER InfoValue, SQLSMALLINT* LengthPtr, SQLUSMALLINT value);
void returnSmall(SQLPOINTER InfoValue, SQLINTEGER* LengthPtr, SQLUSMALLINT value);
void returnPointer(SQLPOINTER pointer, void* value);
int getDefaultCType(int sqlType);
extern HINSTANCE m_dll;
extern bool m_socket_init;
class Socket {
SOCKET m_socket;
private:
void setError(char* where);
void read(char* buffer, int len);
void write(const char* buffer, int len);
public:
Socket(const char* host,int port);
void close();
int readByte();
int readInt();
bool readBool();
string readString();
Socket* writeByte(int byte);
Socket* writeBool(bool x);
Socket* writeInt(int x);
Socket* writeString(const char* string);
bool isClosed() {
return m_socket != 0;
}
};
class Environment;
class Connection;
class Statement;
class Descriptor;
class DescriptorRecord;
enum DescriptorState {D_ACTIVE,D_FREE};
enum DescriptorType {DT_DEFAULT,DT_SHARED};
enum ConnectionState {C_INIT,C_OPEN,C_CLOSED};
enum StatementState {S_PREPARED,S_EXECUTED,S_POSITIONED,S_CLOSED};
enum Send {S_EXECUTE};
const int MAGIC_ENVIRONMENT=0xABC0;
const int MAGIC_CONNECTION=0xABC1;
const int MAGIC_STATEMENT=0xABC2;
const int MAGIC_DESCRIPTOR=0xABC3;
const int MAGIC_DESCRIPTOR_RECORD=0xABC4;
class Descriptor {
int m_magic;
Connection* m_connection;
int m_id;
int m_type;
int m_arraySize;
int m_count;
SQLUSMALLINT* m_statusPointer;
SQLUINTEGER* m_rowsProcessedPointer;
DescriptorState m_state;
vector<Statement*> m_bound;
vector<DescriptorRecord*> m_records;
char* m_error;
bool m_rowWiseBinding;
int m_rowSize;
public:
static Descriptor* cast(void* pointer);
// create a shared descriptor
Descriptor(Connection* c);
// create a default descriptor (not shared)
Descriptor();
~Descriptor();
void init();
bool isFreed() {
return m_state==D_FREE;
}
void clearRecords() {
m_records.clear();
}
void addRecord(DescriptorRecord* rec) {
m_records.push_back(rec);
}
void readData(int i, Socket* s);
DescriptorRecord* getRecord(int i) {
return m_records[i];
}
int getRecordCount() {
return m_records.size();
}
void setStatusPointer(SQLUSMALLINT* newPointer) {
m_statusPointer = newPointer;
}
SQLUSMALLINT* getStatusPointer() {
return m_statusPointer;
}
void setRowsProcessedPointer(SQLUINTEGER* rowsProcessedPointer) {
m_rowsProcessedPointer = rowsProcessedPointer;
}
void setRowsProcessed(int rows) {
if(m_rowsProcessedPointer != 0) {
*m_rowsProcessedPointer = rows;
}
}
void setStatus(SQLUSMALLINT value) {
if(m_statusPointer != 0) {
*m_statusPointer = value;
}
}
void setError(char* error) {
m_error = error;
}
char* getError() {
return m_error;
}
void setBindingType(bool rowWiseBinding, int rowSize);
};
/*
Header:
SQL_DESC_ALLOC_TYPE (readonly)
SQL_DESC_BIND_TYPE (read/write)
SQL_DESC_ARRAY_SIZE (read/write)
SQL_DESC_COUNT (readonly)
SQL_DESC_ARRAY_STATUS_PTR (read/write)
SQL_DESC_ROWS_PROCESSED_PTR (read/write)
SQL_DESC_BIND_OFFSET_PTR (read/write)
Record:
SQL_DESC_AUTO_UNIQUE_VALUE
SQL_DESC_LOCAL_TYPE_NAME SQLCHAR* TypeName
SQL_DESC_BASE_COLUMN_NAME SQLCHAR* TableName
SQL_DESC_NAME SQLCHAR* ColumnName / DisplayName
SQL_DESC_BASE_TABLE_NAME SQLCHAR* TableName
SQL_DESC_NULLABLE
SQL_DESC_CASE_SENSITIVE
SQL_DESC_OCTET_LENGTH
SQL_DESC_CATALOG_NAME SQLCHAR* CatalogName
SQL_DESC_OCTET_LENGTH_PTR
SQL_DESC_CONCISE_TYPE SQLSMALLINT DataType
SQL_DESC_PARAMETER_TYPE
SQL_DESC_DATA_PTR
SQL_DESC_PRECISION
SQL_DESC_DATETIME_INTERVAL_CODE
SQL_DESC_SCALE
SQL_DESC_DATETIME_INTERVAL_PRECISION
SQL_DESC_SCHEMA_NAME SQLCHAR* SchemaName
SQL_DESC_DISPLAY_SIZE
SQL_DESC_SEARCHABLE
SQL_DESC_FIXED_PREC_SCALE
SQL_DESC_TABLE_NAME SQLCHAR* TableName
SQL_DESC_INDICATOR_PTR
SQL_DESC_TYPE
SQL_DESC_LABEL SQLCHAR*
SQL_DESC_TYPE_NAME SQLCHAR*
SQL_DESC_LENGTH
SQL_DESC_UNNAMED
SQL_DESC_LITERAL_PREFIX SQLCHAR*
SQL_DESC_UNSIGNED
SQL_DESC_LITERAL_SUFFIX SQLCHAR*
SQL_DESC_UPDATABLE
*/
class DescriptorRecord {
int m_magic;
Descriptor* m_descriptor;
int m_sqlDataType;
int m_cDataType;
string m_name;
string m_columnName;
string m_tableName;
SQLPOINTER m_pointer;
SQLINTEGER* m_statusPointer;
int m_targetBufferLength;
int m_dataInt;
string m_dataString;
int m_precision;
int m_scale;
int m_displaySize;
bool m_wasNull;
public:
static DescriptorRecord* cast(void* pointer);
DescriptorRecord(Descriptor* d) {
m_magic=MAGIC_DESCRIPTOR_RECORD;
m_descriptor=d;
m_sqlDataType = 0;
m_cDataType = 0;
m_pointer = 0;
m_statusPointer = 0;
m_targetBufferLength = 0;
m_dataInt = 0;
m_precision = 0;
m_scale = 0;
m_displaySize = 0;
m_wasNull = false;
}
~DescriptorRecord() {
if(m_magic==MAGIC_DESCRIPTOR_RECORD) {
m_magic=0;
} else {
trace("~DescriptorRecord %d",m_magic);
return;
}
}
void setSqlDataType(int sqlDataType) {
m_sqlDataType = sqlDataType;
}
void setCDataType(int cDataType) {
m_cDataType = cDataType;
}
void setTargetBufferLength(int len) {
m_targetBufferLength = len;
}
void setTargetPointer(SQLPOINTER pointer) {
m_pointer = pointer;
}
void setTargetStatusPointer(SQLINTEGER* statusPointer) {
m_statusPointer = statusPointer;
}
int getSqlDataType() {
return m_sqlDataType;
}
bool hasFixedPrecisionScale();
int getDisplaySize() {
return m_displaySize;
}
int getPrecision() {
return m_precision;
}
int getScale() {
return m_scale;
}
string getColumnName() {
return m_columnName;
}
string getTableName() {
return m_tableName;
}
char* getString();
int getInt();
void readMeta(Socket* s);
void sendParameterValue(Socket* s);
void readData(Socket* s);
void copyData(DescriptorRecord* ar);
bool wasNull() {
return m_wasNull;
}
void setNull();
int getLength();
const char* getPrefix();
const char* getSuffix();
};
class Environment {
int m_magic;
int m_id;
int m_openConnections;
int m_behavior;
char* m_error;
public:
static Environment* cast(void* pointer);
Environment();
~Environment();
Connection* createConnection();
void closeConnection(Connection* conn);
int getOpenConnectionCount() {
return m_openConnections;
}
void setBehavior(int behavior) {
m_behavior=behavior;
}
int getBehavior() {
return m_behavior;
}
void setError(char* error) {
m_error = error;
}
char* getError() {
return m_error;
}
};
class Connection {
int m_magic;
friend class Environment;
Environment* m_environment;
ConnectionState m_state;
int m_id;
string m_name;
string m_user;
string m_password;
bool m_readOnly;
bool m_autoCommit;
vector<Statement*> m_stats;
Socket* m_socket;
char* m_error;
string m_dataSourceName;
private:
Connection(Environment* e);
void appendStatement();
void removeStatement(int i);
~Connection();
public:
static Connection* cast(void* pointer);
Environment* getEnvironment() {
return m_environment;
}
void open(string name,string user,string password);
bool isClosed() {
return m_state==C_CLOSED;
}
void close();
void setReadOnly(bool readonly) {
m_readOnly=readonly;
}
bool getReadOnly() {
return m_readOnly;
}
void setAutoCommit(bool autocommit);
void commit();
void rollback();
bool getAutoCommit() {
return m_autoCommit;
}
Socket* getSocket() {
return m_socket;
}
void setError(char* error) {
m_error = error;
}
char* getError() {
return m_error;
}
string getNativeSQL(const char* sql);
void setDataSourceName(string dataSourceName) {
m_dataSourceName = dataSourceName;
}
string getDataSourceName() {
return m_dataSourceName;
}
};
class Statement {
int m_magic;
Connection* m_connection;
int m_id;
Descriptor m_appRowDefault;
Descriptor m_impRowDefault;
Descriptor m_appParamDefault;
Descriptor m_impParamDefault;
Descriptor* m_appRow;
Descriptor* m_impRow;
Descriptor* m_appParam;
Descriptor* m_impParam;
StatementState m_state;
string m_sql;
int m_columnCount;
int m_updateCount;
int m_resultSetId;
int m_preparedId;
int m_rowId;
bool m_hasResultSet;
int m_parameterCount;
bool m_useBookmarks;
char* m_error;
private:
void processResultSet(Socket* s);
public:
static Statement* cast(void* pointer);
Statement(Connection* c);
~Statement();
bool prepare(char* sql);
bool execute(char* sql);
bool executePrepared();
void getMetaTables(char* catalog, char* schema, char* table, char* tabletypes);
void getMetaColumns(char* catalog, char* schema, char* table, char* column);
void getMetaVersionColumns(char* catalog, char* schema, char* table);
void getMetaBestRowIdentifier(char* catalog, char* schema, char* table, int scope, bool nullable);
void getMetaIndexInfo(char* catalog, char* schema, char* table, bool unique, bool approximate);
void getMetaTypeInfoAll();
void getMetaTypeInfo(int sqlType);
Descriptor* getAppRowDesc();
Descriptor* getImpRowDesc();
Descriptor* getAppParamDesc();
Descriptor* getImpParamDesc();
int getColumnCount() {
return m_columnCount;
}
bool next();
int getParametersCount() {
return m_parameterCount;
}
int getUpdateCount() {
return m_updateCount;
}
const char* getSQL();
void closeCursor();
void setUseBookmarks(bool bookmarks) {
m_useBookmarks = bookmarks;
}
bool getUseBookmarks() {
return m_useBookmarks;
}
int getRowId() {
return m_rowId;
}
void setError(char* error) {
m_error = error;
}
char* getError() {
return m_error;
}
void addParameter();
};
#define E_01000 "01000 General warning"
#define E_01001 "01001 Cursor operation conflict"
#define E_01002 "01002 Disconnect error"
#define E_01003 "01003 NULL value eliminated in set function"
#define E_01004 "01004 String data, right-truncated"
#define E_01006 "01006 Privilege not revoked"
#define E_01007 "01007 Privilege not granted"
#define E_01S00 "01S00 Invalid connection string attribute"
#define E_01S01 "01S01 Error in row"
#define E_01S02 "01S02 Option value changed"
#define E_01S06 "01S06 Attempt to fetch before the result set returned the first rowset"
#define E_01S07 "01S07 Fractional truncation"
#define E_01S08 "01S08 Error saving File DSN"
#define E_01S09 "01S09 Invalid keyword"
#define E_07001 "07001 Wrong number of parameters"
#define E_07002 "07002 COUNT field incorrect"
#define E_07005 "07005 Prepared statement not a cursor-specification"
#define E_07006 "07006 Restricted data type attribute violation"
#define E_07009 "07009 Invalid descriptor index"
#define E_07S01 "07S01 Invalid use of default parameter"
#define E_08001 "08001 Client unable to establish connection"
#define E_08002 "08002 Connection name in use"
#define E_08003 "08003 Connection does not exist"
#define E_08004 "08004 Server rejected the connection"
#define E_08007 "08007 Connection failure during transaction"
#define E_08S01 "08S01 Communication link failure"
#define E_21S01 "21S01 Insert value list does not match column list"
#define E_21S02 "21S02 Degree of derived table does not match column list"
#define E_22001 "22001 String data, right-truncated"
#define E_22002 "22002 Indicator variable required but not supplied"
#define E_22003 "22003 Numeric value out of range"
#define E_22007 "22007 Invalid datetime format"
#define E_22008 "22008 Datetime field overflow"
#define E_22012 "22012 Division by zero"
#define E_22015 "22015 Interval field overflow"
#define E_22018 "22018 Invalid character value for cast specification"
#define E_22019 "22019 Invalid escape character"
#define E_22025 "22025 Invalid escape sequence"
#define E_22026 "22026 String data, length mismatch"
#define E_23000 "23000 Integrity constraint violation"
#define E_24000 "24000 Invalid cursor state"
#define E_25000 "25000 Invalid transaction state"
#define E_25S01 "25S01 Transaction state"
#define E_25S02 "25S02 Transaction is still active"
#define E_25S03 "25S03 Transaction is rolled back"
#define E_28000 "28000 Invalid authorization specification"
#define E_34000 "34000 Invalid cursor name"
#define E_3C000 "3C000 Duplicate cursor name"
#define E_3D000 "3D000 Invalid catalog name"
#define E_3F000 "3F000 Invalid schema name"
#define E_40001 "40001 Serialization failure"
#define E_40002 "40002 Integrity constraint violation"
#define E_40003 "40003 Statement completion unknown"
#define E_42000 "42000 Syntax error or access violation"
#define E_42S01 "42S01 Base table or view already exists"
#define E_42S02 "42S02 Base table or view not found"
#define E_42S11 "42S11 Index already exists"
#define E_42S12 "42S12 Index not found"
#define E_42S21 "42S21 Column already exists"
#define E_42S22 "42S22 Column not found"
#define E_44000 "44000 WITH CHECK OPTION violation"
#define E_HY000 "HY000 General error"
#define E_HY001 "HY001 Memory allocation error"
#define E_HY003 "HY003 Invalid application buffer type"
#define E_HY004 "HY004 Invalid SQL data type"
#define E_HY007 "HY007 Associated statement is not prepared"
#define E_HY008 "HY008 Operation canceled"
#define E_HY009 "HY009 Invalid use of null pointer"
#define E_HY010 "HY010 Function sequence error"
#define E_HY011 "HY011 Attribute cannot be set now"
#define E_HY012 "HY012 Invalid transaction operation code"
#define E_HY013 "HY013 Memory management error"
#define E_HY014 "HY014 Limit on the number of handles exceeded"
#define E_HY015 "HY015 No cursor name available"
#define E_HY016 "HY016 Cannot modify an implementation row descriptor"
#define E_HY017 "HY017 Invalid use of an automatically allocated descriptor handle"
#define E_HY018 "HY018 Server declined cancel request"
#define E_HY019 "HY019 Non-character and non-binary data sent in pieces"
#define E_HY020 "HY020 Attempt to concatenate a null value"
#define E_HY021 "HY021 Inconsistent descriptor information"
#define E_HY024 "HY024 Invalid attribute value"
#define E_HY090 "HY090 Invalid string or buffer length"
#define E_HY091 "HY091 Invalid descriptor field identifier"
#define E_HY092 "HY092 Invalid attribute/option identifier"
#define E_HY095 "HY095 Function type out of range"
#define E_HY096 "HY096 Invalid information type"
#define E_HY097 "HY097 Column type out of range"
#define E_HY098 "HY098 Scope type out of range"
#define E_HY099 "HY099 Nullable type out of range"
#define E_HY100 "HY100 Uniqueness option type out of range"
#define E_HY101 "HY101 Accuracy option type out of range"
#define E_HY103 "HY103 Invalid retrieval code"
#define E_HY104 "HY104 Invalid precision or scale value"
#define E_HY105 "HY105 Invalid parameter type"
#define E_HY106 "HY106 Fetch type out of range"
#define E_HY107 "HY107 Row value out of range"
#define E_HY109 "HY109 Invalid cursor position"
#define E_HY110 "HY110 Invalid driver completion"
#define E_HY111 "HY111 Invalid bookmark value"
#define E_HYC00 "HYC00 Optional feature not implemented"
#define E_HYT00 "HYT00 Timeout expired"
#define E_HYT01 "HYT01 Connection timeout expired"
#define E_IM001 "IM001 Driver does not support this function"
#define E_IM002 "IM002 Data source name not found and no default driver specified"
#define E_IM003 "IM003 Specified driver could not be loaded"
#define E_IM004 "IM004 Driver's SQLAllocHandle on SQL_HANDLE_ENV failed"
#define E_IM005 "IM005 Driver's SQLAllocHandle on SQL_HANDLE_DBC failed"
#define E_IM006 "IM006 Driver's SQLSetConnectAttr failed"
#define E_IM007 "IM007 No data source or driver specified; dialog prohibited"
#define E_IM008 "IM008 Dialog failed"
#define E_IM009 "IM009 Unable to load translation DLL"
#define E_IM010 "IM010 Data source name too long"
#define E_IM011 "IM011 Driver name too long"
#define E_IM012 "IM012 DRIVER keyword syntax error"
#define E_IM013 "IM013 Trace file error"
#define E_IM014 "IM014 Invalid name of File DSN"
#define E_IM015 "IM015 Corrupt file data source"
/*
* 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--;
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
*/
#include "h2odbc.h"
char convertBuffer[512];
Descriptor* Descriptor::cast(void* pointer) {
if(pointer==0) {
return 0;
}
Descriptor* desc=Descriptor::cast(pointer);
if(desc->m_magic!=MAGIC_DESCRIPTOR) {
return 0;
}
return desc;
}
Descriptor::Descriptor(Connection* c) {
init();
m_connection = c;
m_type = DT_SHARED;
}
Descriptor::Descriptor() {
init();
m_type = DT_DEFAULT;
}
void Descriptor::init() {
m_magic = MAGIC_DESCRIPTOR;
m_state = D_ACTIVE;
m_arraySize = 0;
m_statusPointer = 0;
m_rowsProcessedPointer = 0;
m_rowWiseBinding = false;
m_rowSize = 0;
m_id = 0;
m_count = 0;
m_error = 0;
}
void Descriptor::setBindingType(bool rowWiseBinding, int rowSize) {
m_rowWiseBinding = rowWiseBinding;
m_rowSize = rowSize;
}
Descriptor::~Descriptor() {
if(m_magic==MAGIC_DESCRIPTOR) {
m_magic=0;
} else {
trace("~Descriptor %d",m_magic);
return;
}
for(int i=0;i<m_records.size();i++) {
delete m_records[i];
m_records[i]=0;
}
}
void Descriptor::readData(int i, Socket* s) {
m_records[i]->readData(s);
}
DescriptorRecord* DescriptorRecord::cast(void* pointer) {
if(pointer==0) {
return 0;
}
DescriptorRecord* rec=(DescriptorRecord*)pointer;
if(rec->m_magic!=MAGIC_DESCRIPTOR_RECORD) {
return 0;
}
return rec;
}
void DescriptorRecord::sendParameterValue(Socket* s) {
int length = m_targetBufferLength;
if(m_statusPointer != 0) {
if(*m_statusPointer == SQL_NULL_DATA) {
s->writeInt(0);
trace(" write null");
return;
} else if(*m_statusPointer == SQL_NTS) {
trace(" len=max");
length = m_targetBufferLength;
} else if(*m_statusPointer == SQL_DEFAULT_PARAM) {
trace(" len=SQL_DEFAULT_PARAM TODO");
length = m_targetBufferLength;
} else if(*m_statusPointer == SQL_DATA_AT_EXEC) {
trace(" len=SQL_DATA_AT_EXEC TODO");
length = m_targetBufferLength;
} else {
length = *m_statusPointer;
trace(" len = %d", length);
}
}
if(m_pointer == 0) {
trace(" pointer==0 TODO");
s->writeInt(0);
return;
}
switch(m_cDataType) {
case SQL_C_SHORT: {
SQLSMALLINT i = *((SQLSMALLINT*)m_pointer);
trace(" write smallInt %d", i);
s->writeInt(SQL_INTEGER);
s->writeInt(i);
break;
}
case SQL_C_LONG: {
SQLINTEGER i = *((SQLINTEGER*)m_pointer);
trace(" write int %d", i);
s->writeInt(SQL_INTEGER);
s->writeInt(i);
break;
}
case SQL_C_CHAR: {
if(length < 0) {
trace(" write String with buffer %d TODO", length);
s->writeInt(0);
} else {
char buff[length+1];
strncpy(buff, (char*)m_pointer, length);
buff[length] = 0;
trace(" write string %s", buff);
s->writeInt(SQL_VARCHAR);
s->writeString(buff);
}
break;
}
default:
trace(" unsupported data type %d", m_cDataType);
}
}
const char* DescriptorRecord::getPrefix() {
return getSuffix();
}
const char* DescriptorRecord::getSuffix() {
switch(m_sqlDataType) {
case SQL_VARCHAR:
case SQL_TYPE_DATE:
case SQL_TYPE_TIME:
case SQL_TYPE_TIMESTAMP:
return ",";
case SQL_DECIMAL:
case SQL_NUMERIC:
case SQL_BIT:
case SQL_TINYINT:
case SQL_SMALLINT:
case SQL_INTEGER:
case SQL_BIGINT:
case SQL_REAL:
case SQL_FLOAT:
case SQL_DOUBLE:
default:
return "";
}
}
int DescriptorRecord::getLength() {
switch(m_sqlDataType) {
case SQL_VARCHAR:
return 255;
case SQL_DECIMAL:
case SQL_NUMERIC:
return 100;
case SQL_BIT:
return 1;
case SQL_TINYINT:
return 3;
case SQL_SMALLINT:
return 5;
case SQL_INTEGER:
return 10;
case SQL_BIGINT:
return 20;
case SQL_REAL:
return 7;
case SQL_FLOAT:
case SQL_DOUBLE:
return 15;
case SQL_TYPE_DATE:
return 10;
case SQL_TYPE_TIME:
return 8;
case SQL_TYPE_TIMESTAMP:
return 40;
default:
return 255;
}
}
void DescriptorRecord::copyData(DescriptorRecord* ar) {
if(m_wasNull) {
ar->setNull();
} else {
switch(ar->m_cDataType) {
case SQL_C_CHAR:
trace(" SQL_CHAR / SQL_VARCHAR");
returnString((SQLCHAR*)ar->m_pointer, ar->m_targetBufferLength, ar->m_statusPointer, getString());
break;
case SQL_C_SLONG:
case SQL_C_ULONG:
trace(" SQL_INTEGER");
returnInt(ar->m_pointer, ar->m_statusPointer, getInt());
break;
case SQL_C_SSHORT:
trace(" SQL_SMALLINT");
returnSmall((SQLSMALLINT*)ar->m_pointer, ar->m_statusPointer, getInt());
break;
default:
trace(" ard not set");
}
}
}
void DescriptorRecord::setNull() {
if(m_statusPointer != 0) {
*m_statusPointer = SQL_NULL_DATA;
}
}
void DescriptorRecord::readData(Socket* s) {
m_wasNull = false;
switch(m_sqlDataType) {
case 0: {
trace(" read null");
m_wasNull = true;
m_dataInt = 0;
break;
}
case SQL_SMALLINT: {
trace(" read smallInt");
m_wasNull = s->readBool();
if(m_wasNull) {
m_dataInt = 0;
} else {
m_dataInt = s->readInt();
}
break;
}
case SQL_INTEGER: {
trace(" read int");
m_wasNull = s->readBool();
if(m_wasNull) {
m_dataInt = 0;
} else {
m_dataInt = s->readInt();
}
break;
}
case SQL_VARCHAR: {
m_dataString = s->readString();
trace(" read string=%s", (char*)m_dataString.data());
break;
}
default:
trace(" unsupported data type %d", (char*)m_dataString.data());
}
}
void DescriptorRecord::readMeta(Socket* s) {
m_sqlDataType = s->readInt();
m_tableName = s->readString();
m_name = s->readString();
m_columnName = m_name;
m_precision = s->readInt();
m_scale = s->readInt();
m_displaySize = s->readInt();
trace(" %s", m_name.data());
}
char* DescriptorRecord::getString() {
switch(m_sqlDataType) {
case SQL_VARCHAR:
trace(" getString s=%s", (char*)m_dataString.data());
return (char*)m_dataString.data();
case SQL_SMALLINT:
case SQL_INTEGER: {
itoa(m_dataInt, convertBuffer, 10);
trace(" getString int %s", convertBuffer);
return convertBuffer;
}
case 0:
trace(" getString null");
return 0;
default:
trace("unsupported type=%d", m_sqlDataType);
}
return "";
}
int DescriptorRecord::getInt() {
switch(m_sqlDataType) {
case SQL_VARCHAR:
return atoi(m_dataString.data());
case SQL_SMALLINT:
case SQL_INTEGER: {
return m_dataInt;
}
case 0:
return 0;
default:
trace("unsupported type=%d", m_sqlDataType);
return 0;
}
}
bool DescriptorRecord::hasFixedPrecisionScale() {
switch(m_sqlDataType) {
case SQL_VARCHAR:
case SQL_INTEGER:
case SQL_SMALLINT:
case 0:
return false;
default:
trace("unsupported type=%d", m_sqlDataType);
return false;
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
*/
#include "h2odbc.h"
Statement::Statement(Connection* c) {
m_magic=MAGIC_STATEMENT;
m_connection=c;
m_appRow=&m_appRowDefault;
m_impRow=&m_impRowDefault;
m_appParam=&m_appParamDefault;
m_impParam=&m_impParamDefault;
m_columnCount = 0;
m_updateCount = 0;
m_resultSetId = -1;
m_preparedId = 0;
m_rowId = 0;
m_hasResultSet = false;
m_parameterCount = 0;
m_useBookmarks = false;
m_error = 0;
}
Statement::~Statement() {
if(m_magic==MAGIC_STATEMENT) {
m_magic=0;
} else {
trace("~Statement %d",m_magic);
return;
}
}
Statement* Statement::cast(void* pointer) {
if(pointer==0) {
return 0;
}
Statement* stat=(Statement*)pointer;
if(stat->m_magic!=MAGIC_STATEMENT) {
return 0;
}
return stat;
}
void Statement::processResultSet(Socket* s) {
m_rowId = 0;
m_updateCount = 0;
m_state = S_EXECUTED;
m_hasResultSet = true;
m_resultSetId = s->readInt();
m_columnCount = s->readInt();
trace(" ResultSet id=%d cols=%d", m_resultSetId, m_columnCount);
m_impRow->clearRecords();
m_appRow->clearRecords();
for(int i=0; i<m_columnCount; i++) {
DescriptorRecord* rec = new DescriptorRecord(m_impRow);
rec->readMeta(s);
m_impRow->addRecord(rec);
rec = new DescriptorRecord(m_appRow);
m_appRow->addRecord(rec);
}
trace(" imp=%d app=%d", m_impRow->getRecordCount(), m_appRow->getRecordCount());
}
void Statement::getMetaTables(char* catalog, char* schema, char* table, char* tabletypes) {
Socket* s = m_connection->getSocket();
s->writeByte('M');
s->writeByte('T');
s->writeString(catalog);
s->writeString(schema);
s->writeString(table);
s->writeString(tabletypes);
processResultSet(s);
}
void Statement::getMetaBestRowIdentifier(char* catalog, char* schema, char* table, int scope, bool nullable) {
Socket* s = m_connection->getSocket();
s->writeByte('M');
s->writeByte('B');
s->writeString(catalog);
s->writeString(schema);
s->writeString(table);
s->writeInt(scope);
s->writeBool(nullable);
processResultSet(s);
}
void Statement::getMetaVersionColumns(char* catalog, char* schema, char* table) {
Socket* s = m_connection->getSocket();
s->writeByte('M');
s->writeByte('V');
s->writeString(catalog);
s->writeString(schema);
s->writeString(table);
processResultSet(s);
}
void Statement::getMetaIndexInfo(char* catalog, char* schema, char* table, bool unique, bool approximate) {
Socket* s = m_connection->getSocket();
s->writeByte('M');
s->writeByte('I');
s->writeString(catalog);
s->writeString(schema);
s->writeString(table);
s->writeBool(unique);
s->writeBool(approximate);
processResultSet(s);
}
void Statement::getMetaColumns(char* catalog, char* schema, char* table, char* column) {
Socket* s = m_connection->getSocket();
s->writeByte('M');
s->writeByte('C');
s->writeString(catalog);
s->writeString(schema);
s->writeString(table);
s->writeString(column);
processResultSet(s);
}
void Statement::getMetaTypeInfoAll() {
Socket* s = m_connection->getSocket();
s->writeByte('M');
s->writeByte('D');
s->writeByte('A');
processResultSet(s);
}
void Statement::getMetaTypeInfo(int sqlType) {
Socket* s = m_connection->getSocket();
s->writeByte('M');
s->writeByte('D');
s->writeByte('T');
s->writeInt(sqlType);
processResultSet(s);
}
const char* Statement::getSQL() {
return m_sql.data();
}
bool Statement::prepare(char* sql) {
Socket* s = m_connection->getSocket();
m_state = S_PREPARED;
s->writeByte('P');
s->writeString(sql);
m_sql = sql;
int result = s->readByte();
if(result=='E') {
m_parameterCount = 0;
m_state = S_CLOSED;
setError(E_42000);
return false;
} else if(result=='O') {
m_preparedId = s->readInt();
m_parameterCount = s->readInt();
m_impParam->clearRecords();
m_appParam->clearRecords();
trace(" prepared %d params=%d", m_preparedId, m_parameterCount);
}
return true;
}
void Statement::addParameter() {
m_impParam->addRecord(new DescriptorRecord(m_impParam));
m_appParam->addRecord(new DescriptorRecord(m_appParam));
}
bool Statement::executePrepared() {
Socket* s = m_connection->getSocket();
s->writeByte('Q');
s->writeInt(m_preparedId);
trace(" executePrepared %d", m_preparedId);
Descriptor* desc = getAppParamDesc();
for(int i=0; i<m_parameterCount; i++) {
s->writeByte('1');
s->writeInt(i);
DescriptorRecord* rec = desc->getRecord(i);
rec->sendParameterValue(s);
}
// end of parameters
s->writeByte('0');
int result = s->readByte();
// TODO: this is copied source code from execute!
m_state = S_EXECUTED;
m_rowId = 0;
m_resultSetId = 0;
m_columnCount = 0;
m_updateCount = 0;
if(result=='E') {
m_state = S_CLOSED;
setError(E_42000);
return false;
} else if(result=='R') {
processResultSet(s);
} else if(result=='U') {
m_state = S_EXECUTED;
m_hasResultSet = false;
m_updateCount = s->readInt();
}
return true;
}
bool Statement::execute(char* sql) {
Socket* s = m_connection->getSocket();
s->writeByte('E');
s->writeString(sql);
m_sql = sql;
int result = s->readByte();
m_state = S_EXECUTED;
m_rowId = 0;
m_resultSetId = 0;
m_columnCount = 0;
m_updateCount = 0;
m_parameterCount = 0;
if(result=='E') {
m_state = S_CLOSED;
// TODO set correct error
setError(E_42000);
return false;
} else if(result=='R') {
processResultSet(s);
} else if(result=='U') {
m_state = S_EXECUTED;
m_hasResultSet = false;
m_updateCount = s->readInt();
} else if(result=='O') {
m_preparedId = s->readInt();
m_parameterCount = s->readInt();
trace(" executeDirect prepared %d params=%d", m_preparedId, m_parameterCount);
return executePrepared();
}
return true;
}
bool Statement::next() {
if(!m_hasResultSet) {
return false;
}
m_rowId++;
Socket* s = m_connection->getSocket();
s->writeByte('G');
s->writeInt(m_resultSetId);
int result = s->readByte();
trace(" next %c", result);
if(result=='E') {
m_state = S_CLOSED;
return false;
} else if(result == '1') {
for(int i=0; i<m_columnCount; i++) {
m_impRow->readData(i, s);
m_impRow->getRecord(i)->copyData(m_appRow->getRecord(i));
}
trace(" setStatus");
m_impRow->setStatus(SQL_ROW_SUCCESS);
trace(" setRowsProcessed");
m_impRow->setRowsProcessed(1);
return true;
} else {
m_impRow->setStatus(SQL_ROW_NOROW);
m_impRow->setRowsProcessed(0);
return false;
}
return m_resultSetId == 0;
}
void Statement::closeCursor() {
if(m_resultSetId >= 0) {
Socket* s = m_connection->getSocket();
s->writeByte('F');
s->writeInt(m_resultSetId);
m_resultSetId = -1;
}
m_state=S_CLOSED;
}
Descriptor* Statement::getAppRowDesc() {
return m_appRow;
}
Descriptor* Statement::getImpRowDesc() {
return m_impRow;
}
Descriptor* Statement::getAppParamDesc() {
return m_appParam;
}
Descriptor* Statement::getImpParamDesc() {
return m_impParam;
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
*/
#define IDD_CONFIG 101
#define IDI_ICON 102
#define IDC_URL 1000
#define IDC_NAME 1001
#define IDC_USER 1002
#define IDC_PASSWORD 1003
#include "resource.h"
#include <windows.h>
#include <afxres.h>
IDD_CONFIG DIALOG DISCARDABLE 0, 0, 251, 119
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Database Driver Configuration"
FONT 8, "MS Sans Serif"
BEGIN
EDITTEXT IDC_NAME,81,7,163,14,ES_AUTOHSCROLL
EDITTEXT IDC_URL,81,34,163,14,ES_AUTOHSCROLL
EDITTEXT IDC_USER,81,50,163,14,ES_AUTOHSCROLL
EDITTEXT IDC_PASSWORD,81,66,163,14,ES_PASSWORD | ES_AUTOHSCROLL
DEFPUSHBUTTON "OK",IDOK,137,98,50,14
PUSHBUTTON "Cancel",IDCANCEL,194,98,50,14
LTEXT "Database URL:", IDC_STATIC,7,37,72,8
LTEXT "Data Source Name:",IDC_STATIC,7,10,70,8
LTEXT "User Name:",IDC_STATIC,7,53,71,8
LTEXT "Password:",IDC_STATIC,7,69,71,8
CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ | SS_SUNKEN |
WS_GROUP,7,87,237,1
CONTROL "",IDC_STATIC,"Static",SS_ETCHEDHORZ | SS_SUNKEN |
WS_GROUP,7,27,236,1
END
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
*/
#include "h2odbc.h"
bool m_socket_init = false;
Socket::Socket(const char* host,int port) {
if(!m_socket_init) {
initSockets();
m_socket_init = true;
}
m_socket=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);
if(m_socket==INVALID_SOCKET) {
setError("socket");
return;
}
// check if it's an IP number (because that's simpler)
// could be also IPv6 or something, if Winsocks supports that
// also supported is 0x4.0x3.0x2.0x10
SOCKADDR_IN sin;
memset((void*)&sin,0,sizeof(sin));
sin.sin_family=AF_INET;
sin.sin_port=htons(port);
long addr=inet_addr(host);
if(addr=!INADDR_NONE) {
sin.sin_addr.s_addr=addr;
} else {
// ok then it's hopefully a host name
HOSTENT* hostent;
hostent=gethostbyname(host);
if(hostent==NULL) {
setError("gethostbyname");
return;
}
// take the first ip address
memcpy(
&sin.sin_addr,
hostent->h_addr_list[0],
hostent->h_length);
}
int result=connect(m_socket,(sockaddr*)&sin,sizeof(sin));
if(result==SOCKET_ERROR) {
setError("connect");
return;
}
}
void Socket::close() {
if(m_socket==0) {
return;
}
closesocket(m_socket);
m_socket=0;
}
int Socket::readByte() {
if(m_socket==0) {
return -1;
}
char buffer[1];
read(buffer,1);
// trace(" readByte=%c", buffer[0]);
return buffer[0];
}
int Socket::readInt() {
if(m_socket==0) {
return -1;
}
char buffer[4];
read(buffer, 4);
int x = ((buffer[0] & 0xff) << 24) | ((buffer[1] & 0xff) << 16) |
((buffer[2] & 0xff) << 8) | (buffer[3] & 0xff);
return x;
}
void Socket::read(char* buffer, int len) {
if(m_socket==0) {
return;
}
do {
int result=recv(m_socket,buffer,len,0);
if(result==0) {
// closed?
setError("recv");
return;
} else if(result==SOCKET_ERROR) {
setError("recv");
return;
}
len-=result;
buffer+=result;
} while(len>0);
}
Socket* Socket::writeString(const char* string) {
// trace(" writeString %s", string);
int len = strlen(string);
writeInt(len);
write(string, len);
return this;
}
string Socket::readString() {
if(m_socket==0) {
return "";
}
int len = readInt();
if(len<0) {
len = 0;
}
char buffer[len+1];
if(len==0) {
buffer[0]=0;
} else {
read(buffer, len);
buffer[len] = 0;
}
// trace(" readString len=%d s=%s", len, buffer);
return buffer;
}
Socket* Socket::writeByte(int byte) {
// trace(" writeByte %c", byte);
char buffer[1];
buffer[0]=byte;
write(buffer, 1);
return this;
}
Socket* Socket::writeBool(bool x) {
// trace(" writeBoox %d", x ? 1 : 0);
writeInt(x ? 1 : 0);
return this;
}
bool Socket::readBool() {
return readInt() == 1;
}
Socket* Socket::writeInt(int x) {
// trace(" writeInt=%d", x);
char buffer[4];
buffer[0] = (x >> 24) & 0xff;
buffer[1] = (x >> 16) & 0xff;
buffer[2] = (x >> 8) & 0xff;
buffer[3] = x & 0xff;
write(buffer, 4);
return this;
}
void Socket::write(const char* buffer, int len) {
if(m_socket==0) {
return;
}
do {
int result=send(m_socket,buffer,len,0);
if(result==SOCKET_ERROR) {
setError("send");
return;
}
len-=result;
buffer+=result;
} while(len>0);
}
void Socket::setError(char* where) {
m_socket=0;
int error=WSAGetLastError();
trace("Socket error %d in %s", error, where);
}
void initSockets() {
trace("initSockets");
WORD wVersionRequested;
WSADATA wsaData;
wVersionRequested = MAKEWORD( 1, 1 );
int err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 ) {
trace("No Winsock.dll");
return;
}
if ( LOBYTE( wsaData.wVersion ) != 1 ||
HIBYTE( wsaData.wVersion ) != 1 ) {
trace("No Winsock.dll v1.1");
WSACleanup( );
return;
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
*/
#include "h2odbc.h"
SQLRETURN SQL_API SQLAllocHandle(SQLSMALLINT HandleType,
SQLHANDLE InputHandle, SQLHANDLE* OutputHandle) {
trace("SQLAllocHandle");
if(OutputHandle==0) {
return SQL_ERROR;
}
switch(HandleType) {
case SQL_HANDLE_ENV:
trace(" SQL_HANDLE_ENV");
*OutputHandle=new Environment();
break;
case SQL_HANDLE_DBC: {
trace(" SQL_HANDLE_DBC");
Environment* env=Environment::cast(InputHandle);
if(env==0) {
return SQL_INVALID_HANDLE;
}
env->setError(0);
Connection* conn = env->createConnection();
*OutputHandle = conn;
// trace(" use ODBC cursor library if possible");
// SQLSetConnectAttr(conn, SQL_ATTR_ODBC_CURSORS, (void*)SQL_CUR_USE_ODBC);
break;
}
case SQL_HANDLE_STMT: {
trace(" SQL_HANDLE_STMT");
Connection* conn = Connection::cast(InputHandle);
if(conn==0) {
return SQL_INVALID_HANDLE;
}
conn->setError(0);
if(conn->isClosed()) {
conn->setError(E_08003);
return SQL_ERROR;
}
*OutputHandle=new Statement(conn);
break;
}
case SQL_HANDLE_DESC: {
trace(" SQL_HANDLE_DESC");
Connection* conn = Connection::cast(InputHandle);
if(conn==0) {
return SQL_INVALID_HANDLE;
}
conn->setError(0);
if(conn->isClosed()) {
conn->setError(E_08003);
return SQL_ERROR;
}
*OutputHandle=new Descriptor(conn);
break;
}
default:
trace(" ? %d TODO ", HandleType);
return SQL_ERROR;
}
return SQL_SUCCESS;
}
SQLRETURN SQL_API SQLBindCol(SQLHSTMT StatementHandle,
SQLUSMALLINT ColumnNumber, SQLSMALLINT TargetType,
SQLPOINTER TargetValue, SQLINTEGER BufferLength,
SQLINTEGER* StrLen_or_Ind) {
trace("SQLBindCol");
Statement* stat=Statement::cast(StatementHandle);
if(stat==0) {
return SQL_INVALID_HANDLE;
}
stat->setError(0);
trace(" getAppRowDesc");
Descriptor* desc = stat->getAppRowDesc();
if(desc == 0) {
trace(" desc=null");
return SQL_ERROR;
}
ColumnNumber--;
trace(" ColumnNumber=%d", ColumnNumber);
if(ColumnNumber > stat->getColumnCount()) {
trace(" columnCount=%d", stat->getColumnCount());
return SQL_ERROR;
}
trace(" getRecord");
if(ColumnNumber >= desc->getRecordCount()) {
trace(" wrong column; cols=%d", desc->getRecordCount());
}
DescriptorRecord* rec = desc->getRecord(ColumnNumber);
if(rec == 0) {
trace(" rec out of range");
return SQL_ERROR;
}
trace(" setTargetDataType");
rec->setCDataType(TargetType);
trace(" setTargetPointer");
rec->setTargetPointer(TargetValue);
trace(" setTargetBufferLength");
rec->setTargetBufferLength(BufferLength);
trace(" setTargetStatusPointer");
rec->setTargetStatusPointer(StrLen_or_Ind);
return SQL_SUCCESS;
}
SQLRETURN SQL_API SQLBindParameter(
SQLHSTMT StatementHandle,
SQLUSMALLINT ParameterNumber,
SQLSMALLINT InputOutputType,
SQLSMALLINT ValueType,
SQLSMALLINT ParameterType,
SQLUINTEGER ColumnSize,
SQLSMALLINT DecimalDigits,
SQLPOINTER ParameterValuePtr,
SQLINTEGER BufferLength,
SQLINTEGER* StrLen_or_IndPtr) {
trace("SQLBindParameter");
Statement* stat=Statement::cast(StatementHandle);
if(stat==0) {
return SQL_INVALID_HANDLE;
}
stat->setError(0);
switch(InputOutputType) {
case SQL_PARAM_INPUT:
trace(" SQL_PARAM_INPUT");
break;
case SQL_PARAM_INPUT_OUTPUT:
trace(" SQL_PARAM_INPUT_OUTPUT");
break;
case SQL_PARAM_OUTPUT:
trace(" SQL_PARAM_OUTPUT");
break;
default:
trace(" ? %d TODO ", InputOutputType);
return SQL_ERROR;
}
Descriptor* desc = stat->getAppParamDesc();
ParameterNumber--;
while(desc->getRecordCount() <= ParameterNumber) {
stat->addParameter();
}
DescriptorRecord* rec = desc->getRecord(ParameterNumber);
if(rec==0) {
trace(" rec=0 TODO");
}
if(ValueType == SQL_C_DEFAULT) {
trace(" SQL_C_DEFAULT");
ValueType = getDefaultCType(ParameterType);
}
trace(" ValueType=%d, ParameterType=%d", ValueType, ParameterType);
rec->setSqlDataType(ParameterType);
rec->setCDataType(ValueType);
rec->setTargetPointer(ParameterValuePtr);
rec->setTargetBufferLength(ColumnSize);
rec->setTargetStatusPointer(StrLen_or_IndPtr);
return SQL_SUCCESS;
}
SQLRETURN SQL_API SQLCancel(SQLHSTMT StatementHandle) {
trace("SQLCancel TODO");
return SQL_SUCCESS;
}
SQLRETURN SQL_API SQLCloseCursor(SQLHSTMT StatementHandle) {
trace("SQLCloseCursor");
Statement* stat=Statement::cast(StatementHandle);
if(stat==0) {
return SQL_INVALID_HANDLE;
}
stat->setError(0);
stat->closeCursor();
return SQL_SUCCESS;
}
SQLRETURN SQL_API SQLDriverConnect(
SQLHDBC ConnectionHandle,
SQLHWND WindowHandle,
SQLCHAR* InConnectionString,
SQLSMALLINT StringLength1,
SQLCHAR* OutConnectionString,
SQLSMALLINT BufferLength,
SQLSMALLINT* StringLength2Ptr,
SQLUSMALLINT DriverCompletion) {
trace("SQLDriverConnect");
Connection* conn=Connection::cast(ConnectionHandle);
if(conn==0) {
return SQL_INVALID_HANDLE;
}
conn->setError(0);
char connect[1024];
char url[1024];
char user[1024];
char password[1024];
strcpy(url, "");
strcpy(user, "");
strcpy(password, "");
setString(connect,sizeof(connect),InConnectionString,StringLength1);
char* start = strstr(connect, "DSN=");
if(start != 0) {
char dns[1024];
strncpy(dns, start+4, strlen(start+4));
char* end = strstr(dns, ";");
if(end != 0) {
*end = 0;
}
conn->setDataSourceName(dns);
SQLGetPrivateProfileString(
dns,
"URL", "", url, MAX_STRING_LEN,
"ODBC.INI");
SQLGetPrivateProfileString(
dns,
"User", "", user, MAX_STRING_LEN,
"ODBC.INI");
SQLGetPrivateProfileString(
dns,
"Password", "", password, MAX_STRING_LEN,
"ODBC.INI");
}
trace(" url=%s user=%s password=%s", url, user, password);
trace(" connect=%s DSN=<%s>", connect, conn->getDataSourceName().data());
strcat(connect,"UID=sa;PWD=;DRIVER=h2odbc");
conn->open(url, user, password);
if(conn->getError() != 0) {
return SQL_ERROR;
}
returnString(OutConnectionString,BufferLength,StringLength2Ptr,connect);
trace(" %s",connect);
return SQL_SUCCESS;
}
SQLRETURN SQL_API SQLConnect(SQLHDBC ConnectionHandle,
SQLCHAR* ServerName, SQLSMALLINT NameLength1,
SQLCHAR* UserName, SQLSMALLINT NameLength2,
SQLCHAR* Authentication, SQLSMALLINT NameLength3) {
trace("SQLConnect");
Connection* conn = Connection::cast(ConnectionHandle);
if(conn==0) {
return SQL_INVALID_HANDLE;
}
conn->setError(0);
char name[512];
char user[512];
char password[512];
setString(name,sizeof(name),ServerName,NameLength1);
setString(user,sizeof(user),UserName,NameLength2);
setString(password,sizeof(password),Authentication,NameLength3);
trace(" dns=%s user=%s", name, user);
conn->setDataSourceName(name);
conn->open(name,user,password);
return SQL_SUCCESS;
}
SQLRETURN SQL_API SQLCopyDesc(SQLHDESC SourceDescHandle,
SQLHDESC TargetDescHandle) {
trace("SQLCopyDesc TODO");
return SQL_ERROR;
}
SQLRETURN SQL_API SQLDescribeCol(SQLHSTMT StatementHandle,
SQLUSMALLINT ColumnNumber, SQLCHAR* ColumnName,
SQLSMALLINT BufferLength, SQLSMALLINT* NameLengthPtr,
SQLSMALLINT* DataTypePtr, SQLUINTEGER* ColumnSizePtr,
SQLSMALLINT* DecimalDigitsPtr, SQLSMALLINT* NullablePtr) {
trace("SQLDescribeCol");
Statement* stat=Statement::cast(StatementHandle);
if(stat==0) {
return SQL_INVALID_HANDLE;
}
stat->setError(0);
Descriptor* desc = stat->getImpRowDesc();
ColumnNumber--;
if(ColumnNumber >= desc->getRecordCount()) {
trace("SQLDescribeCol E_07009 %d", ColumnNumber);
stat->setError(E_07009);
return SQL_ERROR;
}
trace(" column %d", ColumnNumber);
DescriptorRecord* rec = desc->getRecord(ColumnNumber);
returnString((SQLCHAR*)ColumnName, BufferLength, NameLengthPtr, rec->getColumnName().data());
trace(" =%s", (SQLCHAR*)ColumnName);
returnSmall(DataTypePtr, (SQLINTEGER*)0, rec->getSqlDataType());
returnInt(ColumnSizePtr, rec->getDisplaySize());
trace(" =%d", rec->getDisplaySize());
returnSmall(DecimalDigitsPtr, (SQLINTEGER*)0, 0);
returnSmall(NullablePtr, (SQLINTEGER*)0, SQL_NULLABLE_UNKNOWN);
return SQL_SUCCESS;
}
SQLRETURN SQL_API SQLDisconnect(SQLHDBC ConnectionHandle) {
trace("SQLDisconnect");
Connection* conn = Connection::cast(ConnectionHandle);
if(conn==0) {
return SQL_INVALID_HANDLE;
}
conn->setError(0);
conn->close();
return SQL_SUCCESS;
}
SQLRETURN SQL_API SQLEndTran(SQLSMALLINT HandleType, SQLHANDLE Handle,
SQLSMALLINT CompletionType) {
trace("SQLEndTran");
switch(HandleType) {
case SQL_HANDLE_ENV: {
trace(" SQL_HANDLE_ENV TODO");
Environment* env = Environment::cast(Handle);
if(env==0) {
return SQL_INVALID_HANDLE;
}
env->setError(0);
break;
}
case SQL_HANDLE_DBC: {
trace(" SQL_HANDLE_DBC");
Connection* conn = Connection::cast(Handle);
if(conn==0) {
return SQL_INVALID_HANDLE;
}
conn->setError(0);
switch(CompletionType) {
case SQL_COMMIT:
trace(" SQL_COMMIT");
conn->commit();
break;
case SQL_ROLLBACK:
trace(" SQL_ROLLBACK");
conn->rollback();
break;
default:
conn->setError(E_HY012);
return SQL_ERROR;
break;
}
break;
}
default:
trace(" ? %d TODO ", HandleType);
return SQL_ERROR;
}
return SQL_SUCCESS;
}
SQLRETURN SQL_API SQLExecDirect(SQLHSTMT StatementHandle,
SQLCHAR* StatementText, SQLINTEGER TextLength) {
trace("SQLExecDirect");
Statement* stat=Statement::cast(StatementHandle);
if(stat==0) {
return SQL_INVALID_HANDLE;
}
stat->setError(0);
char sql[512];
setString(sql,sizeof(sql),StatementText,TextLength);
trace(" %s", sql);
if(stat->execute(sql)) {
return SQL_SUCCESS;
} else {
return SQL_ERROR;
}
}
SQLRETURN SQL_API SQLExecute(SQLHSTMT StatementHandle) {
trace("SQLExecute");
Statement* stat=Statement::cast(StatementHandle);
if(stat==0) {
return SQL_INVALID_HANDLE;
}
stat->setError(0);
if(stat->executePrepared()) {
return SQL_SUCCESS;
} else {
return SQL_ERROR;
}
}
SQLRETURN SQL_API SQLFetch(SQLHSTMT StatementHandle) {
trace("SQLFetch");
Statement* stat=Statement::cast(StatementHandle);
if(stat==0) {
return SQL_INVALID_HANDLE;
}
stat->setError(0);
if(!stat->next()) {
trace(" SQL_NO_DATA");
return SQL_NO_DATA;
} else {
trace(" SQL_SUCCESS");
return SQL_SUCCESS;
}
}
SQLRETURN SQL_API SQLFetchScroll(SQLHSTMT StatementHandle,
SQLSMALLINT FetchOrientation, SQLINTEGER FetchOffset) {
trace("SQLFetchScroll");
Statement* stat=Statement::cast(StatementHandle);
if(stat==0) {
return SQL_INVALID_HANDLE;
}
stat->setError(0);
switch(FetchOrientation) {
case SQL_FETCH_NEXT: {
trace(" SQL_FETCH_NEXT");
if(stat->next()) {
return SQL_SUCCESS;
}
return SQL_NO_DATA;
}
case SQL_FETCH_PRIOR:
trace(" SQL_FETCH_PRIOR TODO");
return SQL_ERROR;
break;
case SQL_FETCH_RELATIVE:
trace(" SQL_FETCH_RELATIVE TODO");
return SQL_ERROR;
break;
case SQL_FETCH_ABSOLUTE:
trace(" SQL_FETCH_ABSOLUTE TODO");
return SQL_ERROR;
break;
case SQL_FETCH_FIRST:
trace(" SQL_FETCH_FIRST TODO");
return SQL_ERROR;
break;
case SQL_FETCH_LAST:
trace(" SQL_FETCH_LAST TODO");
return SQL_ERROR;
break;
case SQL_FETCH_BOOKMARK:
trace(" SQL_FETCH_BOOKMARK TODO");
return SQL_ERROR;
break;
default:
trace(" ? %d", FetchOrientation);
return SQL_ERROR;
break;
}
return SQL_SUCCESS;
}
SQLRETURN SQL_API SQLFreeHandle(SQLSMALLINT HandleType, SQLHANDLE Handle) {
trace("SQLFreeHandle");
switch(HandleType) {
case SQL_HANDLE_ENV: {
trace(" SQL_HANDLE_ENV");
Environment* env=Environment::cast(Handle);
if(env==0) {
return SQL_INVALID_HANDLE;
}
env->setError(0);
if(env->getOpenConnectionCount()>0) {
return SQL_ERROR;
}
delete env;
break;
}
case SQL_HANDLE_DBC: {
trace(" SQL_HANDLE_DBC");
Connection* conn=Connection::cast(Handle);
if(conn==0) {
return SQL_INVALID_HANDLE;
}
conn->setError(0);
if(!conn->isClosed()) {
return SQL_ERROR;
}
Environment* env=conn->getEnvironment();
env->closeConnection(conn);
break;
}
case SQL_HANDLE_STMT: {
trace(" SQL_HANDLE_STMT");
Statement* stat=Statement::cast(Handle);
if(stat==0) {
return SQL_INVALID_HANDLE;
}
stat->setError(0);
delete stat;
break;
}
case SQL_HANDLE_DESC: {
trace(" SQL_HANDLE_DESC");
Descriptor* desc=Descriptor::cast(Handle);
if(desc==0) {
return SQL_INVALID_HANDLE;
}
desc->setError(0);
delete desc;
break;
}
default:
trace(" ? %d TODO", HandleType);
return SQL_INVALID_HANDLE;
}
return SQL_SUCCESS;
}
SQLRETURN SQL_API SQLFreeStmt(SQLHSTMT StatementHandle,
SQLUSMALLINT Option) {
trace("SQLFreeStmt");
Statement* stat=Statement::cast(StatementHandle);
if(stat==0) {
return SQL_INVALID_HANDLE;
}
stat->setError(0);
switch(Option) {
case SQL_CLOSE:
trace(" SQL_CLOSE");
stat->closeCursor();
break;
case SQL_UNBIND:
trace(" SQL_UNBIND TODO");
break;
case SQL_RESET_PARAMS:
trace(" SQL_RESET_PARAMS TODO");
break;
default:
trace("%d TODO",Option);
return SQL_ERROR;
}
return SQL_SUCCESS;
}
SQLRETURN SQL_API SQLGetCursorName(SQLHSTMT StatementHandle,
SQLCHAR* CursorName, SQLSMALLINT BufferLength,
SQLSMALLINT* NameLength) {
trace("SQLGetCursorName TODO");
Statement* stat=Statement::cast(StatementHandle);
if(stat==0) {
return SQL_INVALID_HANDLE;
}
stat->setError(E_IM001);
return SQL_ERROR;
}
SQLRETURN SQL_API SQLGetData(SQLHSTMT StatementHandle,
SQLUSMALLINT ColumnNumber, SQLSMALLINT TargetType,
SQLPOINTER TargetValue, SQLINTEGER BufferLength,
SQLINTEGER* StrLen_or_Ind) {
trace("SQLGetData col=%d", ColumnNumber, TargetType);
Statement* stat=Statement::cast(StatementHandle);
if(stat==0) {
return SQL_INVALID_HANDLE;
}
stat->setError(0);
Descriptor* desc = stat->getImpRowDesc();
ColumnNumber--;
if(ColumnNumber > stat->getColumnCount()) {
trace(" columnCount=%d", stat->getColumnCount());
return SQL_ERROR;
}
DescriptorRecord* rec = desc->getRecord(ColumnNumber);
if(rec->wasNull()) {
if(StrLen_or_Ind==0) {
trace(" wasNull error");
stat->setError(E_22002);
return SQL_ERROR;
}
trace(" wasNull");
*StrLen_or_Ind=SQL_NULL_DATA;
return SQL_SUCCESS;
}
if(TargetType == SQL_C_DEFAULT) {
TargetType = getDefaultCType(rec->getSqlDataType());
trace(" SQL_C_DEFAULT set to %d", TargetType);
}
switch(TargetType) {
case SQL_CHAR:
case SQL_VARCHAR:
trace(" SQL_CHAR / SQL_VARCHAR");
returnString((SQLCHAR*)TargetValue, BufferLength, StrLen_or_Ind, rec->getString());
break;
case SQL_INTEGER:
trace(" SQL_INTEGER");
returnInt(TargetValue, StrLen_or_Ind, rec->getInt());
break;
case SQL_SMALLINT:
trace(" SQL_SMALLINT");
returnSmall((SQLSMALLINT*)TargetValue, StrLen_or_Ind, rec->getInt());
break;
default:
trace(" type=%d TODO", TargetType);
}
return SQL_SUCCESS;
}
SQLRETURN SQL_API SQLGetDescField(SQLHDESC DescriptorHandle,
SQLSMALLINT RecNumber, SQLSMALLINT FieldIdentifier,
SQLPOINTER Value, SQLINTEGER BufferLength,
SQLINTEGER* StringLength) {
trace("SQLGetDescField TODO");
Descriptor* desc = Descriptor::cast(DescriptorHandle);
if(desc==0) {
return SQL_INVALID_HANDLE;
}
desc->setError(0);
RecNumber--;
if(RecNumber < 0 || desc->getRecordCount() >= RecNumber) {
desc->setError(E_07009);
return SQL_ERROR;
}
return SQL_ERROR;
}
SQLRETURN SQL_API SQLGetDescRec(SQLHDESC DescriptorHandle,
SQLSMALLINT RecNumber, SQLCHAR* Name,
SQLSMALLINT BufferLength, SQLSMALLINT* StringLength,
SQLSMALLINT* Type, SQLSMALLINT* SubType,
SQLINTEGER* Length, SQLSMALLINT* Precision,
SQLSMALLINT* Scale, SQLSMALLINT* Nullable) {
trace("SQLGetDescRec TODO");
return SQL_ERROR;
}
SQLRETURN SQL_API SQLGetEnvAttr(SQLHENV EnvironmentHandle,
SQLINTEGER Attribute, SQLPOINTER Value,
SQLINTEGER BufferLength, SQLINTEGER* StringLength) {
trace("SQLGetEnvAttr %d",Attribute);
Environment* env=Environment::cast(EnvironmentHandle);
if(env==0) {
return SQL_INVALID_HANDLE;
}
env->setError(0);
switch(Attribute) {
case SQL_ATTR_ODBC_VERSION:
trace(" SQL_ATTR_ODBC_VERSION");
returnInt(Value,StringLength,env->getBehavior());
break;
case SQL_ATTR_CONNECTION_POOLING:
trace(" SQL_ATTR_CONNECTION_POOLING");
break;
case SQL_ATTR_CP_MATCH:
trace(" SQL_ATTR_CP_MATCH");
break;
case SQL_ATTR_OUTPUT_NTS:
trace(" SQL_ATTR_OUTPUT_NTS");
returnInt(Value,StringLength,SQL_TRUE);
break;
default:
trace(" %d",Attribute);
return SQL_ERROR;
}
return SQL_SUCCESS;
}
SQLRETURN SQL_API SQLNumResultCols(SQLHSTMT StatementHandle,
SQLSMALLINT* ColumnCount) {
trace("SQLNumResultCols");
Statement* stat=Statement::cast(StatementHandle);
if(stat==0) {
return SQL_INVALID_HANDLE;
}
stat->setError(0);
int count = stat->getColumnCount();
returnInt(ColumnCount, count);
trace(" %d", count);
return SQL_SUCCESS;
}
SQLRETURN SQL_API SQLNativeSql(
SQLHDBC ConnectionHandle,
SQLCHAR* InStatementText,
SQLINTEGER TextLength1,
SQLCHAR* OutStatementText,
SQLINTEGER BufferLength,
SQLINTEGER* TextLength2Ptr) {
trace("SQLNativeSql");
Connection* conn=Connection::cast(ConnectionHandle);
if(conn==0) {
return SQL_INVALID_HANDLE;
}
conn->setError(0);
char sql[512];
setString(sql,sizeof(sql),InStatementText,TextLength1);
string translated = conn->getNativeSQL(sql);
returnString(OutStatementText,BufferLength,TextLength2Ptr,translated.data());
return SQL_SUCCESS;
}
SQLRETURN SQL_API SQLNumParams(
SQLHSTMT StatementHandle,
SQLSMALLINT* ParameterCountPtr ) {
trace("SQLNumParams");
Statement* stat=Statement::cast(StatementHandle);
if(stat==0) {
return SQL_INVALID_HANDLE;
}
stat->setError(0);
int params = stat->getParametersCount();
returnInt(ParameterCountPtr, params);
return SQL_SUCCESS;
}
SQLRETURN SQL_API SQLParamData(SQLHSTMT StatementHandle,
SQLPOINTER* Value) {
trace("SQLParamData TODO");
return SQL_ERROR;
}
SQLRETURN SQL_API SQLPrepare(SQLHSTMT StatementHandle,
SQLCHAR* StatementText, SQLINTEGER TextLength) {
trace("SQLPrepare");
// TODO should support longer statements
char sql[512];
setString(sql,sizeof(sql),StatementText,TextLength);
trace(" %s", sql);
Statement* stat=Statement::cast(StatementHandle);
if(stat==0) {
return SQL_INVALID_HANDLE;
}
stat->setError(0);
if(stat->prepare(sql)) {
return SQL_SUCCESS;
} else {
return SQL_ERROR;
}
}
SQLRETURN SQL_API SQLPutData(SQLHSTMT StatementHandle,
SQLPOINTER Data, SQLINTEGER StrLen_or_Ind) {
trace("SQLPutData TODO");
return SQL_ERROR;
}
SQLRETURN SQL_API SQLRowCount(SQLHSTMT StatementHandle,
SQLINTEGER* RowCount) {
trace("SQLRowCount");
Statement* stat=Statement::cast(StatementHandle);
if(stat==0) {
return SQL_INVALID_HANDLE;
}
stat->setError(0);
trace(" %d", stat->getUpdateCount());
returnInt(RowCount, (SQLINTEGER*)0, stat->getUpdateCount());
return SQL_SUCCESS;
}
SQLRETURN SQL_API SQLSetCursorName(SQLHSTMT StatementHandle,
SQLCHAR* CursorName, SQLSMALLINT NameLength) {
trace("SQLSetCursorName TODO");
return SQL_ERROR;
}
SQLRETURN SQL_API SQLSetDescField(SQLHDESC DescriptorHandle,
SQLSMALLINT RecNumber, SQLSMALLINT FieldIdentifier,
SQLPOINTER Value, SQLINTEGER BufferLength) {
trace("SQLSetDescField TODO");
return SQL_ERROR;
}
SQLRETURN SQL_API SQLSetDescRec(SQLHDESC DescriptorHandle,
SQLSMALLINT RecNumber, SQLSMALLINT Type,
SQLSMALLINT SubType, SQLINTEGER Length,
SQLSMALLINT Precision, SQLSMALLINT Scale,
SQLPOINTER Data, SQLINTEGER* StringLength,
SQLINTEGER* Indicator) {
trace("SQLSetDescRec TODO");
return SQL_ERROR;
}
SQLRETURN SQL_API SQLSetEnvAttr(SQLHENV EnvironmentHandle,
SQLINTEGER Attribute, SQLPOINTER Value,
SQLINTEGER StringLength) {
trace("SQLSetEnvAttr");
Environment* env=Environment::cast(EnvironmentHandle);
if(env==0) {
return SQL_INVALID_HANDLE;
}
env->setError(0);
switch(Attribute) {
case SQL_ATTR_ODBC_VERSION:
env->setBehavior((int)Value);
trace(" SQL_ATTR_ODBC_VERSION");
return SQL_SUCCESS;
case SQL_ATTR_CONNECTION_POOLING:
trace(" SQL_ATTR_CONNECTION_POOLING TODO");
case SQL_ATTR_CP_MATCH:
trace(" SQL_ATTR_CP_MATCH TODO");
case SQL_ATTR_OUTPUT_NTS:
trace(" SQL_ATTR_OUTPUT_NTS TODO");
if((int)Value==SQL_TRUE) {
return SQL_ERROR;
} else {
return SQL_ERROR;
}
default:
trace(" ? %d TODO",Attribute);
return SQL_ERROR;
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
*/
#include "h2odbc.h"
SQLRETURN SQLColAttribute (
SQLHSTMT StatementHandle,
SQLUSMALLINT ColumnNumber,
SQLUSMALLINT FieldIdentifier,
SQLPOINTER CharacterAttributePtr,
SQLSMALLINT BufferLength,
SQLSMALLINT* StringLengthPtr,
SQLPOINTER NumericAttributePtr) {
trace("SQLColAttribute col=%d", ColumnNumber);
Statement* stat=Statement::cast(StatementHandle);
if(stat==0) {
return SQL_INVALID_HANDLE;
}
stat->setError(0);
Descriptor* desc = stat->getImpRowDesc();
ColumnNumber--;
if(ColumnNumber > stat->getColumnCount()) {
trace(" columnCount=%d", stat->getColumnCount());
return SQL_ERROR;
}
DescriptorRecord* rec = desc->getRecord(ColumnNumber);
switch(FieldIdentifier) {
case SQL_DESC_AUTO_UNIQUE_VALUE:
trace(" SQL_DESC_AUTO_UNIQUE_VALUE");
returnInt(NumericAttributePtr, SQL_FALSE);
break;
case SQL_DESC_BASE_COLUMN_NAME:
trace(" SQL_DESC_BASE_COLUMN_NAME");
returnString((SQLCHAR*)CharacterAttributePtr, BufferLength, StringLengthPtr, "");
break;
case SQL_DESC_BASE_TABLE_NAME:
trace(" SQL_DESC_BASE_TABLE_NAME");
returnString((SQLCHAR*)CharacterAttributePtr, BufferLength, StringLengthPtr, "");
break;
case SQL_DESC_CASE_SENSITIVE:
trace(" SQL_DESC_CASE_SENSITIVE");
returnInt(NumericAttributePtr, SQL_TRUE);
break;
case SQL_DESC_CATALOG_NAME:
trace(" SQL_DESC_CATALOG_NAME");
returnString((SQLCHAR*)CharacterAttributePtr, BufferLength, StringLengthPtr, "");
break;
case SQL_DESC_CONCISE_TYPE:
trace(" SQL_DESC_CONCISE_TYPE");
returnInt(NumericAttributePtr, rec->getSqlDataType());
break;
case SQL_DESC_COUNT:
trace(" SQL_DESC_COUNT");
returnInt(NumericAttributePtr, stat->getColumnCount());
break;
case SQL_DESC_DISPLAY_SIZE:
trace(" SQL_DESC_DISPLAY_SIZE");
returnInt(NumericAttributePtr, rec->getDisplaySize());
break;
case SQL_DESC_FIXED_PREC_SCALE:
trace(" SQL_DESC_FIXED_PREC_SCALE");
returnInt(NumericAttributePtr, rec->hasFixedPrecisionScale() ? SQL_TRUE : SQL_FALSE);
break;
case SQL_DESC_LABEL:
trace(" SQL_DESC_LABEL");
returnString((SQLCHAR*)CharacterAttributePtr, BufferLength, StringLengthPtr, rec->getColumnName().data());
break;
case SQL_DESC_LENGTH:
trace(" SQL_DESC_LENGTH =%d", rec->getLength());
returnInt(NumericAttributePtr, rec->getLength());
break;
case SQL_DESC_LITERAL_PREFIX:
trace(" SQL_DESC_LITERAL_PREFIX %s", rec->getPrefix());
returnString((SQLCHAR*)CharacterAttributePtr, BufferLength, StringLengthPtr, rec->getPrefix());
break;
case SQL_DESC_LITERAL_SUFFIX:
trace(" SQL_DESC_LITERAL_SUFFIX %s", rec->getSuffix());
returnString((SQLCHAR*)CharacterAttributePtr, BufferLength, StringLengthPtr, rec->getSuffix());
break;
case SQL_DESC_LOCAL_TYPE_NAME:
trace(" SQL_DESC_LOCAL_TYPE_NAME TODO");
returnString((SQLCHAR*)CharacterAttributePtr, BufferLength, StringLengthPtr, "DataType");
break;
case SQL_DESC_NAME:
trace(" SQL_DESC_LOCAL_TYPE_NAME");
returnString((SQLCHAR*)CharacterAttributePtr, BufferLength, StringLengthPtr, rec->getColumnName().data());
break;
case SQL_DESC_NULLABLE:
trace(" SQL_DESC_NULLABLE TODO");
returnInt(NumericAttributePtr, SQL_NULLABLE_UNKNOWN);
break;
case SQL_DESC_NUM_PREC_RADIX:
trace(" SQL_DESC_NUM_PREC_RADIX TODO");
returnInt(NumericAttributePtr, 10);
break;
case SQL_DESC_OCTET_LENGTH:
trace(" SQL_DESC_OCTET_LENGTH TODO");
returnInt(NumericAttributePtr, 255);
break;
case SQL_DESC_PRECISION:
trace(" SQL_DESC_PRECISION");
returnInt(NumericAttributePtr, rec->getPrecision());
break;
case SQL_DESC_SCALE:
trace(" SQL_DESC_SCALE");
returnInt(NumericAttributePtr, rec->getScale());
break;
case SQL_DESC_SCHEMA_NAME:
trace(" SQL_DESC_SCHEMA_NAME");
returnString((SQLCHAR*)CharacterAttributePtr, BufferLength, StringLengthPtr, "");
break;
case SQL_DESC_SEARCHABLE:
trace(" SQL_DESC_SEARCHABLE");
returnInt(NumericAttributePtr, SQL_PRED_SEARCHABLE);
break;
case SQL_DESC_TABLE_NAME:
trace(" SQL_DESC_TABLE_NAME");
returnString((SQLCHAR*)CharacterAttributePtr, BufferLength, StringLengthPtr, rec->getTableName().data());
break;
case SQL_DESC_TYPE:
trace(" SQL_DESC_TYPE %d", rec->getSqlDataType());
returnInt(NumericAttributePtr, rec->getSqlDataType());
break;
case SQL_DESC_TYPE_NAME:
trace(" SQL_DESC_TYPE_NAME TODO");
returnString((SQLCHAR*)CharacterAttributePtr, BufferLength, StringLengthPtr, "VARCHAR");
break;
case SQL_DESC_UNNAMED:
trace(" SQL_DESC_UNNAMED TODO");
returnInt(NumericAttributePtr, SQL_NAMED);
break;
case SQL_DESC_UNSIGNED:
trace(" SQL_DESC_UNSIGNED");
returnInt(NumericAttributePtr, SQL_FALSE);
break;
case SQL_DESC_UPDATABLE:
trace(" SQL_DESC_UPDATABLE TODO");
returnInt(NumericAttributePtr, SQL_ATTR_READONLY);
break;
default:
trace(" FieldIdentifier=? %d TODO", FieldIdentifier);
stat->setError(E_HY091);
return SQL_ERROR;
}
return SQL_SUCCESS;
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
*/
#include "h2odbc.h"
SQLRETURN SQL_API SQLSetConnectAttr(SQLHDBC ConnectionHandle,
SQLINTEGER Attribute, SQLPOINTER Value,
SQLINTEGER StringLength) {
trace("SQLSetConnectAttr",(int)Value);
Connection* conn=Connection::cast(ConnectionHandle);
if(conn==0) {
return SQL_INVALID_HANDLE;
}
conn->setError(0);
SQLUINTEGER uint=(SQLUINTEGER)Value;
switch(Attribute) {
case SQL_ATTR_ACCESS_MODE:
trace(" SQL_ATTR_ACCESS_MODE");
if(uint==SQL_MODE_READ_ONLY) {
conn->setReadOnly(true);
}
break;
case SQL_ATTR_ASYNC_ENABLE:
trace(" SQL_ATTR_ASYNC_ENABLE (TODO not supported)");
conn->setError(E_HYC00);
return SQL_ERROR;
break;
case SQL_ATTR_ENABLE_AUTO_IPD:
trace(" SQL_ATTR_AUTO_IPD TODO");
conn->setError(E_HYC00);
return SQL_ERROR;
case SQL_ATTR_AUTO_IPD:
trace(" SQL_ATTR_AUTO_IPD TODO");
conn->setError(E_HYC00);
return SQL_ERROR;
case SQL_ATTR_AUTOCOMMIT:
trace(" SQL_ATTR_AUTOCOMMIT");
if(uint==SQL_AUTOCOMMIT_OFF) {
conn->setAutoCommit(false);
} else if(uint==SQL_AUTOCOMMIT_ON) {
conn->setAutoCommit(true);
}
break;
case SQL_ATTR_CONNECTION_DEAD:
trace(" SQL_ATTR_CONNECTION_DEAD TODO");
// read only
return SQL_ERROR;
case SQL_ATTR_CONNECTION_TIMEOUT:
trace(" SQL_ATTR_CONNECTION_TIMEOUT");
break;
case SQL_ATTR_CURRENT_CATALOG:
trace(" SQL_ATTR_CURRENT_CATALOG TODO");
break;
case SQL_ATTR_LOGIN_TIMEOUT:
trace(" SQL_ATTR_LOGIN_TIMEOUT");
break;
case SQL_ATTR_METADATA_ID:
trace(" SQL_ATTR_METADATA_ID");
break;
case SQL_ATTR_ODBC_CURSORS:
trace(" SQL_ATTR_ODBC_CURSORS");
if((SQLUINTEGER)Value != SQL_CUR_USE_ODBC) {
trace(" not SQL_CUR_USE_ODBC %d", (SQLUINTEGER)Value);
conn->setError(E_01S02);
return SQL_ERROR;
}
break;
case SQL_ATTR_PACKET_SIZE:
trace(" SQL_ATTR_PACKET_SIZE");
break;
case SQL_ATTR_QUIET_MODE:
trace(" SQL_ATTR_QUIET_MODE");
break;
case SQL_ATTR_TRACE:
trace(" SQL_ATTR_TRACE");
break;
case SQL_ATTR_TRACEFILE:
trace(" SQL_ATTR_TRACEFILE");
break;
case SQL_ATTR_TRANSLATE_LIB:
trace(" SQL_ATTR_TRANSLATE_LIB");
break;
case SQL_ATTR_TRANSLATE_OPTION:
trace(" SQL_ATTR_TRANSLATE_OPTION");
break;
case SQL_ATTR_TXN_ISOLATION:
trace(" SQL_ATTR_TXN_ISOLATION");
break;
default:
trace(" ? %d TODO",Attribute);
conn->setError(E_HY092);
return SQL_ERROR;
}
return SQL_SUCCESS;
}
SQLRETURN SQL_API SQLGetConnectAttr(SQLHDBC ConnectionHandle,
SQLINTEGER Attribute, SQLPOINTER Value,
SQLINTEGER BufferLength, SQLINTEGER *StringLength) {
trace("SQLGetConnectAttr");
Connection* conn=Connection::cast(ConnectionHandle);
if(conn==0) {
return SQL_INVALID_HANDLE;
}
conn->setError(0);
switch(Attribute) {
case SQL_ATTR_ACCESS_MODE:
trace(" SQL_ATTR_ACCESS_MODE");
if(conn->getReadOnly()) {
returnInt(Value,StringLength,SQL_MODE_READ_ONLY);
} else {
returnInt(Value,StringLength,SQL_MODE_READ_WRITE);
}
break;
case SQL_ATTR_ASYNC_ENABLE:
trace(" SQL_ATTR_ASYNC_ENABLE");
returnInt(Value, SQL_ASYNC_ENABLE_OFF);
break;
case SQL_ATTR_AUTO_IPD:
trace(" SQL_ATTR_AUTO_IPD");
returnInt(Value, SQL_FALSE);
break;
case SQL_ATTR_AUTOCOMMIT:
trace(" SQL_ATTR_AUTOCOMMIT");
if(conn->getAutoCommit()) {
returnInt(Value,StringLength,SQL_AUTOCOMMIT_ON);
} else {
returnInt(Value,StringLength,SQL_AUTOCOMMIT_OFF);
}
break;
case SQL_ATTR_CONNECTION_DEAD:
trace(" SQL_ATTR_CONNECTION_DEAD");
// TODO: should test if connection is active. now say it's active
returnInt(Value, SQL_CD_FALSE);
break;
case SQL_ATTR_CONNECTION_TIMEOUT:
trace(" SQL_ATTR_CONNECTION_TIMEOUT");
returnInt(Value, 0);
break;
case SQL_ATTR_CURRENT_CATALOG:
trace(" SQL_ATTR_CURRENT_CATALOG (temp:DATA)");
returnString(Value, BufferLength, StringLength, "DATA");
break;
case SQL_ATTR_LOGIN_TIMEOUT:
trace(" SQL_ATTR_LOGIN_TIMEOUT");
returnInt(Value, 0);
break;
case SQL_ATTR_METADATA_ID:
trace(" SQL_ATTR_METADATA_ID");
// TODO: how catalogs are treated. FALSE: catalog can contain patterns (%)
returnInt(Value, SQL_FALSE);
break;
case SQL_ATTR_ODBC_CURSORS:
trace(" SQL_ATTR_ODBC_CURSORS");
returnInt(Value, SQL_CUR_USE_IF_NEEDED);
break;
case SQL_ATTR_PACKET_SIZE:
trace(" SQL_ATTR_PACKET_SIZE");
// TODO should return correct packet size
returnInt(Value, 100);
break;
case SQL_ATTR_QUIET_MODE:
trace(" SQL_ATTR_QUIET_MODE");
// TODO should be a hwnd, 0 means no dialogs, other value means dialogs
returnInt(Value, 0);
break;
case SQL_ATTR_TRACE:
trace(" SQL_ATTR_TRACE");
// TODO should support tracing
returnInt(Value, SQL_OPT_TRACE_OFF);
break;
case SQL_ATTR_TRACEFILE:
trace(" SQL_ATTR_TRACEFILE TODO");
break;
case SQL_ATTR_TRANSLATE_LIB:
trace(" SQL_ATTR_TRANSLATE_LIB TODO");
break;
case SQL_ATTR_TRANSLATE_OPTION:
trace(" SQL_ATTR_TRANSLATE_OPTION TODO");
break;
case SQL_ATTR_TXN_ISOLATION:
trace(" SQL_ATTR_TXN_ISOLATION TODO");
break;
default:
conn->setError(E_HY092);
trace(" ? %d TODO", Attribute);
return SQL_ERROR;
}
conn->setError(0);
return SQL_SUCCESS;
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
*/
#include "h2odbc.h"
SQLRETURN SQL_API SQLGetDiagField(SQLSMALLINT HandleType, SQLHANDLE Handle,
SQLSMALLINT RecNumber, SQLSMALLINT DiagIdentifier,
SQLPOINTER DiagInfo, SQLSMALLINT BufferLength,
SQLSMALLINT* StringLength) {
trace("SQLGetDiagField");
if(RecNumber < 0) {
return SQL_ERROR;
}
if(RecNumber > 1) {
trace(" SQL_NO_DATA");
return SQL_NO_DATA;
}
switch(HandleType) {
case SQL_HANDLE_ENV: {
trace(" SQL_HANDLE_ENV TODO");
Environment* env=Environment::cast(Handle);
if(env==0) {
return SQL_INVALID_HANDLE;
}
return SQL_NO_DATA;
}
case SQL_HANDLE_DBC: {
trace(" SQL_HANDLE_DBC TODO");
Connection* conn=Connection::cast(Handle);
if(conn==0) {
return SQL_INVALID_HANDLE;
}
const char* error = conn->getError();
switch(DiagIdentifier) {
case SQL_DIAG_NUMBER:
trace(" SQL_DIAG_NUMBER %d", (error ? 1 : 0));
returnInt(DiagInfo, error ? 1 : 0);
break;
case SQL_DIAG_MESSAGE_TEXT:
trace(" SQL_DIAG_MESSAGE_TEXT");
if(error==0) {
return SQL_NO_DATA;
}
returnString((SQLCHAR*)DiagInfo, BufferLength, StringLength, error + 6);
break;
case SQL_DIAG_NATIVE:
trace(" SQL_DIAG_NATIVE");
if(error==0) {
return SQL_NO_DATA;
}
returnInt(DiagInfo, 0);
break;
case SQL_DIAG_SERVER_NAME:
trace(" SQL_DIAG_SERVER_NAME %s", conn->getDataSourceName().data());
returnString((SQLCHAR*)DiagInfo, BufferLength, StringLength, conn->getDataSourceName().data());
break;
case SQL_DIAG_SQLSTATE:
trace(" SQL_DIAG_SQLSTATE");
if(error==0) {
return SQL_NO_DATA;
}
returnString((SQLCHAR*)DiagInfo, max((int)BufferLength, 6), StringLength, error);
break;
case SQL_DIAG_SUBCLASS_ORIGIN:
trace(" SQL_DIAG_SUBCLASS_ORIGIN");
if(error==0) {
return SQL_NO_DATA;
}
returnString((SQLCHAR*)DiagInfo, BufferLength, StringLength, "ODBC 3.0");
break;
default:
trace(" ? %d", DiagIdentifier);
return SQL_ERROR;
}
return SQL_SUCCESS;
}
case SQL_HANDLE_STMT: {
trace(" SQL_HANDLE_STMT");
Statement* stat=Statement::cast(Handle);
if(stat==0) {
return SQL_INVALID_HANDLE;
}
char* error = stat->getError();
switch(DiagIdentifier) {
case SQL_DIAG_CURSOR_ROW_COUNT:
trace(" SQL_DIAG_CURSOR_ROW_COUNT");
returnInt(DiagInfo, 1);
break;
case SQL_DIAG_DYNAMIC_FUNCTION:
trace(" SQL_DIAG_DYNAMIC_FUNCTION");
returnString((SQLCHAR*)DiagInfo, BufferLength, StringLength, stat->getSQL());
break;
case SQL_DIAG_DYNAMIC_FUNCTION_CODE:
trace(" SQL_DIAG_DYNAMIC_FUNCTION_CODE");
returnInt(DiagInfo, SQL_DIAG_UNKNOWN_STATEMENT);
break;
case SQL_DIAG_NUMBER:
trace(" SQL_DIAG_NUMBER %d", (error ? 1 : 0));
returnInt(DiagInfo, error ? 1 : 0);
break;
case SQL_DIAG_RETURNCODE:
trace(" SQL_DIAG_RETURNCODE TODO");
break;
case SQL_DIAG_ROW_COUNT:
trace(" SQL_DIAG_ROW_COUNT");
returnInt(DiagInfo, stat->getUpdateCount());
break;
case SQL_DIAG_CLASS_ORIGIN:
trace(" SQL_DIAG_CLASS_ORIGIN TODO");
returnString((SQLCHAR*)DiagInfo, BufferLength, StringLength, "ISO 9075");
break;
case SQL_DIAG_COLUMN_NUMBER:
trace(" SQL_DIAG_COLUMN_NUMBER");
returnInt(DiagInfo, stat->getColumnCount());
break;
case SQL_DIAG_CONNECTION_NAME:
trace(" SQL_DIAG_CONNECTION_NAME");
returnString((SQLCHAR*)DiagInfo, BufferLength, StringLength, "");
break;
case SQL_DIAG_MESSAGE_TEXT:
trace(" SQL_DIAG_MESSAGE_TEXT");
if(error==0) {
return SQL_NO_DATA;
}
returnString((SQLCHAR*)DiagInfo, BufferLength, StringLength, error + 6);
break;
case SQL_DIAG_NATIVE:
trace(" SQL_DIAG_NATIVE");
if(error==0) {
return SQL_NO_DATA;
}
returnInt(DiagInfo, 0);
break;
case SQL_DIAG_ROW_NUMBER:
trace(" SQL_DIAG_ROW_NUMBER");
returnInt(DiagInfo, SQL_ROW_NUMBER_UNKNOWN);
break;
case SQL_DIAG_SERVER_NAME:
trace(" SQL_DIAG_SERVER_NAME");
returnString((SQLCHAR*)DiagInfo, BufferLength, StringLength, "");
break;
case SQL_DIAG_SQLSTATE:
trace(" SQL_DIAG_SQLSTATE");
if(error==0) {
return SQL_NO_DATA;
}
returnString((SQLCHAR*)DiagInfo, max((int)BufferLength, 6), StringLength, error);
break;
case SQL_DIAG_SUBCLASS_ORIGIN:
trace(" SQL_DIAG_SUBCLASS_ORIGIN");
if(error==0) {
return SQL_NO_DATA;
}
returnString((SQLCHAR*)DiagInfo, BufferLength, StringLength, "ODBC 3.0");
break;
default:
trace(" ? %d TODO", DiagIdentifier);
return SQL_ERROR;
}
return SQL_SUCCESS;;
}
case SQL_HANDLE_DESC: {
trace(" SQL_HANDLE_DESC");
Descriptor* desc=Descriptor::cast(Handle);
if(desc==0) {
return SQL_INVALID_HANDLE;
}
desc->setError(0);
return SQL_NO_DATA;
}
default:
trace(" ? %d",HandleType);
return SQL_INVALID_HANDLE;
}
}
SQLRETURN SQL_API SQLGetDiagRec(SQLSMALLINT HandleType, SQLHANDLE Handle,
SQLSMALLINT RecNumber, SQLCHAR *Sqlstate,
SQLINTEGER *NativeError, SQLCHAR *MessageText,
SQLSMALLINT BufferLength, SQLSMALLINT *TextLength) {
trace("SQLGetDiagRec %d",RecNumber);
if(RecNumber < 0) {
return SQL_ERROR;
}
if(RecNumber > 1) {
trace(" SQL_NO_DATA");
return SQL_NO_DATA;
}
if(BufferLength < 0) {
return SQL_ERROR;
}
char* error = 0;
switch(HandleType) {
case SQL_HANDLE_ENV: {
trace(" SQL_HANDLE_ENV");
Environment* env=Environment::cast(Handle);
if(env==0) {
trace(" SQL_INVALID_HANDLE");
return SQL_INVALID_HANDLE;
}
error = env->getError();
break;
}
case SQL_HANDLE_DBC: {
trace(" SQL_HANDLE_DBC");
Connection* conn=Connection::cast(Handle);
if(conn==0) {
trace(" SQL_INVALID_HANDLE");
return SQL_INVALID_HANDLE;
}
error = conn->getError();
break;
}
case SQL_HANDLE_STMT: {
trace(" SQL_HANDLE_STMT");
Statement* stat=Statement::cast(Handle);
if(stat==0) {
trace(" SQL_INVALID_HANDLE");
return SQL_INVALID_HANDLE;
}
error = stat->getError();
break;
}
case SQL_HANDLE_DESC: {
trace(" SQL_HANDLE_DESC");
Descriptor* desc=Descriptor::cast(Handle);
if(desc==0) {
trace(" SQL_INVALID_HANDLE");
return SQL_INVALID_HANDLE;
}
error = desc->getError();
break;
}
default:
trace(" ? %d TODO", HandleType);
return SQL_INVALID_HANDLE;
}
if(error == 0) {
trace(" SQL_NO_DATA");
return SQL_NO_DATA;
} else {
returnString(Sqlstate, 6, 0, error);
returnString(MessageText, BufferLength, TextLength, error + 6);
if(NativeError != 0) {
*NativeError = 0;
}
trace(" SQL_SUCCESS %s", MessageText);
return SQL_SUCCESS;
}
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
*/
#include "h2odbc.h"
SQLRETURN SQL_API SQLGetInfo(SQLHDBC ConnectionHandle,
SQLUSMALLINT InfoType, SQLPOINTER InfoValuePtr,
SQLSMALLINT BufferLength, SQLSMALLINT* StringLengthPtr) {
trace("SQLGetInfo");
Connection* conn;
conn=Connection::cast(ConnectionHandle);
if(conn==0) {
return SQL_INVALID_HANDLE;
}
conn->setError(0);
const char* string=0;
switch(InfoType) {
case SQL_ALTER_TABLE:
trace(" SQL_ALTER_TABLE");
// todo
returnInt(InfoValuePtr, StringLengthPtr, 0);
break;
case SQL_FETCH_DIRECTION:
trace(" SQL_FETCH_DIRECTION");
returnInt(InfoValuePtr, StringLengthPtr, SQL_FD_FETCH_NEXT);
break;
case SQL_ODBC_API_CONFORMANCE:
trace(" SQL_ODBC_API_CONFORMANCE");
returnSmall(InfoValuePtr, StringLengthPtr, SQL_OAC_LEVEL1);
break;
case SQL_LOCK_TYPES:
trace(" SQL_LOCK_TYPES");
returnInt(InfoValuePtr, StringLengthPtr, SQL_LCK_NO_CHANGE);
break;
case SQL_POS_OPERATIONS:
trace(" SQL_POS_OPERATIONS");
returnInt(InfoValuePtr, StringLengthPtr, 0);
break;
case SQL_POSITIONED_STATEMENTS:
trace(" SQL_POSITIONED_STATEMENTS");
returnInt(InfoValuePtr, StringLengthPtr, 0);
break;
case SQL_SCROLL_CONCURRENCY:
trace(" SQL_SCROLL_CONCURRENCY");
returnInt(InfoValuePtr, StringLengthPtr, SQL_SCCO_READ_ONLY);
break;
case SQL_STATIC_SENSITIVITY:
trace(" SQL_STATIC_SENSITIVITY");
returnInt(InfoValuePtr, StringLengthPtr, 0);
break;
case SQL_ACCESSIBLE_PROCEDURES:
trace(" SQL_ACCESSIBLE_PROCEDURES");
string="Y";
break;
case SQL_ACCESSIBLE_TABLES:
trace(" SQL_ACCESSIBLE_TABLES");
string="Y";
break;
case SQL_ACTIVE_ENVIRONMENTS:
trace(" SQL_ACTIVE_ENVIRONMENTS");
returnSmall(InfoValuePtr, StringLengthPtr, 0);
break;
case SQL_AGGREGATE_FUNCTIONS:
trace(" SQL_AGGREGATE_FUNCTIONS");
returnInt(InfoValuePtr, StringLengthPtr, SQL_AF_ALL);
break;
case SQL_ALTER_DOMAIN:
trace(" SQL_ALTER_DOMAIN");
returnInt(InfoValuePtr, StringLengthPtr, 0);
break;
case SQL_ASYNC_MODE:
trace(" SQL_ASYNC_MODE");
returnInt(InfoValuePtr, StringLengthPtr, SQL_AM_NONE);
// todo SQL_AM_STATEMENT
break;
case SQL_BATCH_ROW_COUNT:
trace(" SQL_BATCH_ROW_COUNT");
returnInt(InfoValuePtr, StringLengthPtr, SQL_BRC_EXPLICIT);
break;
case SQL_BATCH_SUPPORT:
trace(" SQL_BATCH_SUPPORT");
returnInt(InfoValuePtr, StringLengthPtr, 0);
// todo
break;
case SQL_BOOKMARK_PERSISTENCE:
trace(" SQL_BOOKMARK_PERSISTENCE");
returnInt(InfoValuePtr, StringLengthPtr, 0);
// todo
break;
case SQL_CATALOG_LOCATION:
trace(" SQL_CATALOG_LOCATION");
returnSmall(InfoValuePtr, StringLengthPtr, SQL_CL_START);
break;
case SQL_CATALOG_NAME:
trace(" SQL_CATALOG_NAME");
string="Y";
break;
case SQL_CATALOG_NAME_SEPARATOR:
trace(" SQL_CATALOG_NAME_SEPARATOR");
string=".";
break;
case SQL_CATALOG_TERM:
trace(" SQL_CATALOG_TERM");
string="catalog";
break;
case SQL_CATALOG_USAGE:
trace(" SQL_CATALOG_USAGE");
returnInt(InfoValuePtr, StringLengthPtr, SQL_CU_DML_STATEMENTS | SQL_CU_PROCEDURE_INVOCATION | SQL_CU_TABLE_DEFINITION | SQL_CU_INDEX_DEFINITION | SQL_CU_PRIVILEGE_DEFINITION);
break;
case SQL_COLLATION_SEQ:
trace(" SQL_COLLATION_SEQ");
string="";
// todo: ISO 8859-1 ?
break;
case SQL_CONCAT_NULL_BEHAVIOR:
trace(" SQL_CONCAT_NULL_BEHAVIOR TODO");
returnSmall(InfoValuePtr, StringLengthPtr, SQL_CB_NULL);
break;
case SQL_CONVERT_BIGINT:
case SQL_CONVERT_BINARY:
case SQL_CONVERT_BIT:
case SQL_CONVERT_CHAR:
case SQL_CONVERT_DATE:
case SQL_CONVERT_DECIMAL:
case SQL_CONVERT_DOUBLE:
case SQL_CONVERT_FLOAT:
case SQL_CONVERT_INTEGER:
case SQL_CONVERT_INTERVAL_YEAR_MONTH:
case SQL_CONVERT_INTERVAL_DAY_TIME:
case SQL_CONVERT_LONGVARBINARY:
case SQL_CONVERT_LONGVARCHAR:
case SQL_CONVERT_NUMERIC:
case SQL_CONVERT_REAL:
case SQL_CONVERT_SMALLINT:
case SQL_CONVERT_TIME:
case SQL_CONVERT_TIMESTAMP:
case SQL_CONVERT_TINYINT:
case SQL_CONVERT_VARBINARY:
case SQL_CONVERT_VARCHAR:
trace(" SQL_CONVERT_ %d", InfoType);
returnInt(InfoValuePtr, StringLengthPtr,
SQL_CVT_BIGINT |
SQL_CVT_BINARY |
SQL_CVT_BIT |
SQL_CVT_CHAR |
SQL_CVT_DATE |
SQL_CVT_DECIMAL |
SQL_CVT_DOUBLE |
SQL_CVT_FLOAT |
SQL_CVT_INTEGER |
SQL_CVT_INTERVAL_YEAR_MONTH |
SQL_CVT_INTERVAL_DAY_TIME |
SQL_CVT_LONGVARBINARY |
SQL_CVT_LONGVARCHAR |
SQL_CVT_NUMERIC |
SQL_CVT_REAL |
SQL_CVT_SMALLINT |
SQL_CVT_TIME |
SQL_CVT_TIMESTAMP |
SQL_CVT_TINYINT |
SQL_CVT_VARBINARY |
SQL_CVT_VARCHAR);
break;
case SQL_CONVERT_FUNCTIONS:
trace(" SQL_CONVERT_FUNCTIONS");
returnInt(InfoValuePtr, StringLengthPtr, SQL_FN_CVT_CAST);
// todo
break;
case SQL_CORRELATION_NAME:
trace(" SQL_CORRELATION_NAME");
returnInt(InfoValuePtr, StringLengthPtr, SQL_CN_ANY);
break;
case SQL_CREATE_ASSERTION:
case SQL_CREATE_CHARACTER_SET:
case SQL_CREATE_COLLATION:
case SQL_CREATE_DOMAIN:
case SQL_CREATE_SCHEMA:
trace(" SQL_CREATE_ %d TODO", InfoType);
returnInt(InfoValuePtr, StringLengthPtr, 0);
break;
case SQL_CREATE_TABLE:
trace(" SQL_CREATE_TABLE TODO");
returnInt(InfoValuePtr, StringLengthPtr, SQL_CT_CREATE_TABLE | SQL_CT_TABLE_CONSTRAINT);
// todo: SQL_CT_CONSTRAINT_NAME_DEFINITION
break;
case SQL_CREATE_TRANSLATION:
trace(" SQL_CREATE_TRANSLATION");
returnInt(InfoValuePtr, StringLengthPtr, 0);
break;
case SQL_CREATE_VIEW:
trace(" SQL_CREATE_VIEW");
returnInt(InfoValuePtr, StringLengthPtr, SQL_CV_CREATE_VIEW | SQL_CV_CHECK_OPTION);
break;
case SQL_CURSOR_COMMIT_BEHAVIOR:
trace(" SQL_CURSOR_COMMIT_BEHAVIOR");
returnSmall(InfoValuePtr, StringLengthPtr, SQL_CB_CLOSE);
break;
case SQL_CURSOR_ROLLBACK_BEHAVIOR:
trace(" SQL_CURSOR_ROLLBACK_BEHAVIOR");
returnSmall(InfoValuePtr, StringLengthPtr, SQL_CB_CLOSE);
break;
case SQL_CURSOR_SENSITIVITY:
trace(" SQL_CURSOR_SENSITIVITY");
returnInt(InfoValuePtr, StringLengthPtr, SQL_UNSPECIFIED);
break;
case SQL_DATA_SOURCE_NAME:
trace(" SQL_DATA_SOURCE_NAME %s", conn->getDataSourceName().data());
string=conn->getDataSourceName().data();
break;
case SQL_DATA_SOURCE_READ_ONLY:
trace(" SQL_DATA_SOURCE_READ_ONLY");
string="N";
// todo
break;
case SQL_DATABASE_NAME:
trace(" SQL_DATABASE_NAME");
string="H2";
// todo
break;
case SQL_DATETIME_LITERALS:
trace(" SQL_DATETIME_LITERALS");
returnInt(InfoValuePtr, StringLengthPtr,
SQL_DL_SQL92_DATE |
SQL_DL_SQL92_TIME |
SQL_DL_SQL92_TIMESTAMP);
// todo
case SQL_DBMS_NAME:
trace(" SQL_DBMS_NAME");
string="h2";
// todo
break;
case SQL_DBMS_VER:
trace(" SQL_DBMS_VER");
string="1.0";
// todo
break;
case SQL_DDL_INDEX:
trace(" SQL_DDL_INDEX");
returnInt(InfoValuePtr, StringLengthPtr, SQL_DI_CREATE_INDEX | SQL_DI_DROP_INDEX);
break;
case SQL_DEFAULT_TXN_ISOLATION:
trace(" SQL_DEFAULT_TXN_ISOLATION");
returnInt(InfoValuePtr, StringLengthPtr, SQL_TXN_READ_COMMITTED);
break;
case SQL_DESCRIBE_PARAMETER:
trace(" SQL_DESCRIBE_PARAMETER");
string="N";
break;
case SQL_DM_VER:
case SQL_DRIVER_HDBC:
case SQL_DRIVER_HENV:
case SQL_DRIVER_HDESC:
case SQL_DRIVER_HLIB:
case SQL_DRIVER_HSTMT:
trace(" SQL_DRIVER_ %d", InfoType);
// implemented by the DriverManager
break;
case SQL_DRIVER_NAME:
trace(" SQL_DRIVER_NAME");
string="h2";
break;
case SQL_DRIVER_ODBC_VER:
trace(" SQL_DRIVER_ODBC_VER");
string="03.00";
break;
case SQL_DRIVER_VER:
trace(" SQL_DRIVER_VER");
string="01.00.0000";
break;
case SQL_DROP_ASSERTION:
case SQL_DROP_CHARACTER_SET:
case SQL_DROP_COLLATION:
case SQL_DROP_DOMAIN:
case SQL_DROP_SCHEMA:
trace(" SQL_DROP_ %d", InfoType);
returnInt(InfoValuePtr, StringLengthPtr, 0);
break;
case SQL_DROP_TABLE:
trace(" SQL_DROP_TABLE");
returnInt(InfoValuePtr, StringLengthPtr, SQL_DT_DROP_TABLE);
break;
case SQL_DROP_TRANSLATION:
case SQL_DROP_VIEW:
trace(" SQL_DROP_ %d", InfoType);
returnInt(InfoValuePtr, StringLengthPtr, 0);
break;
case SQL_DYNAMIC_CURSOR_ATTRIBUTES1:
trace(" SQL_DYNAMIC_CURSOR_ATTRIBUTES1");
returnInt(InfoValuePtr, StringLengthPtr, 0);
//SQL_CA1_NEXT | SQL_CA1_ABSOLUTE | SQL_CA1_RELATIVE;
break;
case SQL_DYNAMIC_CURSOR_ATTRIBUTES2:
trace(" SQL_DYNAMIC_CURSOR_ATTRIBUTES2");
returnInt(InfoValuePtr, StringLengthPtr, 0);
break;
case SQL_EXPRESSIONS_IN_ORDERBY:
trace(" SQL_EXPRESSIONS_IN_ORDERBY");
string="Y";
break;
case SQL_FILE_USAGE:
trace(" SQL_FILE_USAGE");
returnSmall(InfoValuePtr, StringLengthPtr, SQL_FILE_NOT_SUPPORTED);
break;
case SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES1:
trace(" SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES1");
returnInt(InfoValuePtr, StringLengthPtr, SQL_CA1_NEXT);
break;
case SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES2:
trace(" SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES2");
returnInt(InfoValuePtr, StringLengthPtr, SQL_CA2_READ_ONLY_CONCURRENCY);
break;
case SQL_GETDATA_EXTENSIONS:
trace(" SQL_GETDATA_EXTENSIONS");
returnInt(InfoValuePtr, StringLengthPtr, SQL_GD_ANY_COLUMN | SQL_GD_ANY_ORDER);
break;
case SQL_GROUP_BY:
trace(" SQL_GROUP_BY");
returnSmall(InfoValuePtr, StringLengthPtr, SQL_GB_GROUP_BY_EQUALS_SELECT);
break;
case SQL_IDENTIFIER_CASE:
trace(" SQL_IDENTIFIER_CASE");
returnSmall(InfoValuePtr, StringLengthPtr, SQL_IC_UPPER);
break;
case SQL_IDENTIFIER_QUOTE_CHAR:
trace(" SQL_IDENTIFIER_QUOTE_CHAR");
string="\"";
break;
case SQL_INDEX_KEYWORDS:
trace(" SQL_INDEX_KEYWORDS");
returnInt(InfoValuePtr, StringLengthPtr, SQL_IK_NONE);
break;
case SQL_INFO_SCHEMA_VIEWS:
trace(" SQL_INFO_SCHEMA_VIEWS");
returnInt(InfoValuePtr, StringLengthPtr, 0);
break;
case SQL_INSERT_STATEMENT:
trace(" SQL_INSERT_STATEMENT");
returnInt(InfoValuePtr, StringLengthPtr, SQL_IS_INSERT_LITERALS | SQL_IS_INSERT_SEARCHED | SQL_IS_SELECT_INTO);
break;
case SQL_INTEGRITY:
trace(" SQL_INTEGRITY");
string="Y";
break;
case SQL_KEYSET_CURSOR_ATTRIBUTES1:
trace(" SQL_KEYSET_CURSOR_ATTRIBUTES1");
returnInt(InfoValuePtr, StringLengthPtr, SQL_CA1_NEXT);
break;
case SQL_KEYSET_CURSOR_ATTRIBUTES2:
trace(" SQL_KEYSET_CURSOR_ATTRIBUTES2");
returnInt(InfoValuePtr, StringLengthPtr, SQL_CA2_READ_ONLY_CONCURRENCY);
break;
case SQL_KEYWORDS:
trace(" SQL_KEYWORDS");
string=SQL_ODBC_KEYWORDS;
break;
case SQL_LIKE_ESCAPE_CLAUSE:
trace(" SQL_LIKE_ESCAPE_CLAUSE");
string="Y";
break;
case SQL_MAX_ASYNC_CONCURRENT_STATEMENTS:
case SQL_MAX_BINARY_LITERAL_LEN:
case SQL_MAX_CHAR_LITERAL_LEN:
case SQL_MAX_INDEX_SIZE:
case SQL_MAX_ROW_SIZE:
case SQL_MAX_STATEMENT_LEN:
trace(" SQL_MAX_ %d", InfoType);
returnInt(InfoValuePtr, StringLengthPtr, 0);
break;
case SQL_MAX_CATALOG_NAME_LEN:
case SQL_MAX_COLUMN_NAME_LEN:
case SQL_MAX_COLUMNS_IN_GROUP_BY:
case SQL_MAX_COLUMNS_IN_INDEX:
case SQL_MAX_COLUMNS_IN_ORDER_BY:
case SQL_MAX_COLUMNS_IN_SELECT:
case SQL_MAX_COLUMNS_IN_TABLE:
case SQL_MAX_CONCURRENT_ACTIVITIES:
case SQL_MAX_CURSOR_NAME_LEN:
case SQL_MAX_DRIVER_CONNECTIONS:
case SQL_MAX_IDENTIFIER_LEN:
case SQL_MAX_PROCEDURE_NAME_LEN:
case SQL_MAX_SCHEMA_NAME_LEN:
case SQL_MAX_TABLE_NAME_LEN:
case SQL_MAX_TABLES_IN_SELECT:
case SQL_MAX_USER_NAME_LEN:
trace(" SQL_MAX_ %d", InfoType);
returnSmall(InfoValuePtr, StringLengthPtr, 0);
break;
case SQL_MAX_ROW_SIZE_INCLUDES_LONG:
trace(" SQL_MAX_ROW_SIZE_INCLUDES_LONG");
string="Y";
break;
case SQL_MULT_RESULT_SETS:
trace(" SQL_MULT_RESULT_SETS");
string="N";
break;
case SQL_MULTIPLE_ACTIVE_TXN:
trace(" SQL_MULTIPLE_ACTIVE_TXN");
string="Y";
break;
case SQL_NEED_LONG_DATA_LEN:
trace(" SQL_NEED_LONG_DATA_LEN");
string="Y";
break;
case SQL_NON_NULLABLE_COLUMNS:
trace(" SQL_NON_NULLABLE_COLUMNS");
returnSmall(InfoValuePtr, StringLengthPtr, SQL_NNC_NON_NULL);
break;
case SQL_NULL_COLLATION:
trace(" SQL_NULL_COLLATION");
returnSmall(InfoValuePtr, StringLengthPtr, SQL_NC_LOW);
break;
case SQL_NUMERIC_FUNCTIONS:
trace(" SQL_NUMERIC_FUNCTIONS");
returnInt(InfoValuePtr, StringLengthPtr,
SQL_FN_NUM_ABS |
SQL_FN_NUM_ACOS |
SQL_FN_NUM_ASIN |
SQL_FN_NUM_ATAN |
SQL_FN_NUM_ATAN2 |
SQL_FN_NUM_CEILING |
SQL_FN_NUM_COS |
SQL_FN_NUM_COT |
SQL_FN_NUM_DEGREES |
SQL_FN_NUM_EXP |
SQL_FN_NUM_FLOOR |
SQL_FN_NUM_LOG |
SQL_FN_NUM_LOG10 |
SQL_FN_NUM_MOD |
SQL_FN_NUM_PI |
SQL_FN_NUM_POWER |
SQL_FN_NUM_RADIANS |
SQL_FN_NUM_RAND |
SQL_FN_NUM_ROUND |
SQL_FN_NUM_SIGN |
SQL_FN_NUM_SIN |
SQL_FN_NUM_SQRT |
SQL_FN_NUM_TAN |
SQL_FN_NUM_TRUNCATE);
break;
case SQL_ODBC_INTERFACE_CONFORMANCE:
trace(" SQL_ODBC_INTERFACE_CONFORMANCE");
returnInt(InfoValuePtr, StringLengthPtr, SQL_OIC_CORE);
break;
case SQL_ODBC_VER:
trace(" SQL_ODBC_VER");
// Driver Manager only
break;
case SQL_OJ_CAPABILITIES:
trace(" SQL_OJ_CAPABILITIES");
returnInt(InfoValuePtr, StringLengthPtr, SQL_OJ_LEFT | SQL_OJ_RIGHT | SQL_OJ_INNER);
break;
case SQL_ORDER_BY_COLUMNS_IN_SELECT:
trace(" SQL_ORDER_BY_COLUMNS_IN_SELECT");
string="N";
break;
case SQL_PARAM_ARRAY_ROW_COUNTS:
case SQL_PARAM_ARRAY_SELECTS:
trace(" SQL_PARAM_ARRAY_ %d", InfoType);
returnInt(InfoValuePtr, StringLengthPtr, 0);
break;
case SQL_PROCEDURE_TERM:
trace(" SQL_PROCEDURE_TERM");
string="procedure";
break;
case SQL_PROCEDURES:
trace(" SQL_PROCEDURES");
string="Y";
break;
case SQL_QUOTED_IDENTIFIER_CASE:
trace(" SQL_QUOTED_IDENTIFIER_CASE");
returnSmall(InfoValuePtr, StringLengthPtr, SQL_IC_SENSITIVE);
break;
case SQL_ROW_UPDATES:
trace(" SQL_ROW_UPDATES");
string="N";
break;
case SQL_SCHEMA_TERM:
trace(" SQL_SCHEMA_TERM");
string="schema";
break;
case SQL_SCHEMA_USAGE:
trace(" SQL_SCHEMA_USAGE");
returnInt(InfoValuePtr, StringLengthPtr, SQL_SU_DML_STATEMENTS);
break;
case SQL_SCROLL_OPTIONS:
trace(" SQL_SCROLL_OPTIONS");
returnInt(InfoValuePtr, StringLengthPtr, SQL_SO_FORWARD_ONLY);
break;
case SQL_SEARCH_PATTERN_ESCAPE:
trace(" SQL_SEARCH_PATTERN_ESCAPE");
string="\\";
break;
case SQL_SERVER_NAME:
trace(" SQL_SERVER_NAME TODO");
string="h2";
// todo
break;
case SQL_SPECIAL_CHARACTERS:
trace(" SQL_SPECIAL_CHARACTERS");
string="";
break;
case SQL_SQL_CONFORMANCE:
trace(" SQL_SQL_CONFORMANCE");
returnInt(InfoValuePtr, StringLengthPtr, SQL_SC_SQL92_ENTRY);
break;
case SQL_SQL92_DATETIME_FUNCTIONS:
trace(" SQL_SQL92_DATETIME_FUNCTIONS");
returnInt(InfoValuePtr, StringLengthPtr,
SQL_SDF_CURRENT_DATE | SQL_SDF_CURRENT_TIME | SQL_SDF_CURRENT_TIMESTAMP);
break;
case SQL_SQL92_FOREIGN_KEY_DELETE_RULE:
trace(" SQL_SQL92_FOREIGN_KEY_DELETE_RULE");
returnInt(InfoValuePtr, StringLengthPtr, SQL_SFKD_NO_ACTION);
break;
case SQL_SQL92_FOREIGN_KEY_UPDATE_RULE:
trace(" SQL_SQL92_FOREIGN_KEY_UPDATE_RULE");
returnInt(InfoValuePtr, StringLengthPtr, SQL_SFKU_NO_ACTION);
break;
case SQL_SQL92_GRANT:
trace(" SQL_SQL92_GRANT");
returnInt(InfoValuePtr, StringLengthPtr, 0);
break;
case SQL_SQL92_NUMERIC_VALUE_FUNCTIONS:
trace(" SQL_SQL92_NUMERIC_VALUE_FUNCTIONS");
returnInt(InfoValuePtr, StringLengthPtr,
SQL_SNVF_BIT_LENGTH |
SQL_SNVF_CHAR_LENGTH |
SQL_SNVF_CHARACTER_LENGTH |
SQL_SNVF_EXTRACT |
SQL_SNVF_OCTET_LENGTH |
SQL_SNVF_POSITION);
break;
case SQL_SQL92_PREDICATES:
trace(" SQL_SQL92_PREDICATES");
returnInt(InfoValuePtr, StringLengthPtr,
SQL_SP_BETWEEN |
SQL_SP_COMPARISON |
SQL_SP_EXISTS |
SQL_SP_IN |
SQL_SP_ISNOTNULL |
SQL_SP_ISNULL |
SQL_SP_LIKE |
SQL_SP_QUANTIFIED_COMPARISON |
SQL_SP_UNIQUE);
break;
case SQL_SQL92_RELATIONAL_JOIN_OPERATORS:
trace(" SQL_SQL92_RELATIONAL_JOIN_OPERATORS");
returnInt(InfoValuePtr, StringLengthPtr,
SQL_SRJO_INNER_JOIN |
SQL_SRJO_LEFT_OUTER_JOIN |
SQL_SRJO_RIGHT_OUTER_JOIN);
break;
case SQL_SQL92_REVOKE:
trace(" SQL_SQL92_REVOKE");
returnInt(InfoValuePtr, StringLengthPtr, 0);
break;
case SQL_SQL92_ROW_VALUE_CONSTRUCTOR:
trace(" SQL_SQL92_ROW_VALUE_CONSTRUCTOR");
returnInt(InfoValuePtr, StringLengthPtr,
SQL_SRVC_VALUE_EXPRESSION |
SQL_SRVC_NULL |
SQL_SRVC_ROW_SUBQUERY);
break;
case SQL_SQL92_STRING_FUNCTIONS:
trace(" SQL_SQL92_STRING_FUNCTIONS");
returnInt(InfoValuePtr, StringLengthPtr,
SQL_SSF_CONVERT |
SQL_SSF_LOWER |
SQL_SSF_UPPER |
SQL_SSF_SUBSTRING |
SQL_SSF_TRANSLATE |
SQL_SSF_TRIM_BOTH |
SQL_SSF_TRIM_LEADING |
SQL_SSF_TRIM_TRAILING);
break;
case SQL_SQL92_VALUE_EXPRESSIONS:
trace(" SQL_SQL92_VALUE_EXPRESSIONS");
returnInt(InfoValuePtr, StringLengthPtr, 0);
break;
case SQL_STANDARD_CLI_CONFORMANCE:
trace(" SQL_STANDARD_CLI_CONFORMANCE");
returnInt(InfoValuePtr, StringLengthPtr, SQL_SCC_XOPEN_CLI_VERSION1);
break;
case SQL_STATIC_CURSOR_ATTRIBUTES1:
trace(" SQL_STATIC_CURSOR_ATTRIBUTES1");
returnInt(InfoValuePtr, StringLengthPtr,
SQL_CA1_NEXT /* | SQL_CA1_ABSOLUTE | SQL_CA1_RELATIVE */);
break;
case SQL_STATIC_CURSOR_ATTRIBUTES2:
trace(" SQL_STATIC_CURSOR_ATTRIBUTES2");
returnInt(InfoValuePtr, StringLengthPtr, 0);
break;
case SQL_STRING_FUNCTIONS:
trace(" SQL_STRING_FUNCTIONS");
returnInt(InfoValuePtr, StringLengthPtr,
SQL_FN_STR_ASCII |
SQL_FN_STR_BIT_LENGTH |
SQL_FN_STR_CHAR |
SQL_FN_STR_CHAR_LENGTH |
SQL_FN_STR_CHARACTER_LENGTH |
SQL_FN_STR_CONCAT |
SQL_FN_STR_DIFFERENCE |
SQL_FN_STR_INSERT |
SQL_FN_STR_LCASE |
SQL_FN_STR_LEFT |
SQL_FN_STR_LENGTH |
SQL_FN_STR_LOCATE |
SQL_FN_STR_LTRIM |
SQL_FN_STR_OCTET_LENGTH |
SQL_FN_STR_POSITION |
SQL_FN_STR_REPEAT |
SQL_FN_STR_REPLACE |
SQL_FN_STR_RIGHT |
SQL_FN_STR_RTRIM |
SQL_FN_STR_SOUNDEX |
SQL_FN_STR_SPACE |
SQL_FN_STR_SUBSTRING |
SQL_FN_STR_UCASE);
break;
case SQL_SUBQUERIES:
trace(" SQL_SUBQUERIES");
returnInt(InfoValuePtr, StringLengthPtr,
SQL_SQ_CORRELATED_SUBQUERIES |
SQL_SQ_COMPARISON |
SQL_SQ_EXISTS |
SQL_SQ_IN |
SQL_SQ_QUANTIFIED);
break;
case SQL_SYSTEM_FUNCTIONS:
trace(" SQL_SYSTEM_FUNCTIONS");
returnInt(InfoValuePtr, StringLengthPtr,
SQL_FN_SYS_DBNAME |
SQL_FN_SYS_IFNULL |
SQL_FN_SYS_USERNAME);
break;
case SQL_TABLE_TERM:
trace(" SQL_TABLE_TERM");
string="table";
break;
case SQL_TIMEDATE_ADD_INTERVALS:
trace(" SQL_TIMEDATE_ADD_INTERVALS");
returnInt(InfoValuePtr, StringLengthPtr, 0);
break;
case SQL_TIMEDATE_DIFF_INTERVALS:
trace(" SQL_TIMEDATE_DIFF_INTERVALS");
returnInt(InfoValuePtr, StringLengthPtr, 0);
break;
case SQL_TIMEDATE_FUNCTIONS:
trace(" SQL_TIMEDATE_FUNCTIONS");
returnInt(InfoValuePtr, StringLengthPtr,
SQL_FN_TD_CURRENT_DATE |
SQL_FN_TD_CURRENT_TIME |
SQL_FN_TD_CURRENT_TIMESTAMP |
SQL_FN_TD_CURDATE |
SQL_FN_TD_CURTIME);
break;
case SQL_TXN_CAPABLE:
trace(" SQL_TXN_CAPABLE");
returnSmall(InfoValuePtr, StringLengthPtr, SQL_TC_DDL_COMMIT);
break;
case SQL_TXN_ISOLATION_OPTION:
trace(" SQL_TXN_ISOLATION_OPTION");
returnInt(InfoValuePtr, StringLengthPtr,
SQL_TXN_SERIALIZABLE |
SQL_TXN_REPEATABLE_READ |
SQL_TXN_READ_COMMITTED);
break;
case SQL_UNION:
trace(" SQL_UNION");
returnInt(InfoValuePtr, StringLengthPtr, SQL_U_UNION | SQL_U_UNION_ALL);
break;
case SQL_USER_NAME:
trace(" SQL_USER_NAME TODO");
string="sa";
// todo
break;
case SQL_XOPEN_CLI_YEAR:
trace(" SQL_XOPEN_CLI_YEAR");
string="2002";
break;
default:
trace(" ? %d TODO", InfoType);
conn->setError(E_HY096);
return SQL_ERROR;
/*
SQL_ACCESSIBLE_PROCEDURES
SQL_ACCESSIBLE_TABLES
SQL_ACTIVE_ENVIRONMENTS
SQL_AGGREGATE_FUNCTIONS
SQL_ALTER_DOMAIN
SQL_ALTER_TABLE
SQL_ASYNC_MODE
SQL_BATCH_ROW_COUNT
SQL_BATCH_SUPPORT
SQL_BOOKMARK_PERSISTENCE
SQL_CATALOG_LOCATION
SQL_CATALOG_NAME
SQL_CATALOG_NAME_SEPARATOR
SQL_CATALOG_TERM
SQL_CATALOG_USAGE
SQL_COLLATION_SEQ
SQL_COLUMN_ALIAS
SQL_CONCAT_NULL_BEHAVIOR
SQL_CONVERT_BIGINT
SQL_CONVERT_BINARY
SQL_CONVERT_BIT
SQL_CONVERT_CHAR
SQL_CONVERT_DATE
SQL_CONVERT_DECIMAL
SQL_CONVERT_DOUBLE
SQL_CONVERT_FLOAT
SQL_CONVERT_FUNCTIONS
SQL_CONVERT_GUID
SQL_CONVERT_INTEGER
SQL_CONVERT_INTERVAL_DAY_TIME
SQL_CONVERT_INTERVAL_YEAR_MONTH
SQL_CONVERT_LONGVARBINARY
SQL_CONVERT_LONGVARCHAR
SQL_CONVERT_NUMERIC
SQL_CONVERT_REAL
SQL_CONVERT_SMALLINT
SQL_CONVERT_TIME
SQL_CONVERT_TIMESTAMP
SQL_CONVERT_TINYINT
SQL_CONVERT_VARBINARY
SQL_CONVERT_VARCHAR
SQL_CORRELATION_NAME
SQL_CREATE_ASSERTION
SQL_CREATE_CHARACTER_SET
SQL_CREATE_COLLATION
SQL_CREATE_DOMAIN
SQL_CREATE_SCHEMA
SQL_CREATE_TABLE
SQL_CREATE_TRANSLATION
SQL_CREATE_VIEW
SQL_CURSOR_COMMIT_BEHAVIOR
SQL_CURSOR_ROLLBACK_BEHAVIOR
SQL_CURSOR_ROLLBACK_SQL_CURSOR_SENSITIVITY
SQL_DATA_SOURCE_NAME
SQL_DATA_SOURCE_READ_ONLY
SQL_DATABASE_NAME
SQL_DATETIME_LITERALS
SQL_DBMS_NAME
SQL_DBMS_VER
SQL_DDL_INDEX
SQL_DEFAULT_TXN_ISOLATION
SQL_DESCRIBE_PARAMETER
SQL_DM_VER
SQL_DRIVER_HDBC
SQL_DRIVER_HDESC
SQL_DRIVER_HENV
SQL_DRIVER_HLIB
SQL_DRIVER_HSTMT
SQL_DRIVER_NAME
SQL_DRIVER_ODBC_VER
SQL_DRIVER_VER
SQL_DROP_ASSERTION
SQL_DROP_CHARACTER_SET
SQL_DROP_COLLATION
SQL_DROP_DOMAIN
SQL_DROP_SCHEMA
SQL_DROP_TABLE
SQL_DROP_TRANSLATION
SQL_DROP_VIEW
SQL_DYNAMIC_CURSOR_ATTRIBUTES1
SQL_DYNAMIC_CURSOR_ATTRIBUTES2
SQL_EXPRESSIONS_IN_ORDERBY
SQL_FILE_USAGE
SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES1
SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES2
SQL_GETDATA_EXTENSIONS
SQL_GROUP_BY
SQL_IDENTIFIER_CASE
SQL_IDENTIFIER_QUOTE_CHAR
SQL_INDEX_KEYWORDS
SQL_INFO_SCHEMA_VIEWS
SQL_INSERT_STATEMENT
SQL_INTEGRITY
SQL_KEYSET_CURSOR_ATTRIBUTES1
SQL_KEYSET_CURSOR_ATTRIBUTES2
SQL_KEYWORDS
SQL_LIKE_ESCAPE_CLAUSE
SQL_MAX_ASYNC_CONCURRENT_STATEMENTS
SQL_MAX_BINARY_LITERAL_LEN
SQL_MAX_CATALOG_NAME_LEN
SQL_MAX_CHAR_LITERAL_LEN
SQL_MAX_COLUMN_NAME_LEN
SQL_MAX_COLUMNS_IN_GROUP_BY
SQL_MAX_COLUMNS_IN_INDEX
SQL_MAX_COLUMNS_IN_ORDER_BY
SQL_MAX_COLUMNS_IN_SELECT
SQL_MAX_COLUMNS_IN_TABLE
SQL_MAX_CONCURRENT_ACTIVITIES
SQL_MAX_CURSOR_NAME_LEN
SQL_MAX_DRIVER_CONNECTIONS
SQL_MAX_IDENTIFIER_LEN
SQL_MAX_INDEX_SIZE
SQL_MAX_PROCEDURE_NAME_LEN
SQL_MAX_ROW_SIZE
SQL_MAX_ROW_SIZE_INCLUDES_LONG
SQL_MAX_SCHEMA_NAME_LEN
SQL_MAX_STATEMENT_LEN
SQL_MAX_TABLE_NAME_LEN
SQL_MAX_TABLES_IN_SELECT
SQL_MAX_USER_NAME_LEN
SQL_MULT_RESULT_SETS
SQL_MULTIPLE_ACTIVE_TXN
SQL_NEED_LONG_DATA_LEN
SQL_NON_NULLABLE_COLUMNS
SQL_NULL_COLLATION
SQL_NUMERIC_FUNCTIONS
SQL_ODBC_INTERFACE_CONFORMANCE
SQL_ODBC_VER
SQL_OJ_CAPABILITIES
SQL_ORDER_BY_COLUMNS_IN_SELECT
SQL_PARAM_ARRAY_ROW_COUNTS
SQL_PARAM_ARRAY_SELECTS
SQL_POS_OPERATIONS
SQL_PROCEDURE_TERM
SQL_PROCEDURES
SQL_QUOTED_IDENTIFIER_CASE
SQL_ROW_UPDATES
SQL_SCHEMA_TERM
SQL_SCHEMA_USAGE
SQL_SCROLL_OPTIONS
SQL_SEARCH_PATTERN_ESCAPE
SQL_SERVER_NAME
SQL_SPECIAL_CHARACTERS
SQL_SQL_CONFORMANCE
SQL_SQL92_DATETIME_FUNCTIONS
SQL_SQL92_FOREIGN_KEY_DELETE_RULE
SQL_SQL92_FOREIGN_KEY_UPDATE_RULE
SQL_SQL92_GRANT
SQL_SQL92_NUMERIC_InfoValuePtr_FUNCTIONS
SQL_SQL92_PREDICATES
SQL_SQL92_RELATIONAL_JOIN_OPERATORS
SQL_SQL92_REVOKE
SQL_SQL92_ROW_InfoValuePtr_CONSTRUCTOR
SQL_SQL92_STRING_FUNCTIONS
SQL_SQL92_InfoValuePtr_EXPRESSIONS
SQL_STANDARD_CLI_CONFORMANCE
SQL_STATIC_CURSOR_ATTRIBUTES1
SQL_STATIC_CURSOR_ATTRIBUTES2
SQL_STRING_FUNCTIONS
SQL_SUBQUERIES
SQL_SYSTEM_FUNCTIONS
SQL_TABLE_TERM
SQL_TIMEDATE_ADD_INTERVALS
SQL_TIMEDATE_DIFF_INTERVALS
SQL_TIMEDATE_FUNCTIONS
SQL_TXN_CAPABLE
SQL_TXN_ISOLATION_OPTION
SQL_UNION
SQL_USER_NAME
SQL_XOPEN_CLI_YEAR
*/
}
if(string!=0) {
trace(" =%s", string);
returnString((SQLCHAR*)InfoValuePtr, BufferLength, StringLengthPtr, string);
}
return SQL_SUCCESS;
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
*/
#include "h2odbc.h"
SQLRETURN SQL_API SQLGetStmtAttr(SQLHSTMT StatementHandle,
SQLINTEGER Attribute, SQLPOINTER Value,
SQLINTEGER BufferLength, SQLINTEGER* StringLength) {
trace("SQLGetStmtAttr");
Statement* stat=Statement::cast(StatementHandle);
if(stat==0) {
return SQL_INVALID_HANDLE;
}
stat->setError(0);
switch(Attribute) {
case SQL_ATTR_APP_ROW_DESC:
trace(" SQL_ATTR_APP_ROW_DESC");
returnPointer(Value,stat->getAppRowDesc());
break;
case SQL_ATTR_APP_PARAM_DESC:
trace(" SQL_ATTR_APP_PARAM_DESC");
returnPointer(Value,stat->getAppParamDesc());
break;
case SQL_ATTR_IMP_ROW_DESC:
trace(" SQL_ATTR_IMP_ROW_DESC");
returnPointer(Value,stat->getImpRowDesc());
break;
case SQL_ATTR_IMP_PARAM_DESC:
trace(" SQL_ATTR_IMP_PARAM_DESC");
returnPointer(Value,stat->getImpParamDesc());
break;
case SQL_ATTR_QUERY_TIMEOUT:
trace(" SQL_ATTR_QUERY_TIMEOUT");
returnInt(Value,StringLength,0);
break;
case SQL_ATTR_ASYNC_ENABLE:
trace(" SQL_ATTR_ASYNC_ENABLE TODO");
break;
case SQL_ATTR_CONCURRENCY:
trace(" SQL_ATTR_CONCURRENCY");
returnInt(Value, SQL_CONCUR_READ_ONLY);
break;
case SQL_ATTR_CURSOR_SCROLLABLE:
trace(" SQL_ATTR_CURSOR_SCROLLABLE TODO");
break;
case SQL_ATTR_CURSOR_SENSITIVITY:
trace(" SQL_ATTR_CURSOR_SENSITIVITY");
returnInt(Value, SQL_INSENSITIVE);
break;
case SQL_ATTR_CURSOR_TYPE:
trace(" SQL_ATTR_CURSOR_TYPE");
returnInt(Value, SQL_CURSOR_FORWARD_ONLY);
break;
case SQL_ATTR_ENABLE_AUTO_IPD:
trace(" SQL_ATTR_ENABLE_AUTO_IPD TODO");
break;
case SQL_ATTR_FETCH_BOOKMARK_PTR:
trace(" SQL_ATTR_FETCH_BOOKMARK_PTR TODO");
break;
case SQL_ATTR_KEYSET_SIZE:
trace(" SQL_ATTR_KEYSET_SIZE TODO");
break;
case SQL_ATTR_MAX_LENGTH:
trace(" SQL_ATTR_MAX_LENGTH TODO");
break;
case SQL_ATTR_MAX_ROWS:
trace(" SQL_ATTR_MAX_ROWS TODO");
break;
case SQL_ATTR_METADATA_ID:
trace(" SQL_ATTR_METADATA_ID TODO");
break;
case SQL_ATTR_NOSCAN:
trace(" SQL_ATTR_NOSCAN TODO");
break;
case SQL_ATTR_PARAM_BIND_OFFSET_PTR:
trace(" SQL_ATTR_PARAM_BIND_OFFSET_PTR TODO");
break;
case SQL_ATTR_PARAM_BIND_TYPE:
trace(" SQL_ATTR_PARAM_BIND_TYPE TODO");
break;
case SQL_ATTR_PARAM_OPERATION_PTR:
trace(" SQL_ATTR_PARAM_OPERATION_PTR TODO");
break;
case SQL_ATTR_PARAM_STATUS_PTR:
trace(" SQL_ATTR_PARAM_STATUS_PTR TODO");
break;
case SQL_ATTR_PARAMS_PROCESSED_PTR:
trace(" SQL_ATTR_PARAMS_PROCESSED_PTR TODO");
break;
case SQL_ATTR_PARAMSET_SIZE:
trace(" SQL_ATTR_PARAMSET_SIZE TODO");
break;
case SQL_ATTR_RETRIEVE_DATA:
trace(" SQL_ATTR_RETRIEVE_DATA TODO");
break;
case SQL_ATTR_ROW_ARRAY_SIZE:
trace(" SQL_ATTR_ROW_ARRAY_SIZE TODO");
break;
case SQL_ATTR_ROW_BIND_OFFSET_PTR:
trace(" SQL_ATTR_ROW_BIND_OFFSET_PTR TODO");
break;
case SQL_ATTR_ROW_BIND_TYPE:
trace(" SQL_ATTR_ROW_BIND_TYPE TODO");
break;
case SQL_ATTR_ROW_NUMBER: {
trace(" SQL_ATTR_ROW_NUMBER");
returnInt(Value, stat->getRowId());
break;
}
case SQL_ATTR_ROW_OPERATION_PTR:
trace(" SQL_ATTR_ROW_OPERATION_PTR TODO");
break;
case SQL_ATTR_ROW_STATUS_PTR:
trace(" SQL_ATTR_ROW_STATUS_PTR");
returnInt(Value, (int)stat->getAppRowDesc()->getStatusPointer());
break;
case SQL_ATTR_ROWS_FETCHED_PTR:
trace(" SQL_ATTR_ROWS_FETCHED_PTR TODO");
break;
case SQL_ATTR_SIMULATE_CURSOR:
trace(" SQL_ATTR_SIMULATE_CURSOR TODO");
break;
case SQL_ATTR_USE_BOOKMARKS:
trace(" SQL_ATTR_USE_BOOKMARKS");
returnInt(Value, stat->getUseBookmarks() ? SQL_UB_VARIABLE : SQL_UB_OFF);
break;
default:
trace(" ? %d TODO",(int)Attribute);
return SQL_ERROR;
}
return SQL_SUCCESS;
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
*/
#include "h2odbc.h"
SQLRETURN SQL_API SQLColumns(SQLHSTMT StatementHandle,
SQLCHAR* CatalogName, SQLSMALLINT NameLength1,
SQLCHAR* SchemaName, SQLSMALLINT NameLength2,
SQLCHAR* TableName, SQLSMALLINT NameLength3,
SQLCHAR* ColumnName, SQLSMALLINT NameLength4) {
trace("SQLColumns");
Statement* stat=Statement::cast(StatementHandle);
if(stat==0) {
return SQL_INVALID_HANDLE;
}
stat->setError(0);
char catalog[512];
setString(catalog,sizeof(catalog),CatalogName,NameLength1);
char schema[512];
setString(schema,sizeof(schema),SchemaName,NameLength2);
char table[512];
setString(table,sizeof(table),TableName,NameLength3);
char column[512];
setString(column,sizeof(column),ColumnName,NameLength4);
trace(" catalog=%s schema=%s table=%s column=%s",catalog,schema,table,column);
stat->getMetaColumns(catalog, schema, table, column);
return SQL_SUCCESS;
}
SQLRETURN SQL_API SQLSpecialColumns(SQLHSTMT StatementHandle,
SQLUSMALLINT IdentifierType, SQLCHAR* CatalogName,
SQLSMALLINT NameLength1, SQLCHAR* SchemaName,
SQLSMALLINT NameLength2, SQLCHAR* TableName,
SQLSMALLINT NameLength3, SQLUSMALLINT Scope,
SQLUSMALLINT Nullable) {
trace("SQLSpecialColumns");
Statement* stat=Statement::cast(StatementHandle);
if(stat==0) {
return SQL_INVALID_HANDLE;
}
stat->setError(0);
char catalog[512];
setString(catalog,sizeof(catalog),CatalogName,NameLength1);
char schema[512];
setString(schema,sizeof(schema),SchemaName,NameLength2);
char table[512];
setString(table,sizeof(table),TableName,NameLength3);
switch(IdentifierType) {
case SQL_BEST_ROWID: {
trace(" SQL_BEST_ROWID");
bool nullable = Nullable == SQL_NULLABLE;
stat->getMetaBestRowIdentifier(catalog, schema, table, Scope, nullable);
break;
}
case SQL_ROWVER: {
trace(" SQL_ROWVER");
stat->getMetaVersionColumns(catalog, schema, table);
break;
}
default:
stat->setError(E_HY097);
return SQL_ERROR;
}
return SQL_SUCCESS;
}
SQLRETURN SQL_API SQLStatistics(SQLHSTMT StatementHandle,
SQLCHAR* CatalogName, SQLSMALLINT NameLength1,
SQLCHAR* SchemaName, SQLSMALLINT NameLength2,
SQLCHAR* TableName, SQLSMALLINT NameLength3,
SQLUSMALLINT Unique, SQLUSMALLINT Reserved) {
trace("SQLStatistics");
Statement* stat=Statement::cast(StatementHandle);
if(stat==0) {
return SQL_INVALID_HANDLE;
}
stat->setError(0);
char catalog[512];
setString(catalog,sizeof(catalog),CatalogName,NameLength1);
char schema[512];
setString(schema,sizeof(schema),SchemaName,NameLength2);
char table[512];
setString(table,sizeof(table),TableName,NameLength3);
bool unique = Unique == SQL_INDEX_UNIQUE;
bool approximate = Reserved == SQL_QUICK;
stat->getMetaIndexInfo(catalog, schema, table, unique, approximate);
return SQL_SUCCESS;
}
SQLRETURN SQL_API SQLTables(SQLHSTMT StatementHandle,
SQLCHAR* CatalogName, SQLSMALLINT NameLength1,
SQLCHAR* SchemaName, SQLSMALLINT NameLength2,
SQLCHAR* TableName, SQLSMALLINT NameLength3,
SQLCHAR* TableType, SQLSMALLINT NameLength4) {
trace("SQLTables");
Statement* stat=Statement::cast(StatementHandle);
if(stat==0) {
return SQL_INVALID_HANDLE;
}
stat->setError(0);
char catalog[512];
setString(catalog,sizeof(catalog),CatalogName,NameLength1);
char schema[512];
setString(schema,sizeof(schema),SchemaName,NameLength2);
char table[512];
setString(table,sizeof(table),TableName,NameLength3);
char tabletypes[512];
setString(tabletypes,sizeof(tabletypes),TableType,NameLength4);
trace(" catalog=%s schema=%s table=%s tabletypes=%s",catalog, schema, table, tabletypes);
stat->getMetaTables(catalog, schema, table, tabletypes);
return SQL_SUCCESS;
}
SQLRETURN SQL_API SQLGetTypeInfo(SQLHSTMT StatementHandle,
SQLSMALLINT DataType) {
trace("SQLGetTypeInfo");
Statement* stat=Statement::cast(StatementHandle);
if(stat==0) {
return SQL_INVALID_HANDLE;
}
stat->setError(0);
switch(DataType) {
case SQL_ALL_TYPES:
trace(" SQL_ALL_TYPES");
stat->getMetaTypeInfoAll();
break;
/*
case SQL_CHAR:
trace(" SQL_CHAR");
break;
case SQL_VARCHAR:
trace(" SQL_VARCHAR");
break;
case SQL_LONGVARCHAR:
trace(" SQL_LONGVARCHAR");
break;
case SQL_WCHAR:
trace(" SQL_WCHAR");
break;
case SQL_WVARCHAR:
trace(" SQL_WVARCHAR");
break;
case SQL_WLONGVARCHAR:
trace(" SQL_WLONGVARCHAR");
break;
case SQL_DECIMAL:
trace(" SQL_DECIMAL");
break;
case SQL_NUMERIC:
trace(" SQL_NUMERIC");
break;
case SQL_INTEGER:
trace(" SQL_INTEGER");
break;
case SQL_BINARY:
trace(" SQL_BINARY");
break;
case SQL_SMALLINT:
trace(" SQL_SMALLINT");
break;
case SQL_REAL:
trace(" SQL_REAL");
break;
case SQL_FLOAT:
trace(" SQL_FLOAT");
break;
case SQL_DOUBLE:
trace(" SQL_DOUBLE");
break;
case SQL_BIT:
trace(" SQL_BIT");
break;
case SQL_TINYINT:
trace(" SQL_TINYINT");
break;
case SQL_BIGINT:
trace(" SQL_BIGINT");
break;
case SQL_VARBINARY:
trace(" SQL_VARBINARY");
break;
case SQL_LONGVARBINARY:
trace(" SQL_LONGVARBINARY");
break;
case SQL_TYPE_DATE:
trace(" SQL_TYPE_DATE");
break;
case SQL_TYPE_TIME:
trace(" SQL_TYPE_TIME");
break;
case SQL_TYPE_TIMESTAMP:
trace(" SQL_TYPE_TIMESTAMP");
break;
case SQL_INTERVAL_MONTH:
case SQL_INTERVAL_YEAR:
case SQL_INTERVAL_YEAR_TO_MONTH:
case SQL_INTERVAL_DAY:
case SQL_INTERVAL_HOUR:
case SQL_INTERVAL_MINUTE:
case SQL_INTERVAL_SECOND:
case SQL_INTERVAL_DAY_TO_HOUR:
case SQL_INTERVAL_DAY_TO_MINUTE:
case SQL_INTERVAL_DAY_TO_SECOND:
case SQL_INTERVAL_HOUR_TO_MINUTE:
case SQL_INTERVAL_HOUR_TO_SECOND:
case SQL_INTERVAL_MINUTE_TO_SECOND:
trace(" SQL_INTERVAL_ %d",DataType);
break;
case SQL_GUID:
trace(" SQL_GUID");
break;
*/
default:
trace(" type=%d", DataType);
stat->getMetaTypeInfo(DataType);
break;
}
return SQL_SUCCESS;
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
*/
#include "h2odbc.h"
SQLRETURN SQL_API SQLSetStmtAttr(SQLHSTMT StatementHandle,
SQLINTEGER Attribute, SQLPOINTER Value,
SQLINTEGER StringLength) {
trace("SQLSetStmtAttr");
Statement* stat=Statement::cast(StatementHandle);
if(stat==0) {
return SQL_INVALID_HANDLE;
}
stat->setError(0);
switch(Attribute) {
case SQL_ATTR_APP_PARAM_DESC:
trace(" SQL_ATTR_APP_ROW_DESC TODO");
// todo
return SQL_ERROR;
case SQL_ATTR_APP_ROW_DESC:
trace(" SQL_ATTR_APP_ROW_DESC TODO");
// todo
return SQL_ERROR;
case SQL_ATTR_ASYNC_ENABLE:
trace(" SQL_ATTR_ASYNC_ENABLE TODO not supported");
// TODO should support that!
if((SQLUINTEGER)Value != SQL_ASYNC_ENABLE_OFF) {
stat->setError(E_01S02);
return SQL_SUCCESS_WITH_INFO;
}
break;
case SQL_ATTR_CONCURRENCY: {
trace(" SQL_ATTR_CONCURRENCY");
// option value can be changed
SQLUINTEGER type = (SQLUINTEGER)Value;
switch(type) {
case SQL_CONCUR_READ_ONLY:
trace(" SQL_CONCUR_READ_ONLY");
break;
case SQL_CONCUR_LOCK:
trace(" SQL_CONCUR_LOCK");
stat->setError(E_01S02);
return SQL_SUCCESS_WITH_INFO;
break;
case SQL_CONCUR_ROWVER:
trace(" SQL_CONCUR_ROWVER");
stat->setError(E_01S02);
return SQL_SUCCESS_WITH_INFO;
break;
case SQL_CONCUR_VALUES:
trace(" SQL_CONCUR_ROWVER");
stat->setError(E_01S02);
return SQL_SUCCESS_WITH_INFO;
break;
default:
trace(" =? %d TODO", type);
return SQL_ERROR;
}
break;
}
case SQL_ATTR_CURSOR_SCROLLABLE:
trace(" SQL_ATTR_CURSOR_SCROLLABLE TODO");
break;
case SQL_ATTR_CURSOR_SENSITIVITY: {
trace(" SQL_ATTR_CURSOR_SENSITIVITY TODO");
// it seems this must be supported!
SQLUINTEGER type = (SQLUINTEGER)Value;
switch(type) {
case SQL_UNSPECIFIED:
trace(" SQL_UNSPECIFIED");
break;
case SQL_INSENSITIVE:
trace(" SQL_INSENSITIVE");
stat->setError(E_01S02);
return SQL_SUCCESS_WITH_INFO;
break;
case SQL_SENSITIVE:
trace(" SQL_SENSITIVE");
stat->setError(E_01S02);
return SQL_SUCCESS_WITH_INFO;
break;
default:
trace(" =? %d TODO", type);
return SQL_ERROR;
}
break;
}
case SQL_ATTR_CURSOR_TYPE: {
trace(" SQL_ATTR_CURSOR_TYPE");
// option value can be changed
SQLUINTEGER type = (SQLUINTEGER)Value;
switch(type) {
case SQL_CURSOR_FORWARD_ONLY:
trace(" SQL_CURSOR_FORWARD_ONLY");
break;
case SQL_CURSOR_STATIC:
trace(" SQL_CURSOR_STATIC");
stat->setError(E_01S02);
return SQL_SUCCESS_WITH_INFO;
break;
case SQL_CURSOR_KEYSET_DRIVEN:
trace(" SQL_CURSOR_KEYSET_DRIVEN");
stat->setError(E_01S02);
return SQL_SUCCESS_WITH_INFO;
break;
case SQL_CURSOR_DYNAMIC:
trace(" SQL_CURSOR_DYNAMIC");
stat->setError(E_01S02);
return SQL_SUCCESS_WITH_INFO;
break;
default:
trace(" =? %d TODO", type);
return SQL_ERROR;
}
break;
}
case SQL_ATTR_IMP_PARAM_DESC:
trace(" SQL_ATTR_IMP_PARAM_DESC TODO");
return SQL_ERROR;
case SQL_ATTR_ROW_NUMBER:
trace(" SQL_ATTR_ROW_NUMBER TODO");
return SQL_ERROR;
case SQL_ATTR_IMP_ROW_DESC:
trace(" SQL_ATTR_IMP_ROW_DESC TODO");
return SQL_ERROR;
case SQL_ATTR_QUERY_TIMEOUT:
trace(" SQL_ATTR_QUERY_TIMEOUT");
// option value can be changed
if((SQLUINTEGER)Value != 0) {
stat->setError(E_01S02);
return SQL_SUCCESS_WITH_INFO;
}
break;
case SQL_ATTR_ENABLE_AUTO_IPD:
trace(" SQL_ATTR_ENABLE_AUTO_IPD TODO");
break;
case SQL_ATTR_FETCH_BOOKMARK_PTR:
trace(" SQL_ATTR_FETCH_BOOKMARK_PTR TODO");
break;
case SQL_ATTR_KEYSET_SIZE:
trace(" SQL_ATTR_KEYSET_SIZE");
// option value can be changed
if((SQLUINTEGER)Value != 0) {
stat->setError(E_01S02);
return SQL_SUCCESS_WITH_INFO;
}
break;
case SQL_ATTR_MAX_LENGTH:
trace(" SQL_ATTR_MAX_LENGTH %d", Value);
// option value can be changed
if((SQLUINTEGER)Value != 0) {
stat->setError(E_01S02);
return SQL_SUCCESS_WITH_INFO;
}
break;
case SQL_ATTR_MAX_ROWS:
trace(" SQL_ATTR_MAX_ROWS");
// option value can be changed
if((SQLUINTEGER)Value != 0) {
stat->setError(E_01S02);
return SQL_SUCCESS_WITH_INFO;
}
break;
case SQL_ATTR_METADATA_ID:
trace(" SQL_ATTR_METADATA_ID TODO");
break;
case SQL_ATTR_NOSCAN:
trace(" SQL_ATTR_NOSCAN TODO");
break;
case SQL_ATTR_PARAM_BIND_OFFSET_PTR:
trace(" SQL_ATTR_PARAM_BIND_OFFSET_PTR TODO");
break;
case SQL_ATTR_PARAM_BIND_TYPE:
trace(" SQL_ATTR_PARAM_BIND_TYPE TODO");
break;
case SQL_ATTR_PARAM_OPERATION_PTR:
trace(" SQL_ATTR_PARAM_OPERATION_PTR TODO");
break;
case SQL_ATTR_PARAM_STATUS_PTR:
trace(" SQL_ATTR_PARAM_STATUS_PTR TODO");
break;
case SQL_ATTR_PARAMS_PROCESSED_PTR:
trace(" SQL_ATTR_PARAMS_PROCESSED_PTR TODO");
break;
case SQL_ATTR_PARAMSET_SIZE:
trace(" SQL_ATTR_PARAMSET_SIZE TODO");
// TODO it seems all drivers must support arrays, but the MySQL driver doesn't support it
if((SQLUINTEGER)Value != 1) {
stat->setError(E_01S02);
return SQL_SUCCESS_WITH_INFO;
}
break;
case SQL_ATTR_RETRIEVE_DATA:
trace(" SQL_ATTR_RETRIEVE_DATA TODO");
break;
case SQL_ATTR_ROW_ARRAY_SIZE:
trace(" SQL_ATTR_ROW_ARRAY_SIZE");
// option value can be changed
if((SQLUINTEGER)Value != 1) {
stat->setError(E_01S02);
return SQL_SUCCESS_WITH_INFO;
}
break;
case SQL_ATTR_ROW_BIND_OFFSET_PTR:
trace(" SQL_ATTR_ROW_BIND_OFFSET_PTR TODO");
break;
case SQL_ATTR_ROW_BIND_TYPE:
trace(" SQL_ATTR_ROW_BIND_TYPE TODO");
if(Value == SQL_BIND_BY_COLUMN) {
// column wise binding
// SQL_BIND_BY_COLUMN = 0UL
trace(" SQL_BIND_BY_COLUMN TODO");
stat->getAppRowDesc()->setBindingType(false, 0);
} else {
// row wise binding
trace(" row wise binding size=%d", Value);
stat->getAppRowDesc()->setBindingType(true, (int)Value);
}
break;
case SQL_ATTR_ROW_OPERATION_PTR:
trace(" SQL_ATTR_ROW_OPERATION_PTR TODO");
break;
case SQL_ATTR_ROW_STATUS_PTR:
trace(" SQL_ATTR_ROW_STATUS_PTR");
stat->getAppRowDesc()->setStatusPointer((SQLUSMALLINT*)Value);
break;
case SQL_ATTR_ROWS_FETCHED_PTR:
trace(" SQL_ATTR_ROWS_FETCHED_PTR");
stat->getImpRowDesc()->setRowsProcessedPointer((SQLUINTEGER*)Value);
break;
case SQL_ATTR_SIMULATE_CURSOR: {
trace(" SQL_ATTR_SIMULATE_CURSOR");
// option value can be changed
if((SQLUINTEGER)Value != SQL_SC_NON_UNIQUE) {
stat->setError(E_01S02);
return SQL_SUCCESS_WITH_INFO;
}
break;
}
case SQL_ATTR_USE_BOOKMARKS: {
trace(" SQL_ATTR_USE_BOOKMARKS");
switch((int)Value) {
case SQL_UB_OFF:
trace(" SQL_UB_OFF");
stat->setUseBookmarks(false);
break;
case SQL_UB_FIXED:
trace(" SQL_UB_FIXED TODO");
break;
case SQL_UB_VARIABLE:
trace(" SQL_UB_VARIABLE");
stat->setUseBookmarks(true);
break;
default:
trace(" ? %d TODO", Value);
}
break;
}
default:
trace(" ? %d TODO",Attribute);
break;
}
return SQL_SUCCESS;
}
/*
* Copyright 2004-2006 H2 Group. Licensed under the H2 License, Version 1.0 (http://h2database.com/html/license.html).
*/
#include "h2odbc.h"
void setString(char* dest, int dest_len, SQLCHAR* source, SQLSMALLINT source_len) {
if(dest==0 || dest_len==0) {
return;
}
if(source==0) {
*dest=0;
return;
}
int len;
if(source_len==SQL_NTS) {
len=strlen((char*)source);
} else {
len=(int)source_len;
}
if(dest_len<len) {
len=dest_len;
}
strncpy(dest, (char*)source, len);
dest[len]=0;
}
void returnString(SQLPOINTER dest, SQLINTEGER dest_len, SQLINTEGER* dest_pt, const char* source) {
if(dest_len==0) {
return;
}
char* s = (char*)source;
if(source==0) {
s="";
}
int len=strlen(s);
if(dest_len<len) {
len=dest_len;
}
if(dest_pt!=0) {
*dest_pt=len;
}
if(dest!=0) {
strncpy((char*)dest, s, len);
((char*)dest)[len]=0;
}
}
void returnString(SQLCHAR* dest, SQLSMALLINT dest_len, SQLSMALLINT* dest_pt, const char* source) {
if(dest_len==0) {
return;
}
char* s = (char*)source;
if(source==0) {
s="";
}
int len=strlen(s);
if(dest_len<len) {
len=dest_len;
}
if(dest_pt!=0) {
*dest_pt=len;
}
if(dest!=0) {
strncpy((char*)dest, s, len);
dest[len]=0;
}
}
void returnInt(SQLPOINTER InfoValue, SQLINTEGER* LengthPtr, SQLUINTEGER value) {
if(LengthPtr!=0) {
*LengthPtr=sizeof(SQLUINTEGER);
}
*((SQLUINTEGER*)InfoValue)=value;
}
void returnInt(SQLPOINTER NumericPtr, int value) {
if(NumericPtr != 0) {
*(SQLUINTEGER*)NumericPtr = value;
}
}
void returnInt(SQLSMALLINT* pointer, int value) {
if(pointer != 0) {
*pointer = value;
}
}
void returnInt(SQLPOINTER InfoValue, SQLSMALLINT* LengthPtr, SQLUINTEGER value) {
if(LengthPtr!=0) {
*LengthPtr=sizeof(SQLUINTEGER);
}
*((SQLUINTEGER*)InfoValue)=value;
}
void returnSmall(SQLPOINTER InfoValue, SQLINTEGER* LengthPtr, SQLUSMALLINT value) {
if(LengthPtr!=0) {
*LengthPtr=sizeof(SQLUSMALLINT);
}
*((SQLSMALLINT*)InfoValue)=value;
}
void returnSmall(SQLPOINTER InfoValue, SQLSMALLINT* LengthPtr, SQLUSMALLINT value) {
if(LengthPtr!=0) {
*LengthPtr=sizeof(SQLUSMALLINT);
}
*((SQLSMALLINT*)InfoValue)=value;
}
void returnPointer(SQLPOINTER pointer, void* value) {
if(pointer==0) {
return;
}
(*(void**)pointer)=value;
}
int getDefaultCType(int sqlType) {
switch (sqlType) {
case SQL_CHAR:
case SQL_VARCHAR:
case SQL_LONGVARCHAR:
case SQL_DECIMAL:
case SQL_NUMERIC:
case SQL_GUID:
return SQL_C_CHAR;
case SQL_WCHAR:
case SQL_WVARCHAR:
case SQL_WLONGVARCHAR:
return SQL_C_WCHAR;
case SQL_BIT:
return SQL_C_BIT;
case SQL_TINYINT:
return SQL_C_TINYINT;
case SQL_SMALLINT:
return SQL_C_SHORT;
case SQL_INTEGER:
return SQL_C_LONG;
case SQL_BIGINT:
return SQL_C_SBIGINT;
case SQL_REAL:
return SQL_C_FLOAT;
case SQL_FLOAT:
case SQL_DOUBLE:
return SQL_C_DOUBLE;
case SQL_BINARY:
case SQL_VARBINARY:
case SQL_LONGVARBINARY:
return SQL_C_BINARY;
case SQL_TYPE_DATE:
return SQL_C_DATE;
case SQL_TYPE_TIME:
return SQL_C_TIME;
case SQL_TYPE_TIMESTAMP:
return SQL_C_TIMESTAMP;
default:
trace(" unsupported translation from sqlType %d TODO", sqlType);
return SQL_C_CHAR;
}
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论