advantage 0.1.0-x86-linux → 0.1.1-x86-linux
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +0 -0
- data/README +0 -0
- data/Rakefile +0 -0
- data/ext/Makefile +25 -21
- data/ext/ace.h +6 -1
- data/ext/adscapidll.c +0 -0
- data/ext/adscapidll.h +0 -0
- data/ext/adscapidll.o +0 -0
- data/ext/advantage.c +926 -882
- data/ext/advantage.o +0 -0
- data/ext/advantage.so +0 -0
- data/ext/dbcapi.cpp +1780 -0
- data/ext/dbcapi.h +0 -0
- data/ext/dbcapi.o +0 -0
- data/ext/extconf.rb +0 -0
- data/lib/advantage.so +0 -0
- data/test/advantage_test.rb +0 -0
- data/test/test.sql +0 -0
- metadata +11 -9
data/ext/advantage.o
CHANGED
Binary file
|
data/ext/advantage.so
CHANGED
Binary file
|
data/ext/dbcapi.cpp
ADDED
@@ -0,0 +1,1780 @@
|
|
1
|
+
/*******************************************************************************
|
2
|
+
* Source File : DBCAPI.CPP
|
3
|
+
* Copyright : 2010 Sybase, an SAP company
|
4
|
+
* Description : This contains all entry points to implement the DBCAPI interface
|
5
|
+
* for many clients such as Python, PHP, Ruby, etc.
|
6
|
+
* Notes :
|
7
|
+
*
|
8
|
+
* The purpose of this module is to implement a thin layer between our ACE client
|
9
|
+
* and Sybase's DBCAPI clients. Bascially DBCAPI is a standard API shared between
|
10
|
+
* SQL Anywhere and Adaptive Server Enterprise for use with common thin clients.
|
11
|
+
* By implementing the same API in ACE we can consume those same thin clients
|
12
|
+
* and support many more development environments.
|
13
|
+
*******************************************************************************/
|
14
|
+
|
15
|
+
// This functionality is only used on the client side (in ACE)
|
16
|
+
#ifdef ACE
|
17
|
+
|
18
|
+
#include "adsinc.h"
|
19
|
+
#include <ctype.h>
|
20
|
+
#include "ace.h"
|
21
|
+
#include "acetypes.h"
|
22
|
+
#include "aceclass.h"
|
23
|
+
#include "adsutil.h"
|
24
|
+
#include "cconnect.h"
|
25
|
+
|
26
|
+
#define ACE_ADSVERSION // to get the ACE version string from adsver.h
|
27
|
+
#include "adsver.h"
|
28
|
+
|
29
|
+
#include "dbcapi.h"
|
30
|
+
|
31
|
+
#ifdef _DEBUG
|
32
|
+
#define DBCLogTrace(x)
|
33
|
+
//#define DBCLogTrace(x) printf( "%s\n", x )
|
34
|
+
#else
|
35
|
+
#define DBCLogTrace(x)
|
36
|
+
#endif
|
37
|
+
|
38
|
+
#define DBCAPI_SUCCESS 1 // General success
|
39
|
+
#define DBCAPI_FAILURE 0 // General failure
|
40
|
+
#define DBCAPI_NEGONE (UNSIGNED32)-1 // Failure when returning a length
|
41
|
+
|
42
|
+
|
43
|
+
/*******************************************************************************
|
44
|
+
* Module : ConvertACEtoNativeType
|
45
|
+
* Created : 11-04-2010 Peter F
|
46
|
+
* Last Mod :
|
47
|
+
* Return Value : a_ads_native_type
|
48
|
+
* Desc : Convert an ACE type to a native DBCAPI type
|
49
|
+
* Notes :
|
50
|
+
*******************************************************************************/
|
51
|
+
a_ads_native_type ConvertACEtoNativeType( UNSIGNED16 usACEType )
|
52
|
+
{
|
53
|
+
switch ( usACEType )
|
54
|
+
{
|
55
|
+
case ADS_LOGICAL:
|
56
|
+
return DT_BIT;
|
57
|
+
case ADS_NUMERIC:
|
58
|
+
return DT_DECIMAL;
|
59
|
+
case ADS_DATE:
|
60
|
+
return DT_DATE;
|
61
|
+
case ADS_STRING:
|
62
|
+
return DT_STRING;
|
63
|
+
case ADS_MEMO:
|
64
|
+
return DT_LONGVARCHAR;
|
65
|
+
case ADS_BINARY:
|
66
|
+
return DT_BINARY;
|
67
|
+
case ADS_IMAGE:
|
68
|
+
return DT_BINARY;
|
69
|
+
case ADS_VARCHAR:
|
70
|
+
return DT_VARCHAR;
|
71
|
+
case ADS_COMPACTDATE:
|
72
|
+
return DT_DATE;
|
73
|
+
case ADS_DOUBLE:
|
74
|
+
return DT_DOUBLE;
|
75
|
+
case ADS_INTEGER:
|
76
|
+
return DT_INT;
|
77
|
+
case ADS_SHORTINT:
|
78
|
+
return DT_SMALLINT;
|
79
|
+
case ADS_TIME:
|
80
|
+
return DT_TIME;
|
81
|
+
case ADS_TIMESTAMP:
|
82
|
+
return DT_TIMESTAMP;
|
83
|
+
case ADS_AUTOINC:
|
84
|
+
return DT_INT;
|
85
|
+
case ADS_RAW:
|
86
|
+
return DT_BINARY;
|
87
|
+
case ADS_CURDOUBLE:
|
88
|
+
return DT_DOUBLE;
|
89
|
+
case ADS_MONEY:
|
90
|
+
return DT_BIGINT;
|
91
|
+
case ADS_LONGLONG:
|
92
|
+
return DT_BIGINT;
|
93
|
+
case ADS_CISTRING:
|
94
|
+
return DT_STRING;
|
95
|
+
case ADS_ROWVERSION:
|
96
|
+
return DT_BIGINT;
|
97
|
+
case ADS_MODTIME:
|
98
|
+
return DT_TIMESTAMP;
|
99
|
+
case ADS_VARCHAR_FOX:
|
100
|
+
return DT_VARCHAR;
|
101
|
+
case ADS_VARBINARY_FOX:
|
102
|
+
return DT_BINARY;
|
103
|
+
case ADS_SYSTEM_FIELD:
|
104
|
+
return DT_NOTYPE;
|
105
|
+
case ADS_NCHAR:
|
106
|
+
return DT_NSTRING;
|
107
|
+
case ADS_NVARCHAR:
|
108
|
+
return DT_NSTRING;
|
109
|
+
case ADS_NMEMO:
|
110
|
+
return DT_LONGNVARCHAR;
|
111
|
+
|
112
|
+
default:
|
113
|
+
ASSERT( 0 );
|
114
|
+
return DT_NOTYPE;
|
115
|
+
}
|
116
|
+
|
117
|
+
} /* ConvertACEtoNativeType */
|
118
|
+
|
119
|
+
|
120
|
+
/*******************************************************************************
|
121
|
+
* Module : ConvertACEToIOType
|
122
|
+
* Created : 11-04-2010 Peter F
|
123
|
+
* Last Mod :
|
124
|
+
* Return Value : a_ads_data_type
|
125
|
+
* Desc : Convert an ACE type to a DBCAPI IO type
|
126
|
+
* Notes :
|
127
|
+
*******************************************************************************/
|
128
|
+
a_ads_data_type ConvertACEToIOType( UNSIGNED16 usACEType )
|
129
|
+
{
|
130
|
+
switch ( usACEType )
|
131
|
+
{
|
132
|
+
case ADS_LOGICAL:
|
133
|
+
return A_UVAL8;
|
134
|
+
case ADS_NUMERIC:
|
135
|
+
return A_DECIMAL;
|
136
|
+
case ADS_DATE:
|
137
|
+
return A_DATE;
|
138
|
+
case ADS_STRING:
|
139
|
+
return A_STRING;
|
140
|
+
case ADS_MEMO:
|
141
|
+
return A_STRING;
|
142
|
+
case ADS_BINARY:
|
143
|
+
return A_BINARY;
|
144
|
+
case ADS_IMAGE:
|
145
|
+
return A_BINARY;
|
146
|
+
case ADS_VARCHAR:
|
147
|
+
return A_STRING;
|
148
|
+
case ADS_COMPACTDATE:
|
149
|
+
return A_DATE;
|
150
|
+
case ADS_DOUBLE:
|
151
|
+
return A_DOUBLE;
|
152
|
+
case ADS_INTEGER:
|
153
|
+
return A_VAL32;
|
154
|
+
case ADS_SHORTINT:
|
155
|
+
return A_VAL16;
|
156
|
+
case ADS_TIME:
|
157
|
+
return A_TIME;
|
158
|
+
case ADS_TIMESTAMP:
|
159
|
+
return A_TIMESTAMP;
|
160
|
+
case ADS_AUTOINC:
|
161
|
+
return A_UVAL32;
|
162
|
+
case ADS_RAW:
|
163
|
+
return A_BINARY;
|
164
|
+
case ADS_CURDOUBLE:
|
165
|
+
return A_DOUBLE;
|
166
|
+
case ADS_MONEY:
|
167
|
+
return A_VAL64;
|
168
|
+
case ADS_LONGLONG:
|
169
|
+
return A_VAL64;
|
170
|
+
case ADS_CISTRING:
|
171
|
+
return A_STRING;
|
172
|
+
case ADS_ROWVERSION:
|
173
|
+
return A_UVAL64;
|
174
|
+
case ADS_MODTIME:
|
175
|
+
return A_TIMESTAMP;
|
176
|
+
case ADS_VARCHAR_FOX:
|
177
|
+
return A_STRING;
|
178
|
+
case ADS_VARBINARY_FOX:
|
179
|
+
return A_BINARY;
|
180
|
+
case ADS_SYSTEM_FIELD:
|
181
|
+
return A_INVALID_TYPE;
|
182
|
+
case ADS_NCHAR:
|
183
|
+
return A_NCHAR;
|
184
|
+
case ADS_NVARCHAR:
|
185
|
+
return A_NCHAR;
|
186
|
+
case ADS_NMEMO:
|
187
|
+
return A_NCHAR;
|
188
|
+
|
189
|
+
default:
|
190
|
+
ASSERT( 0 );
|
191
|
+
return A_INVALID_TYPE;
|
192
|
+
}
|
193
|
+
|
194
|
+
} /* ConvertACEToIOType */
|
195
|
+
|
196
|
+
|
197
|
+
/*******************************************************************************
|
198
|
+
* Module : ads_affected_rows
|
199
|
+
* Created : 11-04-2010 Peter F
|
200
|
+
* Last Mod :
|
201
|
+
* Return Value : Number of rows affected
|
202
|
+
* Desc : Return the number of rows affected by a query
|
203
|
+
* Notes :
|
204
|
+
*******************************************************************************/
|
205
|
+
UNSIGNED32 ENTRYPOINT ads_affected_rows( ADSHANDLE hStatement )
|
206
|
+
{
|
207
|
+
UNSIGNED32 ulRows;
|
208
|
+
UNSIGNED32 ulRetCode;
|
209
|
+
|
210
|
+
DBCLogTrace( "ads_affected_rows" );
|
211
|
+
|
212
|
+
// Returns rows affected for statement handles
|
213
|
+
ulRetCode = AdsGetRecordCount( hStatement, ADS_IGNOREFILTERS, &ulRows );
|
214
|
+
if ( ulRetCode == AE_SUCCESS )
|
215
|
+
return ulRows;
|
216
|
+
else
|
217
|
+
return DBCAPI_FAILURE;
|
218
|
+
|
219
|
+
} /* ads_affected_rows */
|
220
|
+
|
221
|
+
|
222
|
+
/*******************************************************************************
|
223
|
+
* Module : ads_bind_param
|
224
|
+
* Created : 11-04-2010 Peter F
|
225
|
+
* Last Mod :
|
226
|
+
* Return Value : SUCCESS or FAILURE
|
227
|
+
* Desc : Bind a user-supplied buffer as a parameter to the prepared statement.
|
228
|
+
* Notes :
|
229
|
+
*******************************************************************************/
|
230
|
+
UNSIGNED32 ENTRYPOINT ads_bind_param( ADSHANDLE hStatement, UNSIGNED32 ulIndex, a_ads_bind_param *param )
|
231
|
+
{
|
232
|
+
UNSIGNED32 ulRetCode;
|
233
|
+
|
234
|
+
DBCLogTrace( "ads_bind_param" );
|
235
|
+
|
236
|
+
if ( param == NULL )
|
237
|
+
return DBCAPI_FAILURE;
|
238
|
+
|
239
|
+
if ( param->value.buffer == NULL )
|
240
|
+
return DBCAPI_FAILURE;
|
241
|
+
|
242
|
+
if ( param->value.length == NULL )
|
243
|
+
return DBCAPI_FAILURE;
|
244
|
+
|
245
|
+
// If the parameter value is NULL, set it to empty in ACE
|
246
|
+
if ( param->value.is_null && *param->value.is_null )
|
247
|
+
{
|
248
|
+
if ( AdsSetEmpty( hStatement, ADSFIELD(ulIndex+1)) == AE_SUCCESS )
|
249
|
+
return DBCAPI_SUCCESS;
|
250
|
+
else
|
251
|
+
return DBCAPI_FAILURE;
|
252
|
+
}
|
253
|
+
|
254
|
+
switch ( param->value.type )
|
255
|
+
{
|
256
|
+
case A_VAL32:
|
257
|
+
case A_UVAL32:
|
258
|
+
ulRetCode = AdsSetLong( hStatement, ADSFIELD(ulIndex+1), *((SIGNED32*)(param->value.buffer)) );
|
259
|
+
break;
|
260
|
+
|
261
|
+
case A_STRING:
|
262
|
+
ulRetCode = AdsSetString( hStatement, ADSFIELD(ulIndex+1), param->value.buffer, *(param->value.length) );
|
263
|
+
break;
|
264
|
+
|
265
|
+
case A_BINARY:
|
266
|
+
ulRetCode = AdsSetBinary( hStatement, ADSFIELD(ulIndex+1), ADS_BINARY, *(param->value.length),
|
267
|
+
0, param->value.buffer, *(param->value.length) );
|
268
|
+
break;
|
269
|
+
|
270
|
+
case A_DOUBLE:
|
271
|
+
ulRetCode = AdsSetDouble( hStatement, ADSFIELD(ulIndex+1), *((double*)(param->value.buffer)));
|
272
|
+
break;
|
273
|
+
|
274
|
+
case A_VAL64:
|
275
|
+
case A_UVAL64:
|
276
|
+
ulRetCode = AdsSetLongLong( hStatement, ADSFIELD(ulIndex+1), *((SIGNED64*)(param->value.buffer)));
|
277
|
+
break;
|
278
|
+
|
279
|
+
case A_VAL16:
|
280
|
+
case A_UVAL16:
|
281
|
+
ulRetCode = AdsSetShort( hStatement, ADSFIELD(ulIndex+1), *((SIGNED16*)(param->value.buffer)));
|
282
|
+
break;
|
283
|
+
|
284
|
+
case A_VAL8:
|
285
|
+
case A_UVAL8:
|
286
|
+
ulRetCode = AdsSetLogical( hStatement, ADSFIELD(ulIndex+1), *((SIGNED8*)(param->value.buffer)));
|
287
|
+
break;
|
288
|
+
|
289
|
+
case A_NCHAR:
|
290
|
+
{
|
291
|
+
// Unicode buffer lengths are always in bytes, but AdsSetStringW needs it in chars (UTF-16)
|
292
|
+
UNSIGNED32 ulChars = (*(param->value.length) >> 1) - 2; // -2 for the BOM
|
293
|
+
ulRetCode = AdsSetStringW( hStatement, ADSFIELD(ulIndex+1),
|
294
|
+
(WCHAR*)(param->value.buffer) + 1, // skip the BOM
|
295
|
+
ulChars );
|
296
|
+
}
|
297
|
+
break;
|
298
|
+
|
299
|
+
default:
|
300
|
+
ulRetCode = AdsSetLastError( AE_INVALID_DATA_TYPE, "Unsupported parameter data type." );
|
301
|
+
break;
|
302
|
+
}
|
303
|
+
|
304
|
+
if ( ulRetCode == AE_SUCCESS )
|
305
|
+
return DBCAPI_SUCCESS;
|
306
|
+
else
|
307
|
+
return DBCAPI_FAILURE;
|
308
|
+
|
309
|
+
} /* ads_bind_param */
|
310
|
+
|
311
|
+
|
312
|
+
/*******************************************************************************
|
313
|
+
* Module : DBCAPICallback
|
314
|
+
* Created : 11-04-2010 Peter F
|
315
|
+
* Last Mod :
|
316
|
+
* Return Value : 1 to cancel the operation, 0 to keep it going
|
317
|
+
* Desc : Callback funtion to support query cancel
|
318
|
+
* Notes : This is a 64 bit FN and must be registered with AdsRegisterCallbackFunction101
|
319
|
+
*******************************************************************************/
|
320
|
+
UNSIGNED32 WINAPI DBCAPICallback( UNSIGNED16 usPercentDone, SIGNED64 qCallbackID )
|
321
|
+
{
|
322
|
+
UNSIGNED32 ulCancel = 0;
|
323
|
+
|
324
|
+
#ifdef x64
|
325
|
+
if ( AdsSetProperty90( (ADSHANDLE)qCallbackID, ADS_DBCAPI_CANCEL, (UNSIGNED64)&ulCancel ) == AE_SUCCESS )
|
326
|
+
#else
|
327
|
+
if ( AdsSetProperty( (ADSHANDLE)qCallbackID, ADS_DBCAPI_CANCEL, (UNSIGNED32)&ulCancel ) == AE_SUCCESS )
|
328
|
+
#endif
|
329
|
+
return ulCancel;
|
330
|
+
|
331
|
+
return 0;
|
332
|
+
|
333
|
+
} /* ShowPercentage */
|
334
|
+
|
335
|
+
|
336
|
+
/*******************************************************************************
|
337
|
+
* Module : ads_cancel
|
338
|
+
* Created : 11-04-2010 Peter F
|
339
|
+
* Last Mod :
|
340
|
+
* Return Value :
|
341
|
+
* Desc : Cancel a query
|
342
|
+
* Notes :
|
343
|
+
*******************************************************************************/
|
344
|
+
void ENTRYPOINT ads_cancel( a_ads_connection *poConnect )
|
345
|
+
{
|
346
|
+
UNSIGNED32 ulCancel = TRUE;
|
347
|
+
|
348
|
+
DBCLogTrace( "ads_cancel" );
|
349
|
+
|
350
|
+
// Set the cancel flag on the connection and the next time the callback
|
351
|
+
// function gets called with this connection, it will abort the query.
|
352
|
+
// Not using AdsSetProperty here since we already have the connection sync and
|
353
|
+
// calling an API would block.
|
354
|
+
if ( poConnect && poConnect->hConnect && ValidConnectionHandle( poConnect->hConnect ))
|
355
|
+
((CCONNECTION*)poConnect->hConnect)->GetDBCAPICancel( &ulCancel );
|
356
|
+
|
357
|
+
} /* ads_cancel */
|
358
|
+
|
359
|
+
|
360
|
+
/*******************************************************************************
|
361
|
+
* Module : ads_clear_error
|
362
|
+
* Created : 11-04-2010 Peter F
|
363
|
+
* Last Mod :
|
364
|
+
* Return Value :
|
365
|
+
* Desc : Clear the current/last error
|
366
|
+
* Notes :
|
367
|
+
*******************************************************************************/
|
368
|
+
void ENTRYPOINT ads_clear_error( a_ads_connection *poConnect )
|
369
|
+
{
|
370
|
+
DBCLogTrace( "ads_clear_error" );
|
371
|
+
AdsClearLastError();
|
372
|
+
|
373
|
+
} /* ads_clear_error */
|
374
|
+
|
375
|
+
|
376
|
+
/*******************************************************************************
|
377
|
+
* Module : ads_client_version
|
378
|
+
* Created : 11-04-2010 Peter F
|
379
|
+
* Last Mod :
|
380
|
+
* Return Value :
|
381
|
+
* Desc : Return the client version
|
382
|
+
* Notes :
|
383
|
+
*******************************************************************************/
|
384
|
+
UNSIGNED32 ENTRYPOINT ads_client_version( UNSIGNED8 *pucBuffer, UNSIGNED32 ulLength )
|
385
|
+
{
|
386
|
+
DBCLogTrace( "ads_client_version" );
|
387
|
+
if ( pucBuffer && ulLength )
|
388
|
+
{
|
389
|
+
AXSTRNCPY( (SIGNED8*)pucBuffer, pcIdAxsVer + 9, ulLength );
|
390
|
+
*(pucBuffer + ulLength - 1) = 0x00; // ensure NULL terminator
|
391
|
+
return DBCAPI_SUCCESS;
|
392
|
+
}
|
393
|
+
|
394
|
+
return DBCAPI_FAILURE;
|
395
|
+
|
396
|
+
} /* ads_client_version */
|
397
|
+
|
398
|
+
|
399
|
+
/*******************************************************************************
|
400
|
+
* Module : ads_commit
|
401
|
+
* Created : 11-04-2010 Peter F
|
402
|
+
* Last Mod :
|
403
|
+
* Return Value :
|
404
|
+
* Desc : Commit the current transaction
|
405
|
+
* Notes :
|
406
|
+
*******************************************************************************/
|
407
|
+
UNSIGNED32 ENTRYPOINT ads_commit( a_ads_connection *poConnect )
|
408
|
+
{
|
409
|
+
DBCLogTrace( "ads_commit" );
|
410
|
+
|
411
|
+
if ( poConnect == NULL )
|
412
|
+
return DBCAPI_FAILURE;
|
413
|
+
|
414
|
+
if ( AdsCommitTransaction( poConnect->hConnect ) == AE_SUCCESS )
|
415
|
+
return DBCAPI_SUCCESS;
|
416
|
+
else
|
417
|
+
return DBCAPI_FAILURE;
|
418
|
+
|
419
|
+
} /* ads_commit */
|
420
|
+
|
421
|
+
|
422
|
+
/*******************************************************************************
|
423
|
+
* Module : ads_connect
|
424
|
+
* Created : 11-04-2010 Peter F
|
425
|
+
* Last Mod :
|
426
|
+
* Return Value :
|
427
|
+
* Desc : Connect to Advantage
|
428
|
+
* Notes :
|
429
|
+
*******************************************************************************/
|
430
|
+
UNSIGNED32 ENTRYPOINT ads_connect( a_ads_connection *poConnect, UNSIGNED8 *pucConnectString )
|
431
|
+
{
|
432
|
+
DBCLogTrace( "ads_connect" );
|
433
|
+
|
434
|
+
if ( poConnect == NULL )
|
435
|
+
return DBCAPI_FAILURE;
|
436
|
+
|
437
|
+
if ( AdsConnect101( pucConnectString, NULL, &(poConnect->hConnect) ) == AE_SUCCESS )
|
438
|
+
return DBCAPI_SUCCESS;
|
439
|
+
else
|
440
|
+
return DBCAPI_FAILURE;
|
441
|
+
|
442
|
+
} /* ads_connect */
|
443
|
+
|
444
|
+
|
445
|
+
/*******************************************************************************
|
446
|
+
* Module : ads_describe_bind_param
|
447
|
+
* Created : 11-04-2010 Peter F
|
448
|
+
* Last Mod :
|
449
|
+
* Return Value :
|
450
|
+
* Desc : Describe a parameter
|
451
|
+
* Notes : Not fully functional...
|
452
|
+
*******************************************************************************/
|
453
|
+
UNSIGNED32 ENTRYPOINT ads_describe_bind_param( ADSHANDLE hStatement, UNSIGNED32 ulIndex, a_ads_bind_param *param )
|
454
|
+
{
|
455
|
+
DBCLogTrace( "ads_describe_bind_param" );
|
456
|
+
|
457
|
+
// Since ACE doesn't know anything about the type of parameters in a prepared
|
458
|
+
// statement, we can't tell the type of a parameter. All we know is that
|
459
|
+
// it must be an INPUT parameter since we don't support OUTPUT (or INPUT_OUTPUT) ones.
|
460
|
+
// If in the future ACE becomes aware of parameters (like our ODBC client), we can update
|
461
|
+
// this function to do what it is supposed to. The effect of this is that the caller must
|
462
|
+
// set the data type themselves.
|
463
|
+
if ( hStatement == 0 )
|
464
|
+
return DBCAPI_FAILURE;
|
465
|
+
|
466
|
+
if ( param == NULL )
|
467
|
+
return DBCAPI_FAILURE;
|
468
|
+
|
469
|
+
// All parameters must be INPUT for ADS
|
470
|
+
param->direction = DD_INPUT;
|
471
|
+
|
472
|
+
return DBCAPI_SUCCESS;
|
473
|
+
|
474
|
+
} /* ads_describe_bind_param */
|
475
|
+
|
476
|
+
|
477
|
+
/*******************************************************************************
|
478
|
+
* Module : ads_disconnect
|
479
|
+
* Created : 11-04-2010 Peter F
|
480
|
+
* Last Mod :
|
481
|
+
* Return Value :
|
482
|
+
* Desc : Disconnect from Advantage
|
483
|
+
* Notes :
|
484
|
+
*******************************************************************************/
|
485
|
+
UNSIGNED32 ENTRYPOINT ads_disconnect( a_ads_connection *poConnect )
|
486
|
+
{
|
487
|
+
UNSIGNED32 ulRetCode;
|
488
|
+
|
489
|
+
DBCLogTrace( "ads_disconnect" );
|
490
|
+
|
491
|
+
if ( poConnect == NULL )
|
492
|
+
return DBCAPI_FAILURE;
|
493
|
+
|
494
|
+
ulRetCode = AdsDisconnect( poConnect->hConnect );
|
495
|
+
poConnect->hConnect = 0;
|
496
|
+
|
497
|
+
if ( ulRetCode == AE_SUCCESS )
|
498
|
+
return DBCAPI_SUCCESS;
|
499
|
+
else
|
500
|
+
return DBCAPI_FAILURE;
|
501
|
+
|
502
|
+
} /* ads_disconnect */
|
503
|
+
|
504
|
+
|
505
|
+
/*******************************************************************************
|
506
|
+
* Module : ads_error
|
507
|
+
* Created : 11-04-2010 Peter F
|
508
|
+
* Last Mod :
|
509
|
+
* Return Value :
|
510
|
+
* Desc : Get the last (current) error
|
511
|
+
* Notes :
|
512
|
+
*******************************************************************************/
|
513
|
+
UNSIGNED32 ENTRYPOINT ads_error( a_ads_connection *poConnect, UNSIGNED8 *pucError, UNSIGNED32 ulLength )
|
514
|
+
{
|
515
|
+
UNSIGNED32 ulError;
|
516
|
+
UNSIGNED16 usLen = (UNSIGNED16)ulLength;
|
517
|
+
|
518
|
+
DBCLogTrace( "ads_error" );
|
519
|
+
|
520
|
+
AdsGetLastError( &ulError, pucError, &usLen );
|
521
|
+
if ( pucError && ulLength )
|
522
|
+
*(pucError + ulLength - 1) = 0x00;
|
523
|
+
|
524
|
+
return ulError;
|
525
|
+
|
526
|
+
} /* ads_error */
|
527
|
+
|
528
|
+
|
529
|
+
/*******************************************************************************
|
530
|
+
* Module : SetupCursorBuffer
|
531
|
+
* Created : 11-04-2010 Peter F
|
532
|
+
* Last Mod :
|
533
|
+
* Return Value :
|
534
|
+
* Desc : Allocate a record buffer structure to hold values as they are fetched
|
535
|
+
* Notes :
|
536
|
+
*******************************************************************************/
|
537
|
+
UNSIGNED32 SetupCursorBuffer( ADSHANDLE hCursor )
|
538
|
+
{
|
539
|
+
UNSIGNED32 ulAllocationSize;
|
540
|
+
UNSIGNED8 *pucFieldData;
|
541
|
+
DBCAPI_COLUMN *pstFieldStruct;
|
542
|
+
UNSIGNED16 usIndex;
|
543
|
+
UNSIGNED16 usFieldCount;
|
544
|
+
UNSIGNED16 usFieldType;
|
545
|
+
UNSIGNED32 ulFieldLength;
|
546
|
+
UNSIGNED32 ulRetCode;
|
547
|
+
UNSIGNED16 usLen;
|
548
|
+
UNSIGNED8 aucFieldName[ADS_MAX_FIELD_NAME + 1];
|
549
|
+
|
550
|
+
// If we're re-executing a query that was already open we might be reusing the
|
551
|
+
// ACE cursor object. In that case, we will already have the DBCAPI_COLUMN structures
|
552
|
+
// initialized.
|
553
|
+
#ifdef x64
|
554
|
+
ulRetCode = AdsSetProperty90( hCursor, ADS_GET_DBCAPI_BUFFER, (UNSIGNED64)&pstFieldStruct );
|
555
|
+
#else
|
556
|
+
ulRetCode = AdsSetProperty( hCursor, ADS_GET_DBCAPI_BUFFER, (UNSIGNED32)&pstFieldStruct );
|
557
|
+
#endif
|
558
|
+
|
559
|
+
if (( ulRetCode == AE_SUCCESS ) && pstFieldStruct )
|
560
|
+
// That was easy!
|
561
|
+
return AE_SUCCESS;
|
562
|
+
|
563
|
+
ulRetCode = AdsGetNumFields( hCursor, &usFieldCount );
|
564
|
+
if ( ulRetCode != AE_SUCCESS )
|
565
|
+
return ulRetCode;
|
566
|
+
|
567
|
+
ulAllocationSize = usFieldCount * sizeof( DBCAPI_COLUMN );
|
568
|
+
|
569
|
+
// Calculate how much extra memory we need for each column's data
|
570
|
+
for ( usIndex = 0; usIndex < usFieldCount; usIndex++ )
|
571
|
+
{
|
572
|
+
// Include some memory for the field name
|
573
|
+
usLen = sizeof( aucFieldName );
|
574
|
+
ulRetCode = AdsGetFieldName( hCursor, usIndex + 1, aucFieldName, &usLen );
|
575
|
+
if ( ulRetCode != AE_SUCCESS )
|
576
|
+
return ulRetCode;
|
577
|
+
|
578
|
+
ulAllocationSize += usLen + 1;
|
579
|
+
|
580
|
+
ulRetCode = AdsGetFieldType( hCursor, ADSFIELD( usIndex + 1), &usFieldType );
|
581
|
+
if ( ulRetCode != AE_SUCCESS )
|
582
|
+
return ulRetCode;
|
583
|
+
|
584
|
+
switch ( usFieldType )
|
585
|
+
{
|
586
|
+
case ADS_MEMO:
|
587
|
+
case ADS_NMEMO:
|
588
|
+
case ADS_IMAGE:
|
589
|
+
case ADS_BINARY:
|
590
|
+
case ADS_VARCHAR:
|
591
|
+
// Blob fields use a dynamic buffer
|
592
|
+
break;
|
593
|
+
|
594
|
+
case ADS_TIME:
|
595
|
+
// Time gets converted to strings
|
596
|
+
ulAllocationSize += 39; // max length if values are wacky
|
597
|
+
break;
|
598
|
+
|
599
|
+
case ADS_DATE:
|
600
|
+
case ADS_COMPACTDATE:
|
601
|
+
// Dates get converted to strings
|
602
|
+
ulAllocationSize += ADS_MAX_DATEMASK;
|
603
|
+
break;
|
604
|
+
|
605
|
+
case ADS_TIMESTAMP:
|
606
|
+
case ADS_MODTIME:
|
607
|
+
// Timestamps get converted to strings
|
608
|
+
ulAllocationSize += 39 + ADS_MAX_DATEMASK;
|
609
|
+
break;
|
610
|
+
|
611
|
+
case ADS_NCHAR:
|
612
|
+
case ADS_NVARCHAR:
|
613
|
+
// Unicode char fields
|
614
|
+
ulRetCode = AdsGetFieldLength100( hCursor, ADSFIELD( usIndex + 1 ), ADS_BYTE_LENGTH, &ulFieldLength );
|
615
|
+
if ( ulRetCode != AE_SUCCESS )
|
616
|
+
return ulRetCode;
|
617
|
+
|
618
|
+
ulAllocationSize += ulFieldLength + 2; // +2 for the double NULL
|
619
|
+
break;
|
620
|
+
|
621
|
+
case ADS_STRING:
|
622
|
+
case ADS_CISTRING:
|
623
|
+
case ADS_VARCHAR_FOX:
|
624
|
+
case ADS_NUMERIC:
|
625
|
+
// Strings need one extra byte for the NULL terminator
|
626
|
+
ulAllocationSize += 1;
|
627
|
+
|
628
|
+
default:
|
629
|
+
// Everything else needs the field length amount of bytes
|
630
|
+
ulRetCode = AdsGetFieldLength100( hCursor, ADSFIELD( usIndex + 1 ), ADS_BYTE_LENGTH, &ulFieldLength );
|
631
|
+
if ( ulRetCode != AE_SUCCESS )
|
632
|
+
return ulRetCode;
|
633
|
+
|
634
|
+
ulAllocationSize += ulFieldLength;
|
635
|
+
break;
|
636
|
+
}
|
637
|
+
}
|
638
|
+
|
639
|
+
pstFieldStruct = (DBCAPI_COLUMN*)MAllocateMemory( ulAllocationSize );
|
640
|
+
if ( pstFieldStruct == NULL )
|
641
|
+
return AdsSetLastError( AE_ALLOCATION_FAILED, NULL );
|
642
|
+
|
643
|
+
pucFieldData = (UNSIGNED8*)pstFieldStruct + (usFieldCount * sizeof( DBCAPI_COLUMN ));
|
644
|
+
|
645
|
+
for ( usIndex = 0; usIndex < usFieldCount; usIndex++ )
|
646
|
+
{
|
647
|
+
usLen = sizeof( aucFieldName );
|
648
|
+
ulRetCode = AdsGetFieldName( hCursor, usIndex + 1, pucFieldData, &usLen );
|
649
|
+
if ( ulRetCode != AE_SUCCESS )
|
650
|
+
return ulRetCode;
|
651
|
+
|
652
|
+
pstFieldStruct[usIndex].pucColumnName = pucFieldData;
|
653
|
+
pucFieldData += usLen + 1;
|
654
|
+
|
655
|
+
ulRetCode = AdsGetFieldType( hCursor, ADSFIELD( usIndex + 1), &usFieldType );
|
656
|
+
if ( ulRetCode != AE_SUCCESS )
|
657
|
+
return ulRetCode;
|
658
|
+
|
659
|
+
pstFieldStruct[usIndex].ulIsNull = 0;
|
660
|
+
switch ( usFieldType )
|
661
|
+
{
|
662
|
+
case ADS_MEMO:
|
663
|
+
case ADS_NMEMO:
|
664
|
+
case ADS_IMAGE:
|
665
|
+
case ADS_BINARY:
|
666
|
+
case ADS_VARCHAR:
|
667
|
+
// Blob fields use dynamic memory
|
668
|
+
pstFieldStruct[usIndex].pucData = NULL;
|
669
|
+
pstFieldStruct[usIndex].ulBufferLength = 0;
|
670
|
+
break;
|
671
|
+
|
672
|
+
case ADS_TIME:
|
673
|
+
// Time gets converted to strings
|
674
|
+
pstFieldStruct[usIndex].pucData = pucFieldData;
|
675
|
+
pstFieldStruct[usIndex].ulBufferLength = 39;
|
676
|
+
pucFieldData += 39;
|
677
|
+
break;
|
678
|
+
|
679
|
+
case ADS_DATE:
|
680
|
+
case ADS_COMPACTDATE:
|
681
|
+
// Dates get converted to strings
|
682
|
+
pstFieldStruct[usIndex].pucData = pucFieldData;
|
683
|
+
pstFieldStruct[usIndex].ulBufferLength = ADS_MAX_DATEMASK;
|
684
|
+
pucFieldData += ADS_MAX_DATEMASK;
|
685
|
+
break;
|
686
|
+
|
687
|
+
case ADS_TIMESTAMP:
|
688
|
+
case ADS_MODTIME:
|
689
|
+
// Timestamps get converted to strings
|
690
|
+
pstFieldStruct[usIndex].pucData = pucFieldData;
|
691
|
+
pstFieldStruct[usIndex].ulBufferLength = 39 + ADS_MAX_DATEMASK;
|
692
|
+
pucFieldData += 39 + ADS_MAX_DATEMASK;
|
693
|
+
break;
|
694
|
+
|
695
|
+
case ADS_STRING:
|
696
|
+
case ADS_CISTRING:
|
697
|
+
case ADS_VARCHAR_FOX:
|
698
|
+
case ADS_NUMERIC:
|
699
|
+
ulRetCode = AdsGetFieldLength100( hCursor, ADSFIELD( usIndex + 1 ), ADS_BYTE_LENGTH, &ulFieldLength );
|
700
|
+
if ( ulRetCode != AE_SUCCESS )
|
701
|
+
return ulRetCode;
|
702
|
+
|
703
|
+
pstFieldStruct[usIndex].pucData = pucFieldData;
|
704
|
+
pstFieldStruct[usIndex].ulBufferLength = ulFieldLength + 1;
|
705
|
+
pucFieldData += ulFieldLength + 1;
|
706
|
+
break;
|
707
|
+
|
708
|
+
case ADS_NCHAR:
|
709
|
+
case ADS_NVARCHAR:
|
710
|
+
ulRetCode = AdsGetFieldLength100( hCursor, ADSFIELD( usIndex + 1 ), ADS_BYTE_LENGTH, &ulFieldLength );
|
711
|
+
if ( ulRetCode != AE_SUCCESS )
|
712
|
+
return ulRetCode;
|
713
|
+
|
714
|
+
pstFieldStruct[usIndex].pucData = pucFieldData;
|
715
|
+
pstFieldStruct[usIndex].ulBufferLength = ulFieldLength + 2;
|
716
|
+
pucFieldData += ulFieldLength + 1;
|
717
|
+
break;
|
718
|
+
|
719
|
+
default:
|
720
|
+
ulRetCode = AdsGetFieldLength100( hCursor, ADSFIELD( usIndex + 1 ), ADS_BYTE_LENGTH, &ulFieldLength );
|
721
|
+
if ( ulRetCode != AE_SUCCESS )
|
722
|
+
return ulRetCode;
|
723
|
+
|
724
|
+
pstFieldStruct[usIndex].pucData = pucFieldData;
|
725
|
+
pstFieldStruct[usIndex].ulBufferLength = ulFieldLength;
|
726
|
+
pucFieldData += ulFieldLength;
|
727
|
+
break;
|
728
|
+
}
|
729
|
+
}
|
730
|
+
|
731
|
+
// Store the field structure pointer in the cursor object
|
732
|
+
return AdsSetProperty90( hCursor, ADS_SET_DBCAPI_BUFFER, (UNSIGNED64)pstFieldStruct );
|
733
|
+
|
734
|
+
} /* SetupCursorBuffer */
|
735
|
+
|
736
|
+
|
737
|
+
/*******************************************************************************
|
738
|
+
* Module : ads_execute
|
739
|
+
* Created : 11-04-2010 Peter F
|
740
|
+
* Last Mod :
|
741
|
+
* Return Value :
|
742
|
+
* Desc : Execute a prepared query
|
743
|
+
* Notes :
|
744
|
+
*******************************************************************************/
|
745
|
+
UNSIGNED32 ENTRYPOINT ads_execute( ADSHANDLE hStatement )
|
746
|
+
{
|
747
|
+
ADSHANDLE hCursor;
|
748
|
+
UNSIGNED32 ulRetCode;
|
749
|
+
ADSHANDLE hConnect;
|
750
|
+
|
751
|
+
DBCLogTrace( "ads_execute" );
|
752
|
+
|
753
|
+
ulRetCode = AdsGetConnectionHandle( hStatement, &hConnect );
|
754
|
+
if ( ulRetCode != AE_SUCCESS )
|
755
|
+
return DBCAPI_FAILURE;
|
756
|
+
|
757
|
+
ulRetCode = AdsRegisterCallbackFunction101( DBCAPICallback, hConnect );
|
758
|
+
if ( ulRetCode != AE_SUCCESS )
|
759
|
+
return DBCAPI_FAILURE;
|
760
|
+
|
761
|
+
ulRetCode = AdsExecuteSQL( hStatement, &hCursor );
|
762
|
+
if (( ulRetCode == AE_SUCCESS ) && hCursor )
|
763
|
+
{
|
764
|
+
ulRetCode = SetupCursorBuffer( hCursor );
|
765
|
+
if ( ulRetCode != AE_SUCCESS )
|
766
|
+
AdsCloseTable( hCursor );
|
767
|
+
}
|
768
|
+
|
769
|
+
if ( ulRetCode == AE_SUCCESS )
|
770
|
+
return DBCAPI_SUCCESS;
|
771
|
+
else
|
772
|
+
return DBCAPI_FAILURE;
|
773
|
+
|
774
|
+
} /* ads_execute */
|
775
|
+
|
776
|
+
|
777
|
+
/*******************************************************************************
|
778
|
+
* Module : ads_execute_direct
|
779
|
+
* Created : 11-04-2010 Peter F
|
780
|
+
* Last Mod :
|
781
|
+
* Return Value :
|
782
|
+
* Desc : Execute a query
|
783
|
+
* Notes :
|
784
|
+
*******************************************************************************/
|
785
|
+
ADSHANDLE ENTRYPOINT ads_execute_direct( a_ads_connection *poConnect, UNSIGNED8 *pucSQL )
|
786
|
+
{
|
787
|
+
UNSIGNED32 ulRetCode;
|
788
|
+
ADSHANDLE hCursor;
|
789
|
+
ADSHANDLE hStatement;
|
790
|
+
|
791
|
+
DBCLogTrace( "ads_execute_direct" );
|
792
|
+
|
793
|
+
if ( poConnect == NULL )
|
794
|
+
return DBCAPI_FAILURE;
|
795
|
+
|
796
|
+
ulRetCode = AdsCreateSQLStatement( poConnect->hConnect, &hStatement );
|
797
|
+
if ( ulRetCode != AE_SUCCESS )
|
798
|
+
return DBCAPI_FAILURE;
|
799
|
+
|
800
|
+
ulRetCode = AdsRegisterCallbackFunction101( DBCAPICallback, poConnect->hConnect );
|
801
|
+
if ( ulRetCode != AE_SUCCESS )
|
802
|
+
return DBCAPI_FAILURE;
|
803
|
+
|
804
|
+
ulRetCode = AdsExecuteSQLDirect( hStatement, pucSQL, &hCursor );
|
805
|
+
if ( ulRetCode != AE_SUCCESS )
|
806
|
+
{
|
807
|
+
AdsSetProperty( poConnect->hConnect, ADS_PUSH_ERROR_STACK, 0 );
|
808
|
+
AdsCloseSQLStatement( hStatement );
|
809
|
+
AdsSetProperty( poConnect->hConnect, ADS_POP_ERROR_STACK, 0 );
|
810
|
+
return DBCAPI_FAILURE;
|
811
|
+
}
|
812
|
+
else if ( hCursor )
|
813
|
+
{
|
814
|
+
ulRetCode = SetupCursorBuffer( hCursor );
|
815
|
+
if ( ulRetCode != AE_SUCCESS )
|
816
|
+
{
|
817
|
+
AdsCloseTable( hCursor );
|
818
|
+
AdsCloseSQLStatement( hStatement );
|
819
|
+
return DBCAPI_FAILURE;
|
820
|
+
}
|
821
|
+
}
|
822
|
+
|
823
|
+
return hStatement;
|
824
|
+
|
825
|
+
} /* ads_execute_direct */
|
826
|
+
|
827
|
+
|
828
|
+
/*******************************************************************************
|
829
|
+
* Module : ads_execute_immediate
|
830
|
+
* Created : 11-04-2010 Peter F
|
831
|
+
* Last Mod :
|
832
|
+
* Return Value :
|
833
|
+
* Desc : Execute a query that has no results
|
834
|
+
* Notes :
|
835
|
+
*******************************************************************************/
|
836
|
+
UNSIGNED32 ENTRYPOINT ads_execute_immediate( a_ads_connection *poConnect, UNSIGNED8 *pucSQL )
|
837
|
+
{
|
838
|
+
ADSHANDLE hCursor = 0;
|
839
|
+
UNSIGNED32 ulRetCode;
|
840
|
+
ADSHANDLE hStatement;
|
841
|
+
|
842
|
+
DBCLogTrace( "ads_execute_immediate" );
|
843
|
+
|
844
|
+
if ( poConnect == NULL )
|
845
|
+
return DBCAPI_FAILURE;
|
846
|
+
|
847
|
+
ulRetCode = AdsCreateSQLStatement( poConnect->hConnect, &hStatement );
|
848
|
+
if ( ulRetCode != AE_SUCCESS )
|
849
|
+
return DBCAPI_FAILURE;
|
850
|
+
|
851
|
+
ulRetCode = AdsRegisterCallbackFunction101( DBCAPICallback, poConnect->hConnect );
|
852
|
+
if ( ulRetCode != AE_SUCCESS )
|
853
|
+
return DBCAPI_FAILURE;
|
854
|
+
|
855
|
+
ulRetCode = AdsExecuteSQLDirect( hStatement, pucSQL, &hCursor );
|
856
|
+
if (( ulRetCode == AE_SUCCESS ) && hCursor )
|
857
|
+
// There shouldn't be a result set with this API
|
858
|
+
AdsCloseTable( hCursor );
|
859
|
+
|
860
|
+
if ( ulRetCode == AE_SUCCESS )
|
861
|
+
AdsCloseSQLStatement( hStatement );
|
862
|
+
else
|
863
|
+
{
|
864
|
+
AdsSetProperty( poConnect->hConnect, ADS_PUSH_ERROR_STACK, 0 );
|
865
|
+
AdsCloseSQLStatement( hStatement );
|
866
|
+
AdsSetProperty( poConnect->hConnect, ADS_POP_ERROR_STACK, 0 );
|
867
|
+
}
|
868
|
+
|
869
|
+
if ( ulRetCode == AE_SUCCESS )
|
870
|
+
return DBCAPI_SUCCESS;
|
871
|
+
else
|
872
|
+
return DBCAPI_FAILURE;
|
873
|
+
|
874
|
+
} /* ads_execute_immediate */
|
875
|
+
|
876
|
+
|
877
|
+
/*******************************************************************************
|
878
|
+
* Module : ads_fetch_absolute
|
879
|
+
* Created : 11-04-2010 Peter F
|
880
|
+
* Last Mod :
|
881
|
+
* Return Value :
|
882
|
+
* Desc : Fetch a specific record in a cursor
|
883
|
+
* Notes :
|
884
|
+
*******************************************************************************/
|
885
|
+
UNSIGNED32 ENTRYPOINT ads_fetch_absolute( ADSHANDLE hStatement, UNSIGNED32 ulRowNum )
|
886
|
+
{
|
887
|
+
ADSHANDLE hCursor;
|
888
|
+
|
889
|
+
DBCLogTrace( "ads_fetch_absolute" );
|
890
|
+
|
891
|
+
if ( AdsStmtGetCursorHandle( hStatement, &hCursor ) != AE_SUCCESS )
|
892
|
+
return DBCAPI_FAILURE;
|
893
|
+
|
894
|
+
if ( AdsGotoRecord( hCursor, ulRowNum ) != AE_SUCCESS )
|
895
|
+
return DBCAPI_FAILURE;
|
896
|
+
else
|
897
|
+
return DBCAPI_SUCCESS;
|
898
|
+
|
899
|
+
} /* ads_fetch_absolute */
|
900
|
+
|
901
|
+
|
902
|
+
/*******************************************************************************
|
903
|
+
* Module : ads_fetch_next
|
904
|
+
* Created : 11-04-2010 Peter F
|
905
|
+
* Last Mod :
|
906
|
+
* Return Value :
|
907
|
+
* Desc : Fetch the next record, ie Skip to the next record
|
908
|
+
* Notes :
|
909
|
+
*******************************************************************************/
|
910
|
+
UNSIGNED32 ENTRYPOINT ads_fetch_next( ADSHANDLE hStatement )
|
911
|
+
{
|
912
|
+
ADSHANDLE hCursor;
|
913
|
+
|
914
|
+
DBCLogTrace( "ads_fetch_next" );
|
915
|
+
|
916
|
+
if ( AdsStmtGetCursorHandle( hStatement, &hCursor ) != AE_SUCCESS )
|
917
|
+
return FALSE;
|
918
|
+
|
919
|
+
if ( hCursor )
|
920
|
+
{
|
921
|
+
UNSIGNED32 ulFirstFetch;
|
922
|
+
UNSIGNED32 ulRetCode;
|
923
|
+
UNSIGNED16 usIsDeleted;
|
924
|
+
|
925
|
+
// Peek into the cursor object and see if this is the first time we fetch a record
|
926
|
+
#ifdef x64
|
927
|
+
if ( AdsSetProperty90( hCursor, ADS_IS_FIRST_FETCH, (UNSIGNED64)&ulFirstFetch ) != AE_SUCCESS )
|
928
|
+
#else
|
929
|
+
if ( AdsSetProperty( hCursor, ADS_IS_FIRST_FETCH, (UNSIGNED32)&ulFirstFetch ) != AE_SUCCESS )
|
930
|
+
#endif
|
931
|
+
return FALSE;
|
932
|
+
|
933
|
+
// Since ACE automatically puts us at the first record, don't skip for the first fetch
|
934
|
+
if ( ulFirstFetch == FALSE )
|
935
|
+
{
|
936
|
+
if ( AdsSkip( hCursor, 1 ) != AE_SUCCESS )
|
937
|
+
return FALSE;
|
938
|
+
}
|
939
|
+
|
940
|
+
// If we are not positioned, this API will return AE_NO_CURRENT_RECORD
|
941
|
+
ulRetCode = AdsIsRecordDeleted( hCursor, &usIsDeleted );
|
942
|
+
if ( ulRetCode != AE_SUCCESS )
|
943
|
+
{
|
944
|
+
if ( ulRetCode == AE_NO_CURRENT_RECORD )
|
945
|
+
// Not really an error
|
946
|
+
AdsClearLastError();
|
947
|
+
|
948
|
+
return FALSE;
|
949
|
+
}
|
950
|
+
|
951
|
+
// Don't really care about usIsDeleted, as long as we are positioned
|
952
|
+
return TRUE;
|
953
|
+
}
|
954
|
+
else
|
955
|
+
return FALSE;
|
956
|
+
|
957
|
+
} /* ads_fetch_next */
|
958
|
+
|
959
|
+
|
960
|
+
/*******************************************************************************
|
961
|
+
* Module : ads_fini
|
962
|
+
* Created : 11-04-2010 Peter F
|
963
|
+
* Last Mod :
|
964
|
+
* Return Value :
|
965
|
+
* Desc : Perform any finalization tasks
|
966
|
+
* Notes :
|
967
|
+
*******************************************************************************/
|
968
|
+
UNSIGNED32 ENTRYPOINT ads_fini( void )
|
969
|
+
{
|
970
|
+
DBCLogTrace( "ads_fini" );
|
971
|
+
|
972
|
+
AdsDisconnect( 0 );
|
973
|
+
|
974
|
+
return DBCAPI_SUCCESS;
|
975
|
+
|
976
|
+
} /* ads_fini */
|
977
|
+
|
978
|
+
|
979
|
+
/*******************************************************************************
|
980
|
+
* Module : ads_free_connection
|
981
|
+
* Created : 11-04-2010 Peter F
|
982
|
+
* Last Mod :
|
983
|
+
* Return Value :
|
984
|
+
* Desc : Free an a_ads_connection object & disconnect if necessary
|
985
|
+
* Notes :
|
986
|
+
*******************************************************************************/
|
987
|
+
UNSIGNED32 ENTRYPOINT ads_free_connection( a_ads_connection *poConnect )
|
988
|
+
{
|
989
|
+
DBCLogTrace( "ads_free_connection" );
|
990
|
+
|
991
|
+
if ( poConnect == NULL )
|
992
|
+
return DBCAPI_FAILURE;
|
993
|
+
|
994
|
+
if ( poConnect->hConnect )
|
995
|
+
AdsDisconnect( poConnect->hConnect );
|
996
|
+
|
997
|
+
ReleaseMemory( poConnect );
|
998
|
+
|
999
|
+
return DBCAPI_SUCCESS;
|
1000
|
+
|
1001
|
+
} /* ads_free_connection */
|
1002
|
+
|
1003
|
+
|
1004
|
+
/*******************************************************************************
|
1005
|
+
* Module : ads_free_stmt
|
1006
|
+
* Created : 11-04-2010 Peter F
|
1007
|
+
* Last Mod :
|
1008
|
+
* Return Value :
|
1009
|
+
* Desc : Free a statement
|
1010
|
+
* Notes : This will free any open cursors & the DBCAPI_COLUMN data within
|
1011
|
+
*******************************************************************************/
|
1012
|
+
UNSIGNED32 ENTRYPOINT ads_free_stmt( ADSHANDLE hStatement )
|
1013
|
+
{
|
1014
|
+
DBCLogTrace( "ads_free_stmt" );
|
1015
|
+
|
1016
|
+
if ( hStatement == 0 )
|
1017
|
+
return DBCAPI_FAILURE;
|
1018
|
+
|
1019
|
+
if ( AdsCloseSQLStatement( hStatement ) != AE_SUCCESS )
|
1020
|
+
return DBCAPI_FAILURE;
|
1021
|
+
|
1022
|
+
return DBCAPI_SUCCESS;
|
1023
|
+
|
1024
|
+
} /* ads_free_stmt */
|
1025
|
+
|
1026
|
+
|
1027
|
+
/*******************************************************************************
|
1028
|
+
* Module : ads_get_bind_param_info
|
1029
|
+
* Created : 11-04-2010 Peter F
|
1030
|
+
* Last Mod :
|
1031
|
+
* Return Value :
|
1032
|
+
* Desc : Retrieves information about the parameters that were bound using ads_bind_param
|
1033
|
+
* Notes : Currently not supported
|
1034
|
+
*******************************************************************************/
|
1035
|
+
UNSIGNED32 ENTRYPOINT ads_get_bind_param_info( ADSHANDLE hStatement, UNSIGNED32 ulIndex, a_ads_bind_param_info *info )
|
1036
|
+
{
|
1037
|
+
DBCLogTrace( "ads_get_bind_param_info" );
|
1038
|
+
|
1039
|
+
// UNRESOLVED PF: I think we could support this if the parameter has
|
1040
|
+
// already been set. The statement in ACE has the parameter name, number,
|
1041
|
+
// type, and length. Since we don't support binding variables to parameters
|
1042
|
+
// this function will be incomplete and perhaps not very useful anyway.
|
1043
|
+
return DBCAPI_FAILURE;
|
1044
|
+
|
1045
|
+
} /* ads_get_bind_param_info */
|
1046
|
+
|
1047
|
+
|
1048
|
+
/*******************************************************************************
|
1049
|
+
* Module : DBCAPIGetData
|
1050
|
+
* Created : 11-04-2010 Peter F
|
1051
|
+
* Last Mod :
|
1052
|
+
* Return Value :
|
1053
|
+
* Desc : Utility FN to get column data
|
1054
|
+
* Notes :
|
1055
|
+
*******************************************************************************/
|
1056
|
+
UNSIGNED32 DBCAPIGetData
|
1057
|
+
(
|
1058
|
+
ADSHANDLE hCursor,
|
1059
|
+
a_ads_data_type usDataType,
|
1060
|
+
UNSIGNED32 ulIndex,
|
1061
|
+
UNSIGNED8 **ppucBuffer,
|
1062
|
+
UNSIGNED32 *pulLength,
|
1063
|
+
UNSIGNED32 *pulBufferLength,
|
1064
|
+
UNSIGNED16 *pusIsNull,
|
1065
|
+
UNSIGNED32 ulOffset
|
1066
|
+
)
|
1067
|
+
{
|
1068
|
+
UNSIGNED32 ulRetCode;
|
1069
|
+
UNSIGNED16 usFieldType;
|
1070
|
+
|
1071
|
+
ulRetCode = AdsIsNull( hCursor, ADSFIELD(ulIndex+1), pusIsNull );
|
1072
|
+
if ( ulRetCode != AE_SUCCESS )
|
1073
|
+
return ulRetCode;
|
1074
|
+
|
1075
|
+
switch ( usDataType )
|
1076
|
+
{
|
1077
|
+
case A_VAL16:
|
1078
|
+
ulRetCode = AdsGetShort( hCursor, ADSFIELD(ulIndex+1), (SIGNED16*)*ppucBuffer );
|
1079
|
+
if ( ulRetCode != AE_SUCCESS )
|
1080
|
+
return ulRetCode;
|
1081
|
+
|
1082
|
+
*pulLength = sizeof( SIGNED16 );
|
1083
|
+
break;
|
1084
|
+
|
1085
|
+
case A_UVAL8:
|
1086
|
+
{
|
1087
|
+
UNSIGNED16 usShort;
|
1088
|
+
ulRetCode = AdsGetLogical( hCursor, ADSFIELD(ulIndex+1), &usShort );
|
1089
|
+
if ( ulRetCode != AE_SUCCESS )
|
1090
|
+
return ulRetCode;
|
1091
|
+
|
1092
|
+
**ppucBuffer = (UNSIGNED8)usShort;
|
1093
|
+
*pulLength = sizeof( UNSIGNED8 );
|
1094
|
+
}
|
1095
|
+
break;
|
1096
|
+
|
1097
|
+
case A_VAL32:
|
1098
|
+
case A_UVAL32:
|
1099
|
+
ulRetCode = AdsGetLong( hCursor, ADSFIELD(ulIndex+1), (SIGNED32*)*ppucBuffer );
|
1100
|
+
if ( ulRetCode != AE_SUCCESS )
|
1101
|
+
return ulRetCode;
|
1102
|
+
|
1103
|
+
*pulLength = sizeof( SIGNED32 );
|
1104
|
+
break;
|
1105
|
+
|
1106
|
+
case A_DOUBLE:
|
1107
|
+
ulRetCode = AdsGetDouble( hCursor, ADSFIELD(ulIndex+1), (double*)*ppucBuffer );
|
1108
|
+
if ( ulRetCode != AE_SUCCESS )
|
1109
|
+
return ulRetCode;
|
1110
|
+
|
1111
|
+
*pulLength = sizeof( double );
|
1112
|
+
break;
|
1113
|
+
|
1114
|
+
case A_VAL64:
|
1115
|
+
case A_UVAL64:
|
1116
|
+
ulRetCode = AdsGetLongLong( hCursor, ADSFIELD(ulIndex+1), (SIGNED64*)*ppucBuffer );
|
1117
|
+
if ( ulRetCode != AE_SUCCESS )
|
1118
|
+
return ulRetCode;
|
1119
|
+
|
1120
|
+
*pulLength = sizeof( SIGNED64 );
|
1121
|
+
break;
|
1122
|
+
|
1123
|
+
default:
|
1124
|
+
// If no buffer length is provided, the user provided us the buffer so just call AdsGetField
|
1125
|
+
if ( !pulBufferLength )
|
1126
|
+
{
|
1127
|
+
if ( ulOffset )
|
1128
|
+
return AdsGetBinary( hCursor, ADSFIELD(ulIndex+1), ulOffset, *ppucBuffer, pulLength );
|
1129
|
+
else
|
1130
|
+
return AdsGetField( hCursor, ADSFIELD(ulIndex+1), *ppucBuffer, pulLength, ADS_NONE );
|
1131
|
+
}
|
1132
|
+
|
1133
|
+
ulRetCode = AdsGetFieldType( hCursor, ADSFIELD( ulIndex+1 ), &usFieldType );
|
1134
|
+
if ( ulRetCode != AE_SUCCESS )
|
1135
|
+
return ulRetCode;
|
1136
|
+
|
1137
|
+
switch ( usFieldType )
|
1138
|
+
{
|
1139
|
+
case ADS_MEMO:
|
1140
|
+
case ADS_NMEMO:
|
1141
|
+
case ADS_IMAGE:
|
1142
|
+
case ADS_BINARY:
|
1143
|
+
case ADS_VARCHAR:
|
1144
|
+
// BLOB fields use a dynamic buffer to store the data
|
1145
|
+
if ( *pusIsNull )
|
1146
|
+
*pulLength = 0;
|
1147
|
+
else
|
1148
|
+
{
|
1149
|
+
UNSIGNED32 ulBlobLength;
|
1150
|
+
|
1151
|
+
ulRetCode = AdsGetMemoLength( hCursor, ADSFIELD(ulIndex+1), &ulBlobLength );
|
1152
|
+
if ( ulRetCode != AE_SUCCESS )
|
1153
|
+
return ulRetCode;
|
1154
|
+
|
1155
|
+
// Memo (string) fields need an extra byte for the NULL
|
1156
|
+
if (( usFieldType == ADS_MEMO ) || ( usFieldType == ADS_VARCHAR ))
|
1157
|
+
ulBlobLength++;
|
1158
|
+
|
1159
|
+
else if ( usFieldType == ADS_NMEMO )
|
1160
|
+
ulBlobLength = ( ulBlobLength + 1 ) * 2;
|
1161
|
+
|
1162
|
+
// Allocate a larger buffer if necessary
|
1163
|
+
if ( *pulBufferLength < ulBlobLength )
|
1164
|
+
{
|
1165
|
+
if ( *ppucBuffer )
|
1166
|
+
*ppucBuffer = (UNSIGNED8*)ReallocateMemory( *ppucBuffer, ulBlobLength );
|
1167
|
+
else
|
1168
|
+
*ppucBuffer = (UNSIGNED8*)MAllocateMemory( ulBlobLength );
|
1169
|
+
|
1170
|
+
if ( *ppucBuffer == NULL )
|
1171
|
+
return AdsSetLastError( AE_ALLOCATION_FAILED, NULL );
|
1172
|
+
|
1173
|
+
*pulBufferLength = ulBlobLength;
|
1174
|
+
}
|
1175
|
+
|
1176
|
+
*pulLength = *pulBufferLength;
|
1177
|
+
if (( usFieldType == ADS_MEMO ) || ( usFieldType == ADS_VARCHAR ))
|
1178
|
+
ulRetCode = AdsGetString( hCursor, ADSFIELD(ulIndex+1), *ppucBuffer, pulLength, ADS_NONE );
|
1179
|
+
|
1180
|
+
else if ( usFieldType == ADS_NMEMO )
|
1181
|
+
{
|
1182
|
+
// AdsGetStringW expects number of chars, not bytes
|
1183
|
+
*pulLength >>= 1;
|
1184
|
+
ulRetCode = AdsGetStringW( hCursor, ADSFIELD(ulIndex+1), (WCHAR*)*ppucBuffer, pulLength, ADS_NONE );
|
1185
|
+
if ( ulRetCode == AE_SUCCESS )
|
1186
|
+
*pulLength <<= 1;
|
1187
|
+
}
|
1188
|
+
|
1189
|
+
else
|
1190
|
+
ulRetCode = AdsGetBinary( hCursor, ADSFIELD(ulIndex+1), 0, *ppucBuffer, pulLength );
|
1191
|
+
|
1192
|
+
if ( ulRetCode != AE_SUCCESS )
|
1193
|
+
return ulRetCode;
|
1194
|
+
}
|
1195
|
+
break;
|
1196
|
+
|
1197
|
+
case ADS_NCHAR:
|
1198
|
+
case ADS_NVARCHAR:
|
1199
|
+
*pulLength = *pulBufferLength;
|
1200
|
+
*pulLength >>= 1;
|
1201
|
+
ulRetCode = AdsGetStringW( hCursor, ADSFIELD(ulIndex+1), (WCHAR*)*ppucBuffer, pulLength, ADS_NONE );
|
1202
|
+
if ( ulRetCode == AE_SUCCESS )
|
1203
|
+
*pulLength <<= 1;
|
1204
|
+
break;
|
1205
|
+
|
1206
|
+
default:
|
1207
|
+
// Non blob fields can just use AdsGetField
|
1208
|
+
*pulLength = *pulBufferLength;
|
1209
|
+
ulRetCode = AdsGetField( hCursor, ADSFIELD(ulIndex+1), *ppucBuffer, pulLength, ADS_NONE );
|
1210
|
+
if ( ulRetCode != AE_SUCCESS )
|
1211
|
+
return ulRetCode;
|
1212
|
+
|
1213
|
+
break;
|
1214
|
+
|
1215
|
+
} // switch ( ACE type )
|
1216
|
+
|
1217
|
+
break;
|
1218
|
+
|
1219
|
+
} // switch( DBCAPI type )
|
1220
|
+
|
1221
|
+
return ulRetCode;
|
1222
|
+
|
1223
|
+
} /* DBCAPIGetData */
|
1224
|
+
|
1225
|
+
|
1226
|
+
/*******************************************************************************
|
1227
|
+
* Module : ads_get_column
|
1228
|
+
* Created : 11-04-2010 Peter F
|
1229
|
+
* Last Mod :
|
1230
|
+
* Return Value :
|
1231
|
+
* Desc : Get the value of a column
|
1232
|
+
* Notes :
|
1233
|
+
*******************************************************************************/
|
1234
|
+
UNSIGNED32 ENTRYPOINT ads_get_column( ADSHANDLE hStatement, UNSIGNED32 ulIndex, a_ads_data_value *buffer )
|
1235
|
+
{
|
1236
|
+
ADSHANDLE hCursor;
|
1237
|
+
UNSIGNED16 usIsNull;
|
1238
|
+
UNSIGNED32 ulRetCode;
|
1239
|
+
DBCAPI_COLUMN *pstColumnStruct;
|
1240
|
+
UNSIGNED16 usFieldType;
|
1241
|
+
|
1242
|
+
DBCLogTrace( "ads_get_column" );
|
1243
|
+
|
1244
|
+
if ( buffer == NULL )
|
1245
|
+
return DBCAPI_FAILURE;
|
1246
|
+
|
1247
|
+
if ( AdsStmtGetCursorHandle( hStatement, &hCursor ) != AE_SUCCESS )
|
1248
|
+
return DBCAPI_FAILURE;
|
1249
|
+
|
1250
|
+
#ifdef x64
|
1251
|
+
ulRetCode = AdsSetProperty90( hCursor, ADS_GET_DBCAPI_BUFFER, (UNSIGNED64)&pstColumnStruct );
|
1252
|
+
#else
|
1253
|
+
ulRetCode = AdsSetProperty( hCursor, ADS_GET_DBCAPI_BUFFER, (UNSIGNED32)&pstColumnStruct );
|
1254
|
+
#endif
|
1255
|
+
|
1256
|
+
if (( ulRetCode != AE_SUCCESS ) || !pstColumnStruct )
|
1257
|
+
return DBCAPI_FAILURE;
|
1258
|
+
|
1259
|
+
pstColumnStruct += ulIndex;
|
1260
|
+
|
1261
|
+
if ( AdsGetFieldType( hCursor, ADSFIELD( ulIndex + 1 ), &usFieldType ) != AE_SUCCESS )
|
1262
|
+
return DBCAPI_FAILURE;
|
1263
|
+
|
1264
|
+
buffer->type = ConvertACEToIOType( usFieldType );
|
1265
|
+
ulRetCode = DBCAPIGetData( hCursor, buffer->type, ulIndex,
|
1266
|
+
&(pstColumnStruct->pucData),
|
1267
|
+
&(pstColumnStruct->ulDataLength),
|
1268
|
+
&(pstColumnStruct->ulBufferLength),
|
1269
|
+
&usIsNull, 0 );
|
1270
|
+
if ( ulRetCode == AE_SUCCESS )
|
1271
|
+
{
|
1272
|
+
buffer->buffer = pstColumnStruct->pucData;
|
1273
|
+
buffer->length = &(pstColumnStruct->ulDataLength);
|
1274
|
+
buffer->is_null = &(pstColumnStruct->ulIsNull);
|
1275
|
+
buffer->buffer_size = pstColumnStruct->ulBufferLength;
|
1276
|
+
*(buffer->is_null) = usIsNull;
|
1277
|
+
return DBCAPI_SUCCESS;
|
1278
|
+
}
|
1279
|
+
else
|
1280
|
+
{
|
1281
|
+
*(buffer->length) = 0;
|
1282
|
+
buffer->buffer_size = 0;
|
1283
|
+
buffer->buffer = NULL;
|
1284
|
+
buffer->type = A_INVALID_TYPE;
|
1285
|
+
*(buffer->is_null) = 0;
|
1286
|
+
return DBCAPI_NEGONE;
|
1287
|
+
}
|
1288
|
+
|
1289
|
+
} /* ads_get_column */
|
1290
|
+
|
1291
|
+
|
1292
|
+
/*******************************************************************************
|
1293
|
+
* Module : ads_get_column_info
|
1294
|
+
* Created : 11-04-2010 Peter F
|
1295
|
+
* Last Mod :
|
1296
|
+
* Return Value :
|
1297
|
+
* Desc : Get some info about a column
|
1298
|
+
* Notes :
|
1299
|
+
*******************************************************************************/
|
1300
|
+
UNSIGNED32 ENTRYPOINT ads_get_column_info( ADSHANDLE hStatement, UNSIGNED32 ulIndex, a_ads_column_info *buffer )
|
1301
|
+
{
|
1302
|
+
ADSHANDLE hCursor;
|
1303
|
+
UNSIGNED16 usFieldType;
|
1304
|
+
UNSIGNED32 ulFieldLength;
|
1305
|
+
UNSIGNED16 usFieldDecimals;
|
1306
|
+
UNSIGNED16 usIsNullable;
|
1307
|
+
DBCAPI_COLUMN *pstColumnStruct;
|
1308
|
+
UNSIGNED32 ulRetCode;
|
1309
|
+
|
1310
|
+
DBCLogTrace( "ads_get_column_info" );
|
1311
|
+
|
1312
|
+
if ( buffer == NULL )
|
1313
|
+
return DBCAPI_FAILURE;
|
1314
|
+
|
1315
|
+
if ( AdsStmtGetCursorHandle( hStatement, &hCursor ) != AE_SUCCESS )
|
1316
|
+
return DBCAPI_FAILURE;
|
1317
|
+
|
1318
|
+
if ( AdsGetFieldType( hCursor, ADSFIELD( ulIndex + 1 ), &usFieldType ) != AE_SUCCESS )
|
1319
|
+
return DBCAPI_FAILURE;
|
1320
|
+
|
1321
|
+
if ( AdsGetFieldLength100( hCursor, ADSFIELD( ulIndex + 1 ), ADS_BYTE_LENGTH, &ulFieldLength ) != AE_SUCCESS )
|
1322
|
+
return DBCAPI_FAILURE;
|
1323
|
+
|
1324
|
+
if ( AdsGetFieldDecimals( hCursor, ADSFIELD( ulIndex + 1 ), &usFieldDecimals ) != AE_SUCCESS )
|
1325
|
+
return DBCAPI_FAILURE;
|
1326
|
+
|
1327
|
+
if ( AdsIsNullable( hCursor, ADSFIELD( ulIndex + 1 ), &usIsNullable ) != AE_SUCCESS )
|
1328
|
+
return DBCAPI_FAILURE;
|
1329
|
+
|
1330
|
+
#ifdef x64
|
1331
|
+
ulRetCode = AdsSetProperty90( hCursor, ADS_GET_DBCAPI_BUFFER, (UNSIGNED64)&pstColumnStruct );
|
1332
|
+
#else
|
1333
|
+
ulRetCode = AdsSetProperty( hCursor, ADS_GET_DBCAPI_BUFFER, (UNSIGNED32)&pstColumnStruct );
|
1334
|
+
#endif
|
1335
|
+
|
1336
|
+
if (( ulRetCode != AE_SUCCESS ) || !pstColumnStruct )
|
1337
|
+
return DBCAPI_FAILURE;
|
1338
|
+
|
1339
|
+
pstColumnStruct += ulIndex;
|
1340
|
+
|
1341
|
+
buffer->name = pstColumnStruct->pucColumnName;
|
1342
|
+
buffer->max_size = ulFieldLength;
|
1343
|
+
buffer->precision = (UNSIGNED16)ulFieldLength;
|
1344
|
+
buffer->scale = usFieldDecimals;
|
1345
|
+
buffer->nullable = usIsNullable;
|
1346
|
+
buffer->type = ConvertACEToIOType( usFieldType );
|
1347
|
+
buffer->native_type = ConvertACEtoNativeType( usFieldType );
|
1348
|
+
|
1349
|
+
return DBCAPI_SUCCESS;
|
1350
|
+
|
1351
|
+
|
1352
|
+
} /* ads_get_column_info */
|
1353
|
+
|
1354
|
+
|
1355
|
+
/*******************************************************************************
|
1356
|
+
* Module : ads_get_data
|
1357
|
+
* Created : 11-04-2010 Peter F
|
1358
|
+
* Last Mod :
|
1359
|
+
* Return Value :
|
1360
|
+
* Desc : Get data from a column
|
1361
|
+
* Notes :
|
1362
|
+
*******************************************************************************/
|
1363
|
+
UNSIGNED32 ENTRYPOINT ads_get_data( ADSHANDLE hStatement, UNSIGNED32 ulIndex, UNSIGNED32 ulOffset, void *buffer, UNSIGNED32 ulLength )
|
1364
|
+
{
|
1365
|
+
UNSIGNED32 ulRetCode;
|
1366
|
+
UNSIGNED16 usIsNull;
|
1367
|
+
UNSIGNED16 usFieldType;
|
1368
|
+
ADSHANDLE hCursor;
|
1369
|
+
|
1370
|
+
DBCLogTrace( "ads_get_data" );
|
1371
|
+
|
1372
|
+
if ( buffer == NULL )
|
1373
|
+
return DBCAPI_NEGONE;
|
1374
|
+
|
1375
|
+
if ( hStatement == 0 )
|
1376
|
+
return DBCAPI_NEGONE;
|
1377
|
+
|
1378
|
+
ulRetCode = AdsStmtGetCursorHandle( hStatement, &hCursor );
|
1379
|
+
if ( ulRetCode != AE_SUCCESS )
|
1380
|
+
return DBCAPI_NEGONE;
|
1381
|
+
|
1382
|
+
ulRetCode = AdsGetFieldType( hCursor, ADSFIELD(ulIndex+1), &usFieldType );
|
1383
|
+
if ( ulRetCode != AE_SUCCESS )
|
1384
|
+
return DBCAPI_NEGONE;
|
1385
|
+
|
1386
|
+
ulRetCode = DBCAPIGetData( hCursor, ConvertACEToIOType( usFieldType ),
|
1387
|
+
ulIndex, (UNSIGNED8**)&buffer,
|
1388
|
+
&ulLength, NULL, &usIsNull, ulOffset );
|
1389
|
+
if ( ulRetCode != AE_SUCCESS )
|
1390
|
+
return DBCAPI_NEGONE;
|
1391
|
+
|
1392
|
+
return ulLength;
|
1393
|
+
|
1394
|
+
} /* ads_get_data */
|
1395
|
+
|
1396
|
+
|
1397
|
+
/*******************************************************************************
|
1398
|
+
* Module : ads_get_data_info
|
1399
|
+
* Created : 11-04-2010 Peter F
|
1400
|
+
* Last Mod :
|
1401
|
+
* Return Value :
|
1402
|
+
* Desc : Get some info about a column's value
|
1403
|
+
* Notes :
|
1404
|
+
*******************************************************************************/
|
1405
|
+
UNSIGNED32 ENTRYPOINT ads_get_data_info( ADSHANDLE hStatement, UNSIGNED32 ulIndex, a_ads_data_info *buffer )
|
1406
|
+
{
|
1407
|
+
UNSIGNED32 ulRetCode;
|
1408
|
+
UNSIGNED16 usType;
|
1409
|
+
UNSIGNED16 usIsNull;
|
1410
|
+
UNSIGNED32 ulDataLength;
|
1411
|
+
ADSHANDLE hCursor;
|
1412
|
+
|
1413
|
+
DBCLogTrace( "ads_get_data_info" );
|
1414
|
+
|
1415
|
+
if ( buffer == NULL )
|
1416
|
+
return DBCAPI_FAILURE;
|
1417
|
+
|
1418
|
+
if ( AdsStmtGetCursorHandle( hStatement, &hCursor ) != AE_SUCCESS )
|
1419
|
+
return DBCAPI_FAILURE;
|
1420
|
+
|
1421
|
+
if ( hCursor == 0 )
|
1422
|
+
return DBCAPI_FAILURE;
|
1423
|
+
|
1424
|
+
ulRetCode = AdsGetFieldType( hCursor, ADSFIELD(ulIndex+1), &usType );
|
1425
|
+
if ( ulRetCode != AE_SUCCESS )
|
1426
|
+
return DBCAPI_FAILURE;
|
1427
|
+
|
1428
|
+
ulRetCode = AdsIsNull( hCursor, ADSFIELD(ulIndex+1), &usIsNull );
|
1429
|
+
if ( ulRetCode != AE_SUCCESS )
|
1430
|
+
return DBCAPI_FAILURE;
|
1431
|
+
|
1432
|
+
if (( usType == ADS_MEMO ) ||
|
1433
|
+
( usType == ADS_NMEMO ) ||
|
1434
|
+
( usType == ADS_VARCHAR ) ||
|
1435
|
+
( usType == ADS_BINARY ) ||
|
1436
|
+
( usType == ADS_IMAGE ))
|
1437
|
+
ulRetCode = AdsGetMemoLength( hCursor, ADSFIELD(ulIndex+1), &ulDataLength );
|
1438
|
+
else
|
1439
|
+
ulRetCode = AdsGetFieldLength100( hCursor, ADSFIELD(ulIndex+1), ADS_BYTE_LENGTH, &ulDataLength );
|
1440
|
+
|
1441
|
+
if ( ulRetCode != AE_SUCCESS )
|
1442
|
+
return DBCAPI_FAILURE;
|
1443
|
+
|
1444
|
+
buffer->type = ConvertACEToIOType( usType );
|
1445
|
+
buffer->is_null = usIsNull;
|
1446
|
+
buffer->data_size = ulDataLength;
|
1447
|
+
|
1448
|
+
return DBCAPI_SUCCESS;
|
1449
|
+
|
1450
|
+
} /* ads_get_data_info */
|
1451
|
+
|
1452
|
+
|
1453
|
+
/*******************************************************************************
|
1454
|
+
* Module : ads_get_next_result
|
1455
|
+
* Created : 11-04-2010 Peter F
|
1456
|
+
* Last Mod :
|
1457
|
+
* Return Value :
|
1458
|
+
* Desc : Get the next result set from the statement
|
1459
|
+
* Notes : Unsupported with ADS
|
1460
|
+
*******************************************************************************/
|
1461
|
+
UNSIGNED32 ENTRYPOINT ads_get_next_result( ADSHANDLE hStatement )
|
1462
|
+
{
|
1463
|
+
DBCLogTrace( "ads_get_next_result" );
|
1464
|
+
|
1465
|
+
// ADS doesn't support multiple result sets on a single statement
|
1466
|
+
return DBCAPI_FAILURE;
|
1467
|
+
|
1468
|
+
} /* ads_get_next_result */
|
1469
|
+
|
1470
|
+
|
1471
|
+
/*******************************************************************************
|
1472
|
+
* Module : ads_init
|
1473
|
+
* Created : 11-04-2010 Peter F
|
1474
|
+
* Last Mod :
|
1475
|
+
* Return Value :
|
1476
|
+
* Desc : Initialize the DBCAPI client
|
1477
|
+
* Notes :
|
1478
|
+
*******************************************************************************/
|
1479
|
+
UNSIGNED32 ENTRYPOINT ads_init( UNSIGNED8 *app_name, UNSIGNED32 api_version, UNSIGNED32 *version_available )
|
1480
|
+
{
|
1481
|
+
DBCLogTrace( "ads_init" );
|
1482
|
+
|
1483
|
+
// We support the more basic version of DBCAPI, version 1
|
1484
|
+
*version_available = 1;
|
1485
|
+
|
1486
|
+
return DBCAPI_SUCCESS;
|
1487
|
+
|
1488
|
+
} /* ads_init */
|
1489
|
+
|
1490
|
+
|
1491
|
+
/*******************************************************************************
|
1492
|
+
* Module : ads_make_connection
|
1493
|
+
* Created : 11-04-2010 Peter F
|
1494
|
+
* Last Mod :
|
1495
|
+
* Return Value :
|
1496
|
+
* Desc : "make" a connection from a DBLIB SQLCA object
|
1497
|
+
* Notes :
|
1498
|
+
*******************************************************************************/
|
1499
|
+
a_ads_connection_ptr ENTRYPOINT ads_make_connection( void *arg )
|
1500
|
+
{
|
1501
|
+
DBCLogTrace( "ads_make_connection" );
|
1502
|
+
|
1503
|
+
// Create a connection object based on a supplied DBLIB SQLCA pointer
|
1504
|
+
// UNRESOLVED how to interpret a DBLIB SQLCA object?
|
1505
|
+
return NULL;
|
1506
|
+
|
1507
|
+
} /* ads_make_connection */
|
1508
|
+
|
1509
|
+
|
1510
|
+
/*******************************************************************************
|
1511
|
+
* Module : ads_new_connection
|
1512
|
+
* Created : 11-04-2010 Peter F
|
1513
|
+
* Last Mod :
|
1514
|
+
* Return Value :
|
1515
|
+
* Desc : Allocate a new a_ads_connection object
|
1516
|
+
* Notes : Doesn't connect, just creates a new object
|
1517
|
+
*******************************************************************************/
|
1518
|
+
a_ads_connection_ptr ENTRYPOINT ads_new_connection( void )
|
1519
|
+
{
|
1520
|
+
a_ads_connection *poConnect;
|
1521
|
+
|
1522
|
+
DBCLogTrace( "ads_new_connection" );
|
1523
|
+
|
1524
|
+
// Return a DBCAPI connection object, later we'll get a real connection via ads_connect
|
1525
|
+
poConnect = (a_ads_connection*)MAllocateMemory( sizeof( a_ads_connection ));
|
1526
|
+
if ( poConnect )
|
1527
|
+
memset( poConnect, 0, sizeof( a_ads_connection ));
|
1528
|
+
|
1529
|
+
return poConnect;
|
1530
|
+
|
1531
|
+
} /* ads_new_connection */
|
1532
|
+
|
1533
|
+
|
1534
|
+
/*******************************************************************************
|
1535
|
+
* Module : ads_num_cols
|
1536
|
+
* Created : 11-04-2010 Peter F
|
1537
|
+
* Last Mod :
|
1538
|
+
* Return Value :
|
1539
|
+
* Desc : Return the number of columns in the cursor
|
1540
|
+
* Notes :
|
1541
|
+
*******************************************************************************/
|
1542
|
+
UNSIGNED32 ENTRYPOINT ads_num_cols( ADSHANDLE hStatement )
|
1543
|
+
{
|
1544
|
+
ADSHANDLE hCursor;
|
1545
|
+
UNSIGNED16 usFieldCount;
|
1546
|
+
|
1547
|
+
DBCLogTrace( "ads_num_cols" );
|
1548
|
+
|
1549
|
+
if ( hStatement == 0 )
|
1550
|
+
return DBCAPI_FAILURE;
|
1551
|
+
|
1552
|
+
if ( AdsStmtGetCursorHandle( hStatement, &hCursor ) != AE_SUCCESS )
|
1553
|
+
return DBCAPI_FAILURE;
|
1554
|
+
|
1555
|
+
if ( hCursor == 0 )
|
1556
|
+
return DBCAPI_FAILURE;
|
1557
|
+
|
1558
|
+
if ( AdsGetNumFields( hCursor, &usFieldCount ) != AE_SUCCESS )
|
1559
|
+
return DBCAPI_FAILURE;
|
1560
|
+
else
|
1561
|
+
return usFieldCount;
|
1562
|
+
|
1563
|
+
} /* ads_num_cols */
|
1564
|
+
|
1565
|
+
|
1566
|
+
/*******************************************************************************
|
1567
|
+
* Module : ads_num_params
|
1568
|
+
* Created : 11-04-2010 Peter F
|
1569
|
+
* Last Mod :
|
1570
|
+
* Return Value :
|
1571
|
+
* Desc : Return the number of parameters in the statement
|
1572
|
+
* Notes :
|
1573
|
+
*******************************************************************************/
|
1574
|
+
UNSIGNED32 ENTRYPOINT ads_num_params( ADSHANDLE hStatement )
|
1575
|
+
{
|
1576
|
+
UNSIGNED16 usNumParams;
|
1577
|
+
|
1578
|
+
DBCLogTrace( "ads_num_params" );
|
1579
|
+
|
1580
|
+
if ( hStatement == 0 )
|
1581
|
+
return DBCAPI_FAILURE;
|
1582
|
+
|
1583
|
+
if ( AdsStmtGetNumParams( hStatement, &usNumParams ) != AE_SUCCESS )
|
1584
|
+
return DBCAPI_FAILURE;
|
1585
|
+
else
|
1586
|
+
return usNumParams;
|
1587
|
+
|
1588
|
+
} /* ads_num_params */
|
1589
|
+
|
1590
|
+
|
1591
|
+
/*******************************************************************************
|
1592
|
+
* Module : ads_num_rows
|
1593
|
+
* Created : 11-04-2010 Peter F
|
1594
|
+
* Last Mod :
|
1595
|
+
* Return Value :
|
1596
|
+
* Desc : Return the number of rows in the cursor
|
1597
|
+
* Notes :
|
1598
|
+
*******************************************************************************/
|
1599
|
+
UNSIGNED32 ENTRYPOINT ads_num_rows( ADSHANDLE hStatement )
|
1600
|
+
{
|
1601
|
+
UNSIGNED32 ulRecordCount;
|
1602
|
+
ADSHANDLE hCursor;
|
1603
|
+
|
1604
|
+
DBCLogTrace( "ads_num_rows" );
|
1605
|
+
|
1606
|
+
if ( AdsStmtGetCursorHandle( hStatement, &hCursor ) != AE_SUCCESS )
|
1607
|
+
return DBCAPI_FAILURE;
|
1608
|
+
|
1609
|
+
if ( AdsGetRecordCount( hCursor, ADS_RESPECTFILTERS, &ulRecordCount ) != AE_SUCCESS )
|
1610
|
+
return DBCAPI_FAILURE;
|
1611
|
+
else
|
1612
|
+
return ulRecordCount;
|
1613
|
+
|
1614
|
+
} /* ads_num_rows */
|
1615
|
+
|
1616
|
+
|
1617
|
+
/*******************************************************************************
|
1618
|
+
* Module : ads_prepare
|
1619
|
+
* Created : 11-04-2010 Peter F
|
1620
|
+
* Last Mod :
|
1621
|
+
* Return Value :
|
1622
|
+
* Desc : Prepare a query for execution
|
1623
|
+
* Notes :
|
1624
|
+
*******************************************************************************/
|
1625
|
+
ADSHANDLE ENTRYPOINT ads_prepare( a_ads_connection *poConnect, UNSIGNED8 *pucSQL, UNSIGNED8 ucIsUnicode )
|
1626
|
+
{
|
1627
|
+
ADSHANDLE hStmt;
|
1628
|
+
UNSIGNED32 ulRetCode;
|
1629
|
+
|
1630
|
+
DBCLogTrace( "ads_prepare" );
|
1631
|
+
|
1632
|
+
if ( poConnect == NULL )
|
1633
|
+
return DBCAPI_FAILURE;
|
1634
|
+
|
1635
|
+
ulRetCode = AdsCreateSQLStatement( poConnect->hConnect, &hStmt );
|
1636
|
+
if ( ulRetCode != AE_SUCCESS )
|
1637
|
+
return DBCAPI_FAILURE;
|
1638
|
+
|
1639
|
+
if ( ucIsUnicode )
|
1640
|
+
ulRetCode = AdsPrepareSQLW( hStmt, (WCHAR*)pucSQL );
|
1641
|
+
else
|
1642
|
+
ulRetCode = AdsPrepareSQL( hStmt, pucSQL );
|
1643
|
+
if ( ulRetCode != AE_SUCCESS )
|
1644
|
+
{
|
1645
|
+
AdsSetProperty( poConnect->hConnect, ADS_PUSH_ERROR_STACK, 0 );
|
1646
|
+
AdsCloseSQLStatement( hStmt );
|
1647
|
+
AdsSetProperty( poConnect->hConnect, ADS_POP_ERROR_STACK, 0 );
|
1648
|
+
return DBCAPI_FAILURE;
|
1649
|
+
}
|
1650
|
+
|
1651
|
+
return hStmt;
|
1652
|
+
|
1653
|
+
} /* ads_prepare */
|
1654
|
+
|
1655
|
+
|
1656
|
+
/*******************************************************************************
|
1657
|
+
* Module : ads_reset
|
1658
|
+
* Created : 11-04-2010 Peter F
|
1659
|
+
* Last Mod :
|
1660
|
+
* Return Value :
|
1661
|
+
* Desc : Resets a statement to its prepared state condition.
|
1662
|
+
* Notes :
|
1663
|
+
*******************************************************************************/
|
1664
|
+
UNSIGNED32 ENTRYPOINT ads_reset( ADSHANDLE hStatement )
|
1665
|
+
{
|
1666
|
+
ADSHANDLE hCursor;
|
1667
|
+
|
1668
|
+
DBCLogTrace( "ads_reset" );
|
1669
|
+
|
1670
|
+
// Preparing the same query twice is a no-op in ACE.
|
1671
|
+
// All we need to do here is close any open cursor on the STMT.
|
1672
|
+
if ( hStatement == 0 )
|
1673
|
+
return DBCAPI_FAILURE;
|
1674
|
+
|
1675
|
+
if ( AdsStmtGetCursorHandle( hStatement, &hCursor ) != AE_SUCCESS )
|
1676
|
+
return DBCAPI_FAILURE;
|
1677
|
+
|
1678
|
+
if ( hCursor )
|
1679
|
+
AdsCloseTable( hCursor );
|
1680
|
+
|
1681
|
+
return DBCAPI_SUCCESS;
|
1682
|
+
|
1683
|
+
} /* ads_reset */
|
1684
|
+
|
1685
|
+
|
1686
|
+
/*******************************************************************************
|
1687
|
+
* Module : ads_rollback
|
1688
|
+
* Created : 11-04-2010 Peter F
|
1689
|
+
* Last Mod :
|
1690
|
+
* Return Value :
|
1691
|
+
* Desc : Rollback an active transaction
|
1692
|
+
* Notes :
|
1693
|
+
*******************************************************************************/
|
1694
|
+
UNSIGNED32 ENTRYPOINT ads_rollback( a_ads_connection *poConnect )
|
1695
|
+
{
|
1696
|
+
DBCLogTrace( "ads_rollback" );
|
1697
|
+
|
1698
|
+
if ( poConnect == NULL )
|
1699
|
+
return DBCAPI_FAILURE;
|
1700
|
+
|
1701
|
+
if ( AdsRollbackTransaction( poConnect->hConnect ) == AE_SUCCESS )
|
1702
|
+
return DBCAPI_SUCCESS;
|
1703
|
+
else
|
1704
|
+
return DBCAPI_FAILURE;
|
1705
|
+
|
1706
|
+
} /* ads_rollback */
|
1707
|
+
|
1708
|
+
|
1709
|
+
/*******************************************************************************
|
1710
|
+
* Module : ads_send_param_data
|
1711
|
+
* Created : 11-04-2010 Peter F
|
1712
|
+
* Last Mod :
|
1713
|
+
* Return Value :
|
1714
|
+
* Desc : Sends data as part of a bound parameter.
|
1715
|
+
* Notes : This method can be used to send a large amount of data for a bound parameter in chunks.
|
1716
|
+
*******************************************************************************/
|
1717
|
+
UNSIGNED32 ENTRYPOINT ads_send_param_data( ADSHANDLE hStatement, UNSIGNED32 ulIndex, UNSIGNED8 *pucBuffer, UNSIGNED32 ulLength )
|
1718
|
+
{
|
1719
|
+
DBCLogTrace( "ads_send_param_data" );
|
1720
|
+
|
1721
|
+
if ( hStatement == 0 )
|
1722
|
+
return DBCAPI_FAILURE;
|
1723
|
+
|
1724
|
+
if ( AdsSetBinary( hStatement, ADSFIELD( ulIndex + 1 ), ADS_BINARY, ulLength, 0, pucBuffer, ulLength ) == AE_SUCCESS )
|
1725
|
+
return DBCAPI_SUCCESS;
|
1726
|
+
else
|
1727
|
+
return DBCAPI_FAILURE;
|
1728
|
+
|
1729
|
+
} /* ads_send_param_data */
|
1730
|
+
|
1731
|
+
|
1732
|
+
/*******************************************************************************
|
1733
|
+
* Module : ads_sqlstate
|
1734
|
+
* Created : 11-04-2010 Peter F
|
1735
|
+
* Last Mod :
|
1736
|
+
* Return Value :
|
1737
|
+
* Desc : Return the 'sql state' of the last error
|
1738
|
+
* Notes :
|
1739
|
+
*******************************************************************************/
|
1740
|
+
UNSIGNED32 ENTRYPOINT ads_sqlstate( a_ads_connection *poConnect, UNSIGNED8 *pucBuffer, UNSIGNED32 ulLength )
|
1741
|
+
{
|
1742
|
+
UNSIGNED32 ulRetCode;
|
1743
|
+
UNSIGNED32 ulError;
|
1744
|
+
UNSIGNED8 aucError[ADS_MAX_ERROR_LEN+1];
|
1745
|
+
UNSIGNED16 usLen;
|
1746
|
+
|
1747
|
+
DBCLogTrace( "ads_sqlstate" );
|
1748
|
+
|
1749
|
+
usLen = sizeof( aucError );
|
1750
|
+
ulRetCode = AdsGetLastError( &ulError, aucError, &usLen );
|
1751
|
+
if ( ulRetCode != AE_SUCCESS )
|
1752
|
+
return DBCAPI_FAILURE;
|
1753
|
+
|
1754
|
+
if ( ulError == AE_SUCCESS )
|
1755
|
+
strncpy( (SIGNED8*)pucBuffer, "00000", ulLength );
|
1756
|
+
else
|
1757
|
+
{
|
1758
|
+
UNSIGNED8 *pcState;
|
1759
|
+
#define StateMarker "State = "
|
1760
|
+
|
1761
|
+
pcState = (UNSIGNED8*)strstr( (SIGNED8*)aucError, StateMarker );
|
1762
|
+
if ( pcState == NULL )
|
1763
|
+
strncpy( (SIGNED8*)pucBuffer, "00000", ulLength );
|
1764
|
+
else
|
1765
|
+
{
|
1766
|
+
pcState += strlen( StateMarker );
|
1767
|
+
|
1768
|
+
/* The state code is a 5 digit alphanumeric. NULL termintate it */
|
1769
|
+
*(pcState + 5) = 0;
|
1770
|
+
strncpy( (SIGNED8*)pucBuffer, (SIGNED8*)pcState, ulLength );
|
1771
|
+
}
|
1772
|
+
}
|
1773
|
+
|
1774
|
+
return DBCAPI_SUCCESS;
|
1775
|
+
|
1776
|
+
} /* ads_sqlstate */
|
1777
|
+
|
1778
|
+
|
1779
|
+
|
1780
|
+
#endif // ACE
|