1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
/*
* 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"