advantage 0.1.0-x86-linux → 0.1.1-x86-linux

Sign up to get free protection for your applications and to get access to all the features.
Binary file
Binary file
@@ -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