~ubuntu-branches/ubuntu/karmic/firebird2.1/karmic

« back to all changes in this revision

Viewing changes to src/dsql/utld.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Damyan Ivanov
  • Date: 2008-05-26 23:59:25 UTC
  • Revision ID: james.westby@ubuntu.com-20080526235925-2pnqj6nxpppoeaer
Tags: upstream-2.1.0.17798-0.ds2
ImportĀ upstreamĀ versionĀ 2.1.0.17798-0.ds2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *      PROGRAM:        Dynamic SQL runtime support
 
3
 *      MODULE:         utld.cpp
 
4
 *      DESCRIPTION:    Utility routines for DSQL
 
5
 *
 
6
 * The contents of this file are subject to the Interbase Public
 
7
 * License Version 1.0 (the "License"); you may not use this file
 
8
 * except in compliance with the License. You may obtain a copy
 
9
 * of the License at http://www.Inprise.com/IPL.html
 
10
 *
 
11
 * Software distributed under the License is distributed on an
 
12
 * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
 
13
 * or implied. See the License for the specific language governing
 
14
 * rights and limitations under the License.
 
15
 *
 
16
 * The Original Code was created by Inprise Corporation
 
17
 * and its predecessors. Portions created by Inprise Corporation are
 
18
 * Copyright (C) Inprise Corporation.
 
19
 *
 
20
 * All Rights Reserved.
 
21
 * Contributor(s): ______________________________________.
 
22
 *
 
23
 * 21 Nov 01 - Ann Harrison - Turn off the code in parse_sqlda that 
 
24
 *    decides that two statements are the same based on their message
 
25
 *    descriptions because it misleads some code in remote/interface.c
 
26
 *    and causes problems when two statements are prepared.
 
27
 *
 
28
 * 2002.10.29 Sean Leyne - Removed obsolete "Netware" port
 
29
 *
 
30
 */
 
31
 
 
32
 
 
33
#include "firebird.h"
 
34
#include <stdio.h>
 
35
#include <string.h>
 
36
#include "../dsql/dsql.h"
 
37
#include "../dsql/sqlda.h"
 
38
#include "../jrd/ibase.h"
 
39
#include "../jrd/align.h"
 
40
#include "../jrd/constants.h"
 
41
#include "../dsql/utld_proto.h"
 
42
#include "../jrd/gds_proto.h"
 
43
 
 
44
#if !defined(REQUESTER) && !defined(SUPERCLIENT)
 
45
#include "../dsql/metd_proto.h"
 
46
#endif
 
47
 
 
48
 
 
49
static void cleanup(void *);
 
50
static ISC_STATUS error_dsql_804(ISC_STATUS *, ISC_STATUS);
 
51
static SLONG get_numeric_info(const SCHAR**);
 
52
static SLONG get_string_info(const SCHAR**, SCHAR*, int);
 
53
#ifdef NOT_USED_OR_REPLACED
 
54
#ifdef DEV_BUILD
 
55
static void print_xsqlda(XSQLDA *);
 
56
#endif
 
57
#endif
 
58
static void sqlvar_to_xsqlvar(const SQLVAR*, XSQLVAR*);
 
59
static void xsqlvar_to_sqlvar(const XSQLVAR*, SQLVAR*);
 
60
 
 
61
static inline void ch_stuff(BLOB_PTR*& p, const SCHAR value, bool& same_flag)
 
62
{
 
63
        if (*p == value) 
 
64
                p++; 
 
65
        else {
 
66
                *p++ = value;
 
67
                same_flag = false;
 
68
        }
 
69
}
 
70
 
 
71
static inline void ch_stuff_word(BLOB_PTR*& p, const SSHORT value, bool& same_flag)
 
72
{
 
73
        ch_stuff(p, value & 255, same_flag);
 
74
        ch_stuff(p, value >> 8, same_flag);
 
75
}
 
76
 
 
77
/* these statics define a round-robin data area for storing
 
78
   textual error messages returned to the user */
 
79
 
 
80
static TEXT *DSQL_failures, *DSQL_failures_ptr;
 
81
 
 
82
const int  DSQL_FAILURE_SPACE = 2048;
 
83
 
 
84
/**
 
85
        Parse response on isc_info_sql_select or isc_info_sql_bind 
 
86
        request. Return pointer to the next byte after successfully
 
87
        parsed info or NULL if error is encountered or info is truncated
 
88
**/
 
89
SCHAR* UTLD_skip_sql_info(SCHAR* info)
 
90
{
 
91
        if (*info != isc_info_sql_select &&
 
92
                *info != isc_info_sql_bind)
 
93
        {
 
94
                return 0;
 
95
        }
 
96
 
 
97
        info++;
 
98
 
 
99
        if (*info++ != isc_info_sql_describe_vars)
 
100
                return 0;
 
101
 
 
102
        get_numeric_info((const SCHAR**) &info);
 
103
 
 
104
        // Loop over the variables being described
 
105
        while (true)
 
106
        {
 
107
                SCHAR str[256]; // must be big enough to hold metadata name
 
108
                SCHAR item = *info++;
 
109
 
 
110
                switch (item)
 
111
                {
 
112
                case isc_info_end:
 
113
                        return info;
 
114
 
 
115
                case isc_info_truncated:
 
116
                        return 0;
 
117
 
 
118
                case isc_info_sql_select:
 
119
                case isc_info_sql_bind:
 
120
                        return --info;
 
121
 
 
122
                case isc_info_sql_describe_end:
 
123
                        break;
 
124
 
 
125
                case isc_info_sql_sqlda_seq:
 
126
                case isc_info_sql_type:
 
127
                case isc_info_sql_sub_type:
 
128
                case isc_info_sql_scale:
 
129
                case isc_info_sql_length:
 
130
                        get_numeric_info((const SCHAR**) &info);
 
131
                        break;
 
132
 
 
133
                case isc_info_sql_field:
 
134
                case isc_info_sql_relation:
 
135
                case isc_info_sql_owner:
 
136
                case isc_info_sql_alias:
 
137
                        get_string_info((const SCHAR**) &info, str, sizeof(str));
 
138
                        break;
 
139
 
 
140
                default:
 
141
                        return 0;
 
142
                }
 
143
        }
 
144
 
 
145
        return 0;
 
146
}
 
147
 
 
148
 
 
149
/**
 
150
 
 
151
        UTLD_char_length_to_byte_length
 
152
        
 
153
        @brief  Return max byte length necessary for a specified character length string
 
154
        
 
155
        @param lengthInChars
 
156
        @param maxBytesPerChar
 
157
        
 
158
**/
 
159
USHORT UTLD_char_length_to_byte_length(USHORT lengthInChars, USHORT maxBytesPerChar)
 
160
{
 
161
        return MIN((MAX_COLUMN_SIZE - sizeof(USHORT)) / maxBytesPerChar * maxBytesPerChar,
 
162
                           lengthInChars * maxBytesPerChar);
 
163
}
 
164
 
 
165
 
 
166
ISC_STATUS UTLD_copy_status(const ISC_STATUS* from, ISC_STATUS* to)
 
167
{
 
168
/**************************************
 
169
 *
 
170
 *      c o p y _ s t a t u s
 
171
 *
 
172
 **************************************
 
173
 *
 
174
 * Functional description
 
175
 *      Copy a status vector.
 
176
 *
 
177
 **************************************/
 
178
        const ISC_STATUS status = from[1];
 
179
 
 
180
        const ISC_STATUS* const end = from + ISC_STATUS_LENGTH;
 
181
        while (from < end)
 
182
                *to++ = *from++;
 
183
 
 
184
        return status;
 
185
}
 
186
 
 
187
 
 
188
/**
 
189
  
 
190
        UTLD_parse_sql_info
 
191
  
 
192
    @brief      Fill in an SQLDA using data returned
 
193
        by a call to isc_dsql_sql_info.
 
194
 
 
195
 
 
196
    @param status
 
197
    @param dialect
 
198
    @param info
 
199
    @param xsqlda
 
200
    @param return_index
 
201
 
 
202
 **/
 
203
ISC_STATUS      UTLD_parse_sql_info(
 
204
                                ISC_STATUS* status,
 
205
                                USHORT dialect,
 
206
                                const SCHAR* info,
 
207
                                XSQLDA* xsqlda,
 
208
                                USHORT* return_index)
 
209
{
 
210
        XSQLVAR *xvar, xsqlvar;
 
211
        SQLDA* sqlda;
 
212
        SQLVAR* qvar;
 
213
        USHORT last_index = 0;
 
214
 
 
215
        if (return_index)
 
216
                *return_index = 0;
 
217
 
 
218
        if (!xsqlda)
 
219
                return 0;
 
220
 
 
221
/* The first byte of the returned buffer is assumed to be either a
 
222
   isc_info_sql_select or isc_info_sql_bind item.  The second byte
 
223
   is assumed to be isc_info_sql_describe_vars. */
 
224
 
 
225
        info += 2;
 
226
 
 
227
        const SSHORT n = static_cast<SSHORT>(get_numeric_info(&info));
 
228
        if (dialect >= DIALECT_xsqlda)
 
229
        {
 
230
                if (xsqlda->version != SQLDA_VERSION1)
 
231
                        return error_dsql_804(status, isc_dsql_sqlda_err);
 
232
                xsqlda->sqld = n;
 
233
 
 
234
                // If necessary, inform the application that more sqlda items are needed 
 
235
                if (xsqlda->sqld > xsqlda->sqln)
 
236
                        return 0;
 
237
        }
 
238
        else
 
239
        {
 
240
                sqlda = (SQLDA *) xsqlda;
 
241
                sqlda->sqld = n;
 
242
 
 
243
                // If necessary, inform the application that more sqlda items are needed 
 
244
                if (sqlda->sqld > sqlda->sqln)
 
245
                        return 0;
 
246
 
 
247
                xsqlda = NULL;
 
248
                xvar = &xsqlvar;
 
249
        }
 
250
 
 
251
// Loop over the variables being described.
 
252
 
 
253
        USHORT index = 0;
 
254
        while (*info != isc_info_end)
 
255
        {
 
256
           SCHAR item;
 
257
           while ((item = *info++) != isc_info_sql_describe_end)
 
258
                        switch (item)
 
259
                        {
 
260
                        case isc_info_sql_sqlda_seq:
 
261
                                index = static_cast<USHORT>(get_numeric_info(&info));
 
262
                                if (xsqlda)
 
263
                                        xvar = xsqlda->sqlvar + index - 1;
 
264
                                else
 
265
                                {
 
266
                                        qvar = sqlda->sqlvar + index - 1;
 
267
                                        memset(xvar, 0, sizeof(XSQLVAR));
 
268
                                }
 
269
                                break;
 
270
 
 
271
                        case isc_info_sql_type:
 
272
                                xvar->sqltype =
 
273
                                        static_cast<SSHORT>(get_numeric_info(&info));
 
274
                                break;
 
275
 
 
276
                        case isc_info_sql_sub_type:
 
277
                                xvar->sqlsubtype =
 
278
                                        static_cast<SSHORT>(get_numeric_info(&info));
 
279
                                break;
 
280
 
 
281
                        case isc_info_sql_scale:
 
282
                                xvar->sqlscale =
 
283
                                        static_cast<SSHORT>(get_numeric_info(&info));
 
284
                                break;
 
285
 
 
286
                        case isc_info_sql_length:
 
287
                                xvar->sqllen =
 
288
                                        static_cast<SSHORT>(get_numeric_info(&info));
 
289
                                break;
 
290
 
 
291
                        case isc_info_sql_field:
 
292
                                xvar->sqlname_length =
 
293
                                        static_cast<SSHORT>(get_string_info(&info, xvar->sqlname, sizeof(xvar->sqlname)));
 
294
                                break;
 
295
 
 
296
                        case isc_info_sql_relation:
 
297
                                xvar->relname_length =
 
298
                                        static_cast<SSHORT>(get_string_info(&info, xvar->relname, sizeof(xvar->relname)));
 
299
                                break;
 
300
 
 
301
                        case isc_info_sql_owner:
 
302
                                xvar->ownname_length =
 
303
                                        static_cast<SSHORT>(get_string_info(&info, xvar->ownname, sizeof(xvar->ownname)));
 
304
                                break;
 
305
 
 
306
                        case isc_info_sql_alias:
 
307
                                xvar->aliasname_length =
 
308
                                        static_cast<SSHORT>
 
309
                                        (get_string_info
 
310
                                         (&info, xvar->aliasname, sizeof(xvar->aliasname)));
 
311
                                break;
 
312
 
 
313
                        case isc_info_truncated:
 
314
                                if (return_index)
 
315
                                        *return_index = last_index;
 
316
 
 
317
                        default:
 
318
                                return error_dsql_804(status, isc_dsql_sqlda_err);
 
319
                        }
 
320
 
 
321
                if (!xsqlda)
 
322
                        xsqlvar_to_sqlvar(xvar, qvar);
 
323
 
 
324
                if (index > last_index)
 
325
                        last_index = index;
 
326
        }
 
327
 
 
328
        if (*info != isc_info_end)
 
329
                return error_dsql_804(status, isc_dsql_sqlda_err);
 
330
 
 
331
        return FB_SUCCESS;
 
332
}
 
333
 
 
334
 
 
335
/**
 
336
  
 
337
        UTLD_parse_sqlda
 
338
  
 
339
    @brief      This routine creates a blr message that describes
 
340
        a SQLDA as well as moving data from the SQLDA
 
341
        into a message buffer or from the message buffer
 
342
        into the SQLDA.
 
343
 
 
344
 
 
345
    @param status
 
346
    @param dasup
 
347
    @param blr_length
 
348
    @param msg_type
 
349
    @param msg_length
 
350
    @param dialect
 
351
    @param xsqlda
 
352
    @param clause
 
353
 
 
354
 **/
 
355
ISC_STATUS      UTLD_parse_sqlda(
 
356
                                ISC_STATUS* status,
 
357
                                sqlda_sup* const dasup,
 
358
                                USHORT* blr_length,
 
359
                                USHORT* msg_type,
 
360
                                USHORT* msg_length,
 
361
                                USHORT dialect,
 
362
                                XSQLDA* xsqlda,
 
363
                                const USHORT clause)
 
364
{
 
365
        USHORT n;
 
366
        XSQLVAR *xvar, xsqlvar;
 
367
        SQLDA* sqlda;
 
368
        SQLVAR* qvar;
 
369
 
 
370
        if (!xsqlda)
 
371
                n = 0;
 
372
        else
 
373
                if (dialect >= DIALECT_xsqlda)
 
374
                {
 
375
                        if (xsqlda->version != SQLDA_VERSION1)
 
376
                                return error_dsql_804(status, isc_dsql_sqlda_err);
 
377
                        n = xsqlda->sqld;
 
378
                }
 
379
                else
 
380
                {
 
381
                        sqlda = (SQLDA *) xsqlda;
 
382
                        n = sqlda->sqld;
 
383
                        xsqlda = NULL;
 
384
                        xvar = &xsqlvar;
 
385
                }
 
386
 
 
387
 
 
388
        sqlda_sup::dasup_clause* const pClause = &dasup->dasup_clauses[clause];
 
389
 
 
390
        if (!n)
 
391
        {
 
392
                // If there isn't an SQLDA, don't bother with anything else. 
 
393
 
 
394
                if (blr_length)
 
395
                        *blr_length = pClause->dasup_blr_length = 0;
 
396
                if (msg_length)
 
397
                        *msg_length = 0;
 
398
                if (msg_type)
 
399
                        *msg_type = 0;
 
400
                return 0;
 
401
        }
 
402
 
 
403
        USHORT i;
 
404
 
 
405
        if (msg_length)
 
406
        {
 
407
                /* This is a call from execute or open, or the first call from fetch.
 
408
                   Determine the size of the blr, allocate a blr buffer, create the
 
409
                   blr, and finally allocate a message buffer. */
 
410
 
 
411
                /* The message buffer we are describing could be for a message to
 
412
                   either IB 4.0 or IB 3.3 - thus we need to describe the buffer
 
413
                   with the right set of blr.
 
414
                   As the BLR is only used to describe space allocation and alignment,
 
415
                   we can safely use blr_text for both 4.0 and 3.3. */
 
416
 
 
417
                /* Make a quick pass through the SQLDA to determine the amount of
 
418
                   blr that will be generated. */
 
419
 
 
420
                USHORT blr_len = 8;
 
421
                USHORT par_count = 0;
 
422
                if (xsqlda)
 
423
                        xvar = xsqlda->sqlvar - 1;
 
424
                else
 
425
                        qvar = sqlda->sqlvar - 1;
 
426
                for (i = 0; i < n; i++)
 
427
                {
 
428
                        if (xsqlda)
 
429
                                xvar++;
 
430
                        else {
 
431
                                qvar++;
 
432
                                sqlvar_to_xsqlvar(qvar, xvar);
 
433
                        }
 
434
                        const USHORT dtype = xvar->sqltype & ~1;
 
435
                        if (dtype == SQL_VARYING || dtype == SQL_TEXT)
 
436
                                blr_len += 3;
 
437
                        else
 
438
                                if (dtype == SQL_SHORT ||
 
439
                                        dtype == SQL_LONG ||
 
440
                                        dtype == SQL_INT64 ||
 
441
                                        dtype == SQL_QUAD ||
 
442
                                        dtype == SQL_BLOB
 
443
                                        || dtype == SQL_ARRAY)
 
444
                                {
 
445
                                        blr_len += 2;
 
446
                                }
 
447
                                else
 
448
                                        blr_len++;
 
449
                        blr_len += 2;
 
450
                        par_count += 2;
 
451
                }
 
452
 
 
453
                /* Make sure the blr buffer is large enough.  If it isn't, allocate
 
454
                   a new one. */
 
455
 
 
456
                if (blr_len > pClause->dasup_blr_buf_len)
 
457
                {
 
458
                        if (pClause->dasup_blr) {
 
459
                                gds__free(pClause->dasup_blr);
 
460
                        }
 
461
                        pClause->dasup_blr =
 
462
                                reinterpret_cast<char*>(gds__alloc((SLONG) blr_len));
 
463
                        // FREE: unknown
 
464
                        if (!pClause->dasup_blr)        // NOMEM:
 
465
                                return error_dsql_804(status, isc_virmemexh);
 
466
                        pClause->dasup_blr_buf_len = blr_len;
 
467
                        pClause->dasup_blr_length = 0;
 
468
                }
 
469
                memset(pClause->dasup_blr, 0, blr_len);
 
470
 
 
471
                bool same_flag = (blr_len == pClause->dasup_blr_length);
 
472
 
 
473
                /* turn off same_flag because it breaks execute & execute2 when
 
474
                   more than one statement is prepared */
 
475
 
 
476
                same_flag = false;
 
477
 
 
478
                pClause->dasup_blr_length = blr_len;
 
479
 
 
480
                /* Generate the blr for the message and at the same time, determine
 
481
                   the size of the message buffer.  Allow for a null indicator with
 
482
                   each variable in the SQLDA. */
 
483
 
 
484
                // one huge pointer per line for LIBS
 
485
                BLOB_PTR* p = reinterpret_cast<UCHAR*>(pClause->dasup_blr);
 
486
 
 
487
        /** The define SQL_DIALECT_V5 is not available here, Hence using
 
488
        constant 1.
 
489
        **/
 
490
                if (dialect > 1) {
 
491
                        ch_stuff(p, blr_version5, same_flag);
 
492
                }
 
493
                else {
 
494
                        ch_stuff(p, blr_version4, same_flag);
 
495
                }
 
496
                //else if ((SCHAR) *(p) == (SCHAR) (blr_version4)) {
 
497
                //      (p)++; 
 
498
                //}
 
499
                //else {
 
500
                //      *(p)++ = (blr_version4); 
 
501
                //      same_flag = false;
 
502
                //}
 
503
 
 
504
                ch_stuff(p, blr_begin, same_flag);
 
505
                ch_stuff(p, blr_message, same_flag);
 
506
                ch_stuff(p, 0, same_flag);
 
507
                ch_stuff_word(p, par_count, same_flag);
 
508
                USHORT msg_len = 0;
 
509
                if (xsqlda)
 
510
                        xvar = xsqlda->sqlvar - 1;
 
511
                else
 
512
                        qvar = sqlda->sqlvar - 1;
 
513
                for (i = 0; i < n; i++)
 
514
                {
 
515
                        if (xsqlda)
 
516
                                xvar++;
 
517
                        else
 
518
                        {
 
519
                                qvar++;
 
520
                                sqlvar_to_xsqlvar(qvar, xvar);
 
521
                        }
 
522
                        USHORT dtype = xvar->sqltype & ~1;
 
523
                        USHORT len = xvar->sqllen;
 
524
                        switch (dtype)
 
525
                        {
 
526
                        case SQL_VARYING:
 
527
                                ch_stuff(p, blr_varying, same_flag);
 
528
                                ch_stuff_word(p, len, same_flag);
 
529
                                dtype = dtype_varying;
 
530
                                len += sizeof(USHORT);
 
531
                                break;
 
532
                        case SQL_TEXT:
 
533
                                ch_stuff(p, blr_text, same_flag);
 
534
                                ch_stuff_word(p, len, same_flag);
 
535
                                dtype = dtype_text;
 
536
                                break;
 
537
                        case SQL_DOUBLE:
 
538
                                ch_stuff(p, blr_double, same_flag);
 
539
                                dtype = dtype_double;
 
540
                                break;
 
541
                        case SQL_FLOAT:
 
542
                                ch_stuff(p, blr_float, same_flag);
 
543
                                dtype = dtype_real;
 
544
                                break;
 
545
                        case SQL_D_FLOAT:
 
546
                                ch_stuff(p, blr_d_float, same_flag);
 
547
                                dtype = dtype_d_float;
 
548
                                break;
 
549
                        case SQL_TYPE_DATE:
 
550
                                ch_stuff(p, blr_sql_date, same_flag);
 
551
                                dtype = dtype_sql_date;
 
552
                                break;
 
553
                        case SQL_TYPE_TIME:
 
554
                                ch_stuff(p, blr_sql_time, same_flag);
 
555
                                dtype = dtype_sql_time;
 
556
                                break;
 
557
                        case SQL_TIMESTAMP:
 
558
                                ch_stuff(p, blr_timestamp, same_flag);
 
559
                                dtype = dtype_timestamp;
 
560
                                break;
 
561
                        case SQL_BLOB:
 
562
                                ch_stuff(p, blr_quad, same_flag);
 
563
                                ch_stuff(p, 0, same_flag);
 
564
                                dtype = dtype_blob;
 
565
                                break;
 
566
                        case SQL_ARRAY:
 
567
                                ch_stuff(p, blr_quad, same_flag);
 
568
                                ch_stuff(p, 0, same_flag);
 
569
                                dtype = dtype_array;
 
570
                                break;
 
571
                        case SQL_LONG:
 
572
                                ch_stuff(p, blr_long, same_flag);
 
573
                                ch_stuff(p, xvar->sqlscale, same_flag);
 
574
                                dtype = dtype_long;
 
575
                                break;
 
576
                        case SQL_SHORT:
 
577
                                ch_stuff(p, blr_short, same_flag);
 
578
                                ch_stuff(p, xvar->sqlscale, same_flag);
 
579
                                dtype = dtype_short;
 
580
                                break;
 
581
                        case SQL_INT64:
 
582
                                ch_stuff(p, blr_int64, same_flag);
 
583
                                ch_stuff(p, xvar->sqlscale, same_flag);
 
584
                                dtype = dtype_int64;
 
585
                                break;
 
586
                        case SQL_QUAD:
 
587
                                ch_stuff(p, blr_quad, same_flag);
 
588
                                ch_stuff(p, xvar->sqlscale, same_flag);
 
589
                                dtype = dtype_quad;
 
590
                                break;
 
591
                        default:
 
592
                                return error_dsql_804(status, isc_dsql_sqlda_value_err);
 
593
                        }
 
594
 
 
595
                        ch_stuff(p, blr_short, same_flag);
 
596
                        ch_stuff(p, 0, same_flag);
 
597
 
 
598
                        USHORT align = type_alignments[dtype];
 
599
                        if (align)
 
600
                                msg_len = FB_ALIGN(msg_len, align);
 
601
                        msg_len += len;
 
602
                        align = type_alignments[dtype_short];
 
603
                        if (align)
 
604
                                msg_len = FB_ALIGN(msg_len, align);
 
605
                        msg_len += sizeof(SSHORT);
 
606
                }
 
607
 
 
608
                ch_stuff(p, blr_end, same_flag);
 
609
                ch_stuff(p, blr_eoc, same_flag);
 
610
 
 
611
                /* Make sure the message buffer is large enough.  If it isn't, allocate
 
612
                   a new one. */
 
613
 
 
614
                if (msg_len > pClause->dasup_msg_buf_len)
 
615
                {
 
616
                        if (pClause->dasup_msg)
 
617
                                gds__free(pClause->dasup_msg);
 
618
                        pClause->dasup_msg =
 
619
                                reinterpret_cast<char*>(gds__alloc((SLONG) msg_len));
 
620
                        // FREE: unknown
 
621
                        if (!pClause->dasup_msg)        // NOMEM:
 
622
                                return error_dsql_804(status, isc_virmemexh);
 
623
                        pClause->dasup_msg_buf_len = msg_len;
 
624
                }
 
625
                memset(pClause->dasup_msg, 0, msg_len);
 
626
 
 
627
                // Fill in the return values to the caller.
 
628
 
 
629
                *blr_length = (same_flag) ? 0 : blr_len;
 
630
                *msg_length = msg_len;
 
631
                *msg_type = 0;
 
632
 
 
633
                // If this is the first call from fetch, we're done.
 
634
 
 
635
                if (clause == DASUP_CLAUSE_select)
 
636
                        return 0;
 
637
        }
 
638
 
 
639
// Move the data between the SQLDA and the message buffer.
 
640
 
 
641
        USHORT offset = 0;
 
642
        // one huge pointer per line for LIBS
 
643
        BLOB_PTR* msg_buf =
 
644
                reinterpret_cast<UCHAR*>(pClause->dasup_msg);
 
645
        if (xsqlda)
 
646
                xvar = xsqlda->sqlvar - 1;
 
647
        else
 
648
                qvar = sqlda->sqlvar - 1;
 
649
        for (i = 0; i < n; i++)
 
650
        {
 
651
                if (xsqlda)
 
652
                        xvar++;
 
653
                else
 
654
                {
 
655
                        qvar++;
 
656
                        sqlvar_to_xsqlvar(qvar, xvar);
 
657
                }
 
658
                USHORT dtype = xvar->sqltype & ~1;
 
659
                USHORT len = xvar->sqllen;
 
660
                switch (dtype)
 
661
                {
 
662
                case SQL_VARYING:
 
663
                        dtype = dtype_varying;
 
664
                        len += sizeof(USHORT);
 
665
                        break;
 
666
                case SQL_TEXT:
 
667
                        dtype = dtype_text;
 
668
                        break;
 
669
                case SQL_DOUBLE:
 
670
                        dtype = dtype_double;
 
671
                        break;
 
672
                case SQL_FLOAT:
 
673
                        dtype = dtype_real;
 
674
                        break;
 
675
                case SQL_D_FLOAT:
 
676
                        dtype = dtype_d_float;
 
677
                        break;
 
678
                case SQL_TYPE_DATE:
 
679
                        dtype = dtype_sql_date;
 
680
                        break;
 
681
                case SQL_TYPE_TIME:
 
682
                        dtype = dtype_sql_time;
 
683
                        break;
 
684
                case SQL_TIMESTAMP:
 
685
                        dtype = dtype_timestamp;
 
686
                        break;
 
687
                case SQL_BLOB:
 
688
                        dtype = dtype_blob;
 
689
                        break;
 
690
                case SQL_ARRAY:
 
691
                        dtype = dtype_array;
 
692
                        break;
 
693
                case SQL_LONG:
 
694
                        dtype = dtype_long;
 
695
                        break;
 
696
                case SQL_SHORT:
 
697
                        dtype = dtype_short;
 
698
                        break;
 
699
                case SQL_INT64:
 
700
                        dtype = dtype_int64;
 
701
                        break;
 
702
                case SQL_QUAD:
 
703
                        dtype = dtype_quad;
 
704
                }
 
705
 
 
706
                USHORT align = type_alignments[dtype];
 
707
                if (align)
 
708
                        offset = FB_ALIGN(offset, align);
 
709
                USHORT null_offset = offset + len;
 
710
 
 
711
                align = type_alignments[dtype_short];
 
712
                if (align)
 
713
                        null_offset = FB_ALIGN(null_offset, align);
 
714
 
 
715
                SSHORT *null_ind = (SSHORT *) (msg_buf + null_offset);
 
716
                if (clause == DASUP_CLAUSE_select)
 
717
                {
 
718
                        // Move data from the message into the SQLDA. 
 
719
 
 
720
                        // Make sure user has specified a data location 
 
721
                        if (!xvar->sqldata)
 
722
                                return error_dsql_804(status, isc_dsql_sqlda_value_err);
 
723
 
 
724
                        memcpy(xvar->sqldata, msg_buf + offset, len);
 
725
                        if (xvar->sqltype & 1)
 
726
                        {
 
727
                                // Make sure user has specified a location for null indicator 
 
728
                                if (!xvar->sqlind)
 
729
                                        return error_dsql_804(status, isc_dsql_sqlda_value_err);
 
730
                                *xvar->sqlind = *null_ind;
 
731
                        }
 
732
                }
 
733
                else
 
734
                {
 
735
                        /* Move data from the SQLDA into the message.  If the
 
736
                           indicator variable identifies a null value, permit
 
737
                           the data value to be missing. */
 
738
 
 
739
                        if (xvar->sqltype & 1)
 
740
                        {
 
741
                                // Make sure user has specified a location for null indicator 
 
742
                                if (!xvar->sqlind)
 
743
                                        return error_dsql_804(status, isc_dsql_sqlda_value_err);
 
744
                                *null_ind = *xvar->sqlind;
 
745
                        }
 
746
                        else
 
747
                                *null_ind = 0;
 
748
 
 
749
                        // Make sure user has specified a data location (unless NULL) 
 
750
                        if (!xvar->sqldata && !*null_ind)
 
751
                                return error_dsql_804(status, isc_dsql_sqlda_value_err);
 
752
 
 
753
                        // Copy data - unless known to be NULL 
 
754
                        if ((offset + len) > pClause->dasup_msg_buf_len)
 
755
                                return error_dsql_804(status, isc_dsql_sqlda_value_err);
 
756
 
 
757
                        if (!*null_ind)
 
758
                                memcpy(msg_buf + offset, xvar->sqldata, len);
 
759
                }
 
760
 
 
761
                offset = null_offset + sizeof(SSHORT);
 
762
        }
 
763
 
 
764
        return 0;
 
765
}
 
766
 
 
767
 
 
768
/**
 
769
  
 
770
        UTLD_save_status_strings
 
771
  
 
772
    @brief      Strings in status vectors may be stored in stack variables
 
773
        or memory pools that are transient.  To perserve the information,
 
774
        copy any included strings to a special buffer.
 
775
 
 
776
 
 
777
    @param vector
 
778
 
 
779
 **/
 
780
void    UTLD_save_status_strings(ISC_STATUS* vector)
 
781
{
 
782
// allocate space for failure strings if it hasn't already been allocated
 
783
 
 
784
        if (!DSQL_failures)
 
785
        {
 
786
                DSQL_failures = (TEXT *) ALLOC_LIB_MEMORY((SLONG) DSQL_FAILURE_SPACE);
 
787
                // FREE: by exit handler cleanup() 
 
788
                if (!DSQL_failures)             // NOMEM: don't try to copy the strings 
 
789
                        return;
 
790
                DSQL_failures_ptr = DSQL_failures;
 
791
                gds__register_cleanup(cleanup, 0);
 
792
 
 
793
#ifdef DEBUG_GDS_ALLOC
 
794
                gds_alloc_flag_unfreed((void *) DSQL_failures);
 
795
#endif
 
796
        }
 
797
 
 
798
        while (*vector)
 
799
        {
 
800
                const TEXT* p;
 
801
                USHORT l;
 
802
                const ISC_STATUS status = *vector++;
 
803
                switch (status)
 
804
                {
 
805
                case isc_arg_cstring:
 
806
                        l = static_cast<USHORT>(*vector++);
 
807
 
 
808
                case isc_arg_interpreted:
 
809
                case isc_arg_string:
 
810
                        p = (TEXT *) * vector;
 
811
                        if (status != isc_arg_cstring)
 
812
                                l = strlen(p) + 1;
 
813
 
 
814
                        /* If there isn't any more room in the buffer,
 
815
                           start at the beginning again */
 
816
 
 
817
                        if (DSQL_failures_ptr + l > DSQL_failures + DSQL_FAILURE_SPACE)
 
818
                                DSQL_failures_ptr = DSQL_failures;
 
819
                        *vector++ = (ISC_STATUS) DSQL_failures_ptr;
 
820
                        if (l)
 
821
                                do
 
822
                                        *DSQL_failures_ptr++ = *p++;
 
823
                                while (--l && (DSQL_failures_ptr < DSQL_failures + DSQL_FAILURE_SPACE));
 
824
                        if (l)
 
825
                                *(DSQL_failures_ptr - 1) = '\0';
 
826
                        break;
 
827
 
 
828
                default:
 
829
                        ++vector;
 
830
                        break;
 
831
                }
 
832
        }
 
833
}
 
834
 
 
835
 
 
836
/**
 
837
  
 
838
        cleanup
 
839
  
 
840
    @brief      Exit handler to cleanup dynamically allocated memory.
 
841
 
 
842
 
 
843
    @param arg
 
844
 
 
845
 **/
 
846
static void cleanup( void *arg)
 
847
{
 
848
 
 
849
        if (DSQL_failures)
 
850
                FREE_LIB_MEMORY(DSQL_failures);
 
851
 
 
852
        gds__unregister_cleanup(cleanup, 0);
 
853
        DSQL_failures = NULL;
 
854
}
 
855
 
 
856
 
 
857
/**
 
858
  
 
859
        error_dsql_804
 
860
  
 
861
    @brief      Move a DSQL -804 error message into a status vector.
 
862
 
 
863
 
 
864
    @param status
 
865
    @param err
 
866
 
 
867
 **/
 
868
static ISC_STATUS error_dsql_804( ISC_STATUS * status, ISC_STATUS err)
 
869
{
 
870
        ISC_STATUS *p = status;
 
871
 
 
872
        *p++ = isc_arg_gds;
 
873
        *p++ = isc_dsql_error;
 
874
        *p++ = isc_arg_gds;
 
875
        *p++ = isc_sqlerr;
 
876
        *p++ = isc_arg_number;
 
877
        *p++ = -804;
 
878
        *p++ = isc_arg_gds;
 
879
        *p++ = (err);
 
880
        *p = isc_arg_end;
 
881
 
 
882
        return status[1];
 
883
}
 
884
 
 
885
 
 
886
/**
 
887
  
 
888
        get_numeric_info
 
889
  
 
890
    @brief      Pick up a VAX format numeric info item
 
891
        with a 2 byte length.
 
892
 
 
893
 
 
894
    @param ptr
 
895
 
 
896
 **/
 
897
static SLONG get_numeric_info( const SCHAR** ptr)
 
898
{
 
899
        const SSHORT l =
 
900
                static_cast<SSHORT>(gds__vax_integer(reinterpret_cast<const UCHAR*>(*ptr), 2));
 
901
        *ptr += 2;
 
902
        int item = gds__vax_integer(reinterpret_cast<const UCHAR*>(*ptr), l);
 
903
        *ptr += l;
 
904
 
 
905
        return item;
 
906
}
 
907
 
 
908
 
 
909
/**
 
910
  
 
911
        get_string_info
 
912
  
 
913
    @brief      Pick up a string valued info item and return
 
914
        its length.  The buffer_len argument is assumed
 
915
        to include space for the terminating null.
 
916
 
 
917
 
 
918
    @param ptr
 
919
    @param buffer
 
920
    @param buffer_len
 
921
 
 
922
 **/
 
923
static SLONG get_string_info( const SCHAR** ptr, SCHAR * buffer, int buffer_len)
 
924
{
 
925
        const SCHAR* p = *ptr;
 
926
        SSHORT l =
 
927
                static_cast<SSHORT>(gds__vax_integer(reinterpret_cast<const UCHAR*>(p), 2));
 
928
        *ptr += l + 2;
 
929
        p += 2;
 
930
 
 
931
        if (l >= buffer_len)
 
932
                l = buffer_len - 1;
 
933
 
 
934
        SSHORT len = l;
 
935
        if (len)
 
936
                do
 
937
                        *buffer++ = *p++;
 
938
                while (--l);
 
939
        *buffer = 0;
 
940
 
 
941
        return len;
 
942
}
 
943
 
 
944
#ifdef NOT_USED_OR_REPLACED
 
945
#ifdef DEV_BUILD
 
946
static void print_xsqlda( XSQLDA * xsqlda)
 
947
{
 
948
/*****************************************
 
949
 *
 
950
 *      p r i n t _ x s q l d a 
 
951
 *
 
952
 *****************************************
 
953
 *
 
954
 * print an sqlda
 
955
 *
 
956
 *****************************************/
 
957
        XSQLVAR *xvar, *end_var;
 
958
 
 
959
        if (!xsqlda)
 
960
                return;
 
961
 
 
962
        printf("SQLDA Version %d\n", xsqlda->version);
 
963
        printf("      sqldaid %.8s\n", xsqlda->sqldaid);
 
964
        printf("      sqldabc %d\n", xsqlda->sqldabc);
 
965
        printf("      sqln    %d\n", xsqlda->sqln);
 
966
        printf("      sqld    %d\n", xsqlda->sqld);
 
967
 
 
968
        xvar = xsqlda->sqlvar;
 
969
        for (end_var = xvar + xsqlda->sqld; xvar < end_var; xvar++)
 
970
                printf("         %.31s %.31s type: %d, scale %d, len %d subtype %d\n",
 
971
                           xvar->sqlname, xvar->relname, xvar->sqltype,
 
972
                           xvar->sqlscale, xvar->sqllen, xvar->sqlsubtype);
 
973
}
 
974
#endif
 
975
#endif
 
976
 
 
977
/**
 
978
  
 
979
        sqlvar_to_xsqlvar
 
980
  
 
981
 
 
982
    @param sqlvar
 
983
    @param xsqlvar
 
984
 
 
985
 
 
986
    @param sqlvar
 
987
    @param xsqlvar
 
988
 
 
989
 **/
 
990
static void sqlvar_to_xsqlvar(const SQLVAR* sqlvar, XSQLVAR* xsqlvar)
 
991
{
 
992
 
 
993
        xsqlvar->sqltype = sqlvar->sqltype;
 
994
        xsqlvar->sqldata = sqlvar->sqldata;
 
995
        xsqlvar->sqlind = sqlvar->sqlind;
 
996
 
 
997
        xsqlvar->sqlsubtype = 0;
 
998
        xsqlvar->sqlscale = 0;
 
999
        xsqlvar->sqllen = sqlvar->sqllen;
 
1000
        switch (xsqlvar->sqltype & ~1)
 
1001
        {
 
1002
        case SQL_LONG:
 
1003
                xsqlvar->sqlscale = xsqlvar->sqllen >> 8;
 
1004
                xsqlvar->sqllen = sizeof(SLONG);
 
1005
                break;
 
1006
        case SQL_SHORT:
 
1007
                xsqlvar->sqlscale = xsqlvar->sqllen >> 8;
 
1008
                xsqlvar->sqllen = sizeof(SSHORT);
 
1009
                break;
 
1010
        case SQL_INT64:
 
1011
                xsqlvar->sqlscale = xsqlvar->sqllen >> 8;
 
1012
                xsqlvar->sqllen = sizeof(SINT64);
 
1013
                break;
 
1014
        case SQL_QUAD:
 
1015
                xsqlvar->sqlscale = xsqlvar->sqllen >> 8;
 
1016
                xsqlvar->sqllen = sizeof(ISC_QUAD);
 
1017
                break;
 
1018
        }
 
1019
}
 
1020
 
 
1021
 
 
1022
/**
 
1023
  
 
1024
        xsqlvar_to_sqlvar
 
1025
  
 
1026
    @brief      Move an XSQLVAR to an SQLVAR.
 
1027
 
 
1028
 
 
1029
    @param xsqlvar
 
1030
    @param sqlvar
 
1031
 
 
1032
 **/
 
1033
static void xsqlvar_to_sqlvar(const XSQLVAR* xsqlvar, SQLVAR* sqlvar)
 
1034
{
 
1035
 
 
1036
        sqlvar->sqltype = xsqlvar->sqltype;
 
1037
        sqlvar->sqlname_length = xsqlvar->aliasname_length;
 
1038
 
 
1039
// N.B., this may not NULL-terminate the name... 
 
1040
 
 
1041
        memcpy(sqlvar->sqlname, xsqlvar->aliasname, sizeof(sqlvar->sqlname));
 
1042
 
 
1043
        sqlvar->sqllen = xsqlvar->sqllen;
 
1044
        const USHORT scale = xsqlvar->sqlscale << 8;
 
1045
        switch (sqlvar->sqltype & ~1)
 
1046
        {
 
1047
        case SQL_LONG:
 
1048
                sqlvar->sqllen = sizeof(SLONG) | scale;
 
1049
                break;
 
1050
        case SQL_SHORT:
 
1051
                sqlvar->sqllen = sizeof(SSHORT) | scale;
 
1052
                break;
 
1053
        case SQL_INT64:
 
1054
                sqlvar->sqllen = sizeof(SINT64) | scale;
 
1055
                break;
 
1056
        case SQL_QUAD:
 
1057
                sqlvar->sqllen = sizeof(ISC_QUAD) | scale;
 
1058
                break;
 
1059
        }
 
1060
}
 
1061
 
 
1062
 
 
1063
#if !defined(REQUESTER) && !defined(SUPERCLIENT)
 
1064
 
 
1065
UCHAR DSqlDataTypeUtil::maxBytesPerChar(UCHAR charSet)
 
1066
{
 
1067
        return METD_get_charset_bpc(request, charSet);
 
1068
}
 
1069
 
 
1070
USHORT DSqlDataTypeUtil::getDialect() const
 
1071
{
 
1072
        return request->req_client_dialect;
 
1073
}
 
1074
 
 
1075
#endif