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.
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