/[pkg-firebird]/upstream/current/src/jrd/cvt2.cpp
ViewVC logotype

Contents of /upstream/current/src/jrd/cvt2.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1141 - (show annotations) (download)
Sun Apr 1 15:48:28 2007 UTC (6 years, 2 months ago) by dmn
File size: 19533 byte(s)
Import current upstream CVS
1 /*
2 * PROGRAM: JRD Access Method
3 * MODULE: cvt2.cpp
4 * DESCRIPTION: Data mover and converter and comparator, etc.
5 * Routines used ONLY within engine.
6 *
7 * The contents of this file are subject to the Interbase Public
8 * License Version 1.0 (the "License"); you may not use this file
9 * except in compliance with the License. You may obtain a copy
10 * of the License at http://www.Inprise.com/IPL.html
11 *
12 * Software distributed under the License is distributed on an
13 * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
14 * or implied. See the License for the specific language governing
15 * rights and limitations under the License.
16 *
17 * The Original Code was created by Inprise Corporation
18 * and its predecessors. Portions created by Inprise Corporation are
19 * Copyright (C) Inprise Corporation.
20 *
21 * All Rights Reserved.
22 * Contributor(s): ______________________________________.
23 *
24 * 2001.6.18 Claudio Valderrama: Implement comparison on blobs and blobs against
25 * other datatypes by request from Ann Harrison.
26 */
27
28 #include "firebird.h"
29 #include <string.h>
30 #include "../jrd/common.h"
31 #include "../jrd/ibase.h"
32
33 #include "../jrd/jrd.h"
34 #include "../jrd/val.h"
35 #include "../jrd/quad.h"
36 #include "gen/iberror.h"
37 #include "../jrd/intl.h"
38 #include "../jrd/gdsassert.h"
39 #include "../jrd/cvt_proto.h"
40 #include "../jrd/cvt2_proto.h"
41 #include "../jrd/err_proto.h"
42 #include "../jrd/intl_proto.h"
43 #include "../jrd/thd.h"
44 #include "../jrd/intl_classes.h"
45 #include "../jrd/gds_proto.h"
46 /* CVC: I needed them here. */
47 #include "../jrd/jrd.h"
48 #include "../jrd/blb_proto.h"
49 #include "../jrd/tra.h"
50 #include "../jrd/req.h"
51 #include "../jrd/constants.h"
52 #include "../common/utils_proto.h"
53
54 using namespace Jrd;
55
56 #ifdef VMS
57 double MTH$CVT_D_G(), MTH$CVT_G_D();
58 #endif
59
60 /* The original order of dsc_type values corresponded to the priority
61 of conversion (that is, always convert the lesser to the greater
62 type.) Introduction of dtype_int64 breaks that assumption: its
63 position on the scale should be between dtype_long and dtype_real, but
64 the types are integers, and dtype_quad occupies the only available
65 place. Renumbering all the higher-numbered types would be a major
66 ODS change and a fundamental discomfort
67
68 This table permits us to put the entries in the right order for
69 comparison purpose, even though isc_int64 had to get number 19, which
70 is otherwise too high.
71
72 This table is used in CVT2_compare, is indexed by dsc_dtype, and
73 returns the relative priority of types for use when different types
74 are compared.
75 */
76 static const BYTE compare_priority[] = { dtype_unknown, /* dtype_unknown through dtype_varying */
77 dtype_text, /* have their natural values stored */
78 dtype_cstring, /* in the table. */
79 dtype_varying,
80 0, 0, /* dtypes and 4, 5 are unused. */
81 dtype_packed, /* packed through long also have */
82 dtype_byte, /* their natural values in the table */
83 dtype_short,
84 dtype_long,
85 dtype_quad + 1, /* quad through array all move up */
86 dtype_real + 1, /* by one to make room for int64 */
87 dtype_double + 1, /* at its proper place in the table. */
88 dtype_d_float + 1,
89 dtype_sql_date + 1,
90 dtype_sql_time + 1,
91 dtype_timestamp + 1,
92 dtype_blob + 1,
93 dtype_array + 1,
94 dtype_long + 1
95 }; /* int64 goes right after long */
96
97
98 SSHORT CVT2_compare(const dsc* arg1, const dsc* arg2, FPTR_ERROR err)
99 {
100 /**************************************
101 *
102 * C V T 2 _ c o m p a r e
103 *
104 **************************************
105 *
106 * Functional description
107 * Compare two descriptors. Return (-1, 0, 1) if a<b, a=b, or a>b.
108 *
109 **************************************/
110 thread_db* tdbb = NULL;
111
112 // AB: Maybe we need a other error-message, but at least throw
113 // a message when 1 or both input paramters are empty.
114 if (!arg1 || !arg2) {
115 BUGCHECK(189); // msg 189 comparison not supported for specified data types.
116 }
117
118 /* Handle the simple (matched) ones first */
119
120 if (arg1->dsc_dtype == arg2->dsc_dtype && arg1->dsc_scale == arg2->dsc_scale)
121 {
122 const UCHAR* p1 = arg1->dsc_address;
123 const UCHAR* p2 = arg2->dsc_address;
124
125 switch (arg1->dsc_dtype) {
126 case dtype_short:
127 if (*(SSHORT *) p1 == *(SSHORT *) p2)
128 return 0;
129 if (*(SSHORT *) p1 > *(SSHORT *) p2)
130 return 1;
131 return -1;
132
133 case dtype_sql_time:
134 if (*(ULONG *) p1 == *(ULONG *) p2)
135 return 0;
136 if (*(ULONG *) p1 > *(ULONG *) p2)
137 return 1;
138 return -1;
139
140 case dtype_long:
141 case dtype_sql_date:
142 if (*(SLONG *) p1 == *(SLONG *) p2)
143 return 0;
144 if (*(SLONG *) p1 > *(SLONG *) p2)
145 return 1;
146 return -1;
147
148 case dtype_quad:
149 return QUAD_COMPARE(*(SQUAD *) p1, *(SQUAD *) p2);
150
151 case dtype_int64:
152 if (*(SINT64 *) p1 == *(SINT64 *) p2)
153 return 0;
154 if (*(SINT64 *) p1 > *(SINT64 *) p2)
155 return 1;
156 return -1;
157
158 case dtype_timestamp:
159 if (((SLONG *) p1)[0] > ((SLONG *) p2)[0])
160 return 1;
161 if (((SLONG *) p1)[0] < ((SLONG *) p2)[0])
162 return -1;
163 if (((ULONG *) p1)[1] > ((ULONG *) p2)[1])
164 return 1;
165 if (((ULONG *) p1)[1] < ((ULONG *) p2)[1])
166 return -1;
167 return 0;
168
169 case dtype_real:
170 if (*(float *) p1 == *(float *) p2)
171 return 0;
172 if (*(float *) p1 > *(float *) p2)
173 return 1;
174 return -1;
175
176 case DEFAULT_DOUBLE:
177 if (*(double *) p1 == *(double *) p2)
178 return 0;
179 if (*(double *) p1 > *(double *) p2)
180 return 1;
181 return -1;
182
183 #ifdef VMS
184 case SPECIAL_DOUBLE:
185 if (*(double *) p1 == *(double *) p2)
186 return 0;
187 if (CNVT_TO_DFLT((double *) p1) > CNVT_TO_DFLT((double *) p2))
188 return 1;
189 return -1;
190 #endif
191
192 case dtype_text:
193 case dtype_varying:
194 case dtype_cstring:
195 case dtype_array:
196 case dtype_blob:
197 /* Special processing below */
198 break;
199
200 default:
201 /* the two arguments have identical dtype and scale, but the
202 dtype is not one of your defined types! */
203 fb_assert(FALSE);
204 break;
205
206 } /* switch on dtype */
207 } /* if dtypes and scales are equal */
208
209 /* Handle mixed string comparisons */
210
211 if (arg1->dsc_dtype <= dtype_varying && arg2->dsc_dtype <= dtype_varying)
212 {
213 /*
214 * For the sake of optimization, we call INTL_compare
215 * only when we cannot just do byte-by-byte compare.
216 * We can do a local compare here, if
217 * (a) one of the arguments is charset ttype_binary
218 * OR (b) both of the arguments are char set ttype_none
219 * OR (c) both of the arguments are char set ttype_ascii
220 * If any argument is ttype_dynamic, we must see the
221 * charset of the attachment.
222 */
223
224 SET_TDBB(tdbb);
225 CHARSET_ID charset1 = INTL_TTYPE(arg1);
226 if (charset1 == ttype_dynamic)
227 charset1 = INTL_charset(tdbb, charset1);
228
229 CHARSET_ID charset2 = INTL_TTYPE(arg2);
230 if (charset2 == ttype_dynamic)
231 charset2 = INTL_charset(tdbb, charset2);
232
233 if ((IS_INTL_DATA(arg1) || IS_INTL_DATA(arg2)) &&
234 (charset1 != ttype_binary) &&
235 (charset2 != ttype_binary) &&
236 ((charset1 != ttype_ascii) ||
237 (charset2 != ttype_ascii)) &&
238 ((charset1 != ttype_none) || (charset2 != ttype_none)))
239 {
240 return INTL_compare(tdbb, arg1, arg2, err);
241 }
242
243 UCHAR* p1 = NULL;
244 UCHAR* p2 = NULL;
245 USHORT t1, t2; // unused later
246 USHORT length = CVT_get_string_ptr(arg1, &t1, &p1, NULL, 0, err);
247 USHORT length2 = CVT_get_string_ptr(arg2, &t2, &p2, NULL, 0, err);
248
249 int fill = length - length2;
250 const UCHAR pad = charset1 == ttype_binary || charset2 == ttype_binary ? '\0' : ' ';
251 if (length >= length2) {
252 if (length2)
253 do
254 if (*p1++ != *p2++)
255 if (p1[-1] > p2[-1])
256 return 1;
257 else
258 return -1;
259 while (--length2);
260 if (fill > 0)
261 do
262 if (*p1++ != pad)
263 if (p1[-1] > pad)
264 return 1;
265 else
266 return -1;
267 while (--fill);
268 return 0;
269 }
270 if (length)
271 do
272 if (*p1++ != *p2++)
273 if (p1[-1] > p2[-1])
274 return 1;
275 else
276 return -1;
277 while (--length);
278 do
279 if (*p2++ != pad)
280 if (pad > p2[-1])
281 return 1;
282 else
283 return -1;
284 while (++fill);
285 return 0;
286 }
287
288 /* Handle heterogeneous compares */
289
290 if (compare_priority[arg1->dsc_dtype] < compare_priority[arg2->dsc_dtype])
291 return -CVT2_compare(arg2, arg1, err);
292
293 /* At this point, the type of arg1 is guaranteed to be "greater than" arg2,
294 in the sense that it is the preferred type for comparing the two. */
295
296 switch (arg1->dsc_dtype)
297 {
298 SLONG date[2];
299
300 case dtype_timestamp:
301 {
302 DSC desc;
303 MOVE_CLEAR(&desc, sizeof(desc));
304 desc.dsc_dtype = dtype_timestamp;
305 desc.dsc_length = sizeof(date);
306 desc.dsc_address = (UCHAR *) date;
307 CVT_move(arg2, &desc, err);
308 return CVT2_compare(arg1, &desc, err);
309 }
310
311 case dtype_sql_time:
312 {
313 DSC desc;
314 MOVE_CLEAR(&desc, sizeof(desc));
315 desc.dsc_dtype = dtype_sql_time;
316 desc.dsc_length = sizeof(date[0]);
317 desc.dsc_address = (UCHAR *) date;
318 CVT_move(arg2, &desc, err);
319 return CVT2_compare(arg1, &desc, err);
320 }
321
322 case dtype_sql_date:
323 {
324 DSC desc;
325 MOVE_CLEAR(&desc, sizeof(desc));
326 desc.dsc_dtype = dtype_sql_date;
327 desc.dsc_length = sizeof(date[0]);
328 desc.dsc_address = (UCHAR *) date;
329 CVT_move(arg2, &desc, err);
330 return CVT2_compare(arg1, &desc, err);
331 }
332
333 case dtype_short:
334 {
335 SSHORT scale;
336 if (arg2->dsc_dtype > dtype_varying)
337 scale = MIN(arg1->dsc_scale, arg2->dsc_scale);
338 else
339 scale = arg1->dsc_scale;
340 const SLONG temp1 = CVT_get_long(arg1, scale, err);
341 const SLONG temp2 = CVT_get_long(arg2, scale, err);
342 if (temp1 == temp2)
343 return 0;
344 if (temp1 > temp2)
345 return 1;
346 return -1;
347 }
348
349 case dtype_long:
350 /* Since longs may overflow when scaled, use int64 instead */
351 case dtype_int64:
352 {
353 SSHORT scale;
354 if (arg2->dsc_dtype > dtype_varying)
355 scale = MIN(arg1->dsc_scale, arg2->dsc_scale);
356 else
357 scale = arg1->dsc_scale;
358 const SINT64 temp1 = CVT_get_int64(arg1, scale, err);
359 const SINT64 temp2 = CVT_get_int64(arg2, scale, err);
360 if (temp1 == temp2)
361 return 0;
362 if (temp1 > temp2)
363 return 1;
364 return -1;
365 }
366
367 case dtype_quad:
368 {
369 SSHORT scale;
370 if (arg2->dsc_dtype > dtype_varying)
371 scale = MIN(arg1->dsc_scale, arg2->dsc_scale);
372 else
373 scale = arg1->dsc_scale;
374 const SQUAD temp1 = CVT_get_quad(arg1, scale, err);
375 const SQUAD temp2 = CVT_get_quad(arg2, scale, err);
376 return QUAD_COMPARE(temp1, temp2);
377 }
378
379 case dtype_real:
380 {
381 const float temp1 = (float) CVT_get_double(arg1, err);
382 const float temp2 = (float) CVT_get_double(arg2, err);
383 if (temp1 == temp2)
384 return 0;
385 if (temp1 > temp2)
386 return 1;
387 return -1;
388 }
389
390 case dtype_double:
391 #ifdef VMS
392 case dtype_d_float:
393 #endif
394 {
395 const double temp1 = CVT_get_double(arg1, err);
396 const double temp2 = CVT_get_double(arg2, err);
397 if (temp1 == temp2)
398 return 0;
399 if (temp1 > temp2)
400 return 1;
401 return -1;
402 }
403
404 case dtype_blob:
405 return CVT2_blob_compare(arg1, arg2, err);
406
407 case dtype_array:
408 (*err) (isc_wish_list, isc_arg_gds, isc_blobnotsup,
409 isc_arg_string, "compare", 0);
410 break;
411
412 default:
413 BUGCHECK(189); /* msg 189 comparison not supported for specified data types */
414 break;
415 }
416 return 0;
417 }
418
419
420 SSHORT CVT2_blob_compare(const dsc* arg1, const dsc* arg2, FPTR_ERROR err)
421 {
422 /**************************************
423 *
424 * C V T 2 _ b l o b _ c o m p a r e
425 *
426 **************************************
427 *
428 * Functional description
429 * Compare two blobs. Return (-1, 0, 1) if a<b, a=b, or a>b.
430 * Alternatively, it will try to compare a blob against a string;
431 * in this case, the string should be the second argument.
432 * CVC: Ann Harrison asked for this function to make comparisons more
433 * complete in the engine.
434 *
435 **************************************/
436
437 SLONG l1, l2;
438 USHORT ttype2;
439 SSHORT ret_val = 0;
440
441 thread_db* tdbb = NULL;
442 SET_TDBB(tdbb);
443
444 /* DEV_BLKCHK (node, type_nod); */
445
446 if (arg1->dsc_dtype != dtype_blob)
447 (*err) (isc_wish_list, isc_arg_gds, isc_datnotsup, 0);
448
449 USHORT ttype1;
450 if (arg1->dsc_sub_type == isc_blob_text)
451 ttype1 = arg1->dsc_blob_ttype(); /* Load blob character set and collation */
452 else
453 ttype1 = ttype_binary;
454
455 TextType* obj1 = INTL_texttype_lookup(tdbb, ttype1);
456 ttype1 = obj1->getType();
457
458 /* Is arg2 a blob? */
459 if (arg2->dsc_dtype == dtype_blob)
460 {
461 /* Same blob id address? */
462 if (arg1->dsc_address == arg2->dsc_address)
463 return 0;
464 else
465 {
466 /* Second test for blob id, checking relation and slot. */
467 bid* bid1 = (bid*) arg1->dsc_address;
468 bid* bid2 = (bid*) arg2->dsc_address;
469 if (*bid1 == *bid2)
470 {
471 return 0;
472 }
473 }
474
475 if (arg2->dsc_sub_type == isc_blob_text)
476 ttype2 = arg2->dsc_blob_ttype(); /* Load blob character set and collation */
477 else
478 ttype2 = ttype_binary;
479
480 TextType* obj2 = INTL_texttype_lookup(tdbb, ttype2);
481 ttype2 = obj2->getType();
482
483 if (ttype1 == ttype_binary || ttype2 == ttype_binary)
484 ttype1 = ttype2 = ttype_binary;
485 else if (ttype1 == ttype_none || ttype2 == ttype_none)
486 ttype1 = ttype2 = ttype_none;
487
488 obj1 = INTL_texttype_lookup(tdbb, ttype1);
489 obj2 = INTL_texttype_lookup(tdbb, ttype2);
490
491 CharSet* charSet1 = obj1->getCharSet();
492 CharSet* charSet2 = obj2->getCharSet();
493
494 Firebird::HalfStaticArray<UCHAR, BUFFER_LARGE> buffer1;
495 Firebird::HalfStaticArray<UCHAR, BUFFER_LARGE> buffer2;
496 fb_assert(BUFFER_LARGE % 4 == 0); // 4 is our maximum character length
497
498 UCHAR bpb[] = {isc_bpb_version1,
499 isc_bpb_source_type, 1, isc_blob_text, isc_bpb_source_interp, 1, 0,
500 isc_bpb_target_type, 1, isc_blob_text, isc_bpb_target_interp, 1, 0};
501 USHORT bpbLength = 0;
502
503 if (arg1->dsc_sub_type == isc_blob_text && arg2->dsc_sub_type == isc_blob_text)
504 {
505 bpb[6] = arg2->dsc_scale; // source charset
506 bpb[12] = arg1->dsc_scale; // destination charset
507 bpbLength = sizeof(bpb);
508 }
509
510 blb* blob1 = BLB_open(tdbb, tdbb->tdbb_request->req_transaction, (bid*) arg1->dsc_address);
511 blb* blob2 = BLB_open2(tdbb, tdbb->tdbb_request->req_transaction, (bid*) arg2->dsc_address, bpbLength, bpb);
512
513 if (charSet1->isMultiByte())
514 {
515 buffer1.getBuffer(blob1->blb_length);
516 buffer2.getBuffer(blob2->blb_length / charSet2->minBytesPerChar() * charSet1->maxBytesPerChar());
517 }
518
519 while (ret_val == 0 &&
520 !(blob1->blb_flags & BLB_eof) && !(blob2->blb_flags & BLB_eof))
521 {
522 l1 = BLB_get_data(tdbb, blob1, buffer1.begin(), buffer1.getCapacity(), false);
523 l2 = BLB_get_data(tdbb, blob2, buffer2.begin(), buffer2.getCapacity(), false);
524
525 ret_val = obj1->compare(l1, buffer1.begin(), l2, buffer2.begin());
526 }
527
528 if (ret_val == 0)
529 {
530 if ((blob1->blb_flags & BLB_eof) == BLB_eof)
531 l1 = 0;
532
533 if ((blob2->blb_flags & BLB_eof) == BLB_eof)
534 l2 = 0;
535
536 while (ret_val == 0 &&
537 !((blob1->blb_flags & BLB_eof) == BLB_eof &&
538 (blob2->blb_flags & BLB_eof) == BLB_eof))
539 {
540 if (!(blob1->blb_flags & BLB_eof))
541 l1 = BLB_get_data(tdbb, blob1, buffer1.begin(), buffer1.getCapacity(), false);
542
543 if (!(blob2->blb_flags & BLB_eof))
544 l2 = BLB_get_data(tdbb, blob2, buffer2.begin(), buffer2.getCapacity(), false);
545
546 ret_val = obj1->compare(l1, buffer1.begin(), l2, buffer2.begin());
547 }
548 }
549
550 BLB_close(tdbb, blob1);
551 BLB_close(tdbb, blob2);
552 }
553 /* We do not accept arrays for now. Maybe InternalArrayDesc in the future. */
554 else if (arg2->dsc_dtype == dtype_array)
555 (*err) (isc_wish_list, isc_arg_gds, isc_datnotsup, 0);
556 /* The second parameter should be a string. */
557 else
558 {
559 if (arg2->dsc_dtype <= dtype_varying)
560 {
561 if ((ttype2 = arg2->dsc_ttype()) != ttype_binary)
562 ttype2 = ttype1;
563 }
564 else
565 ttype2 = ttype1;
566
567 if (ttype1 == ttype_binary || ttype2 == ttype_binary)
568 ttype1 = ttype2 = ttype_binary;
569 else if (ttype1 == ttype_none || ttype2 == ttype_none)
570 ttype1 = ttype2 = ttype_none;
571
572 obj1 = INTL_texttype_lookup(tdbb, ttype1);
573
574 CharSet* charSet1 = obj1->getCharSet();
575
576 Firebird::HalfStaticArray<UCHAR, BUFFER_LARGE> buffer1;
577 UCHAR* p;
578 MoveBuffer temp_str;
579
580 l2 = CVT2_make_string2(arg2, ttype1, &p, temp_str, err);
581
582 blb* blob1 = BLB_open(tdbb, tdbb->tdbb_request->req_transaction, (bid*) arg1->dsc_address);
583
584 if (charSet1->isMultiByte())
585 buffer1.getBuffer(blob1->blb_length);
586 else
587 buffer1.getBuffer(l2);
588
589 l1 = BLB_get_data(tdbb, blob1, buffer1.begin(), buffer1.getCapacity(), false);
590 ret_val = obj1->compare(l1, buffer1.begin(), l2, p);
591
592 while (ret_val == 0 && (blob1->blb_flags & BLB_eof) != BLB_eof)
593 {
594 l1 = BLB_get_data(tdbb, blob1, buffer1.begin(), buffer1.getCapacity(), false);
595 ret_val = obj1->compare(l1, buffer1.begin(), 0, p);
596 }
597
598 BLB_close(tdbb, blob1);
599 }
600
601 return ret_val;
602 }
603
604
605 void CVT2_get_name(const dsc* desc, TEXT* string, FPTR_ERROR err)
606 {
607 /**************************************
608 *
609 * C V T _ g e t _ n a m e
610 *
611 **************************************
612 *
613 * Functional description
614 * Get a name (max length 31, NULL terminated) from a descriptor.
615 *
616 **************************************/
617 VARY_STR(MAX_SQL_IDENTIFIER_SIZE) temp; /* 31 bytes + 1 NULL */
618 const char* p;
619
620 USHORT length = CVT_make_string(desc, ttype_metadata, &p,
621 (vary*) & temp, sizeof(temp), err);
622 TEXT* const orig_string = string;
623 for (; length; --length)
624 *string++ = *p++;
625
626 *string = 0;
627 fb_utils::exact_name(orig_string);
628 }
629
630
631 USHORT CVT2_make_string2(const dsc* desc,
632 USHORT to_interp,
633 UCHAR** address,
634 Jrd::MoveBuffer& temp,
635 FPTR_ERROR err)
636 {
637 /**************************************
638 *
639 * C V T _ m a k e _ s t r i n g 2
640 *
641 **************************************
642 *
643 * Functional description
644 *
645 * Convert the data from the desc to a string in the specified interp.
646 * The pointer to this string is returned in address.
647 *
648 **************************************/
649 UCHAR* from_buf;
650 USHORT from_len;
651 USHORT from_interp;
652
653 fb_assert(desc != NULL);
654 fb_assert(address != NULL);
655 fb_assert(err != NULL);
656
657 if (desc->dsc_dtype == dtype_text) {
658 from_buf = desc->dsc_address;
659 from_len = desc->dsc_length;
660 from_interp = INTL_TTYPE(desc);
661 }
662
663 else if (desc->dsc_dtype == dtype_cstring) {
664 from_buf = desc->dsc_address;
665 from_len = MIN(strlen((char *) desc->dsc_address), \
666 (unsigned) (desc->dsc_length - 1));
667 from_interp = INTL_TTYPE(desc);
668 }
669
670 else if (desc->dsc_dtype == dtype_varying) {
671 vary* varying = (vary*) desc->dsc_address;
672 from_buf = reinterpret_cast<UCHAR*>(varying->vary_string);
673 from_len =
674 MIN(varying->vary_length, (USHORT) (desc->dsc_length - sizeof(SSHORT)));
675 from_interp = INTL_TTYPE(desc);
676 }
677
678 if (desc->dsc_dtype <= dtype_any_text) {
679
680 if (to_interp == from_interp) {
681 *address = from_buf;
682 return from_len;
683 }
684
685 thread_db* tdbb = JRD_get_thread_data();
686 const USHORT cs1 = INTL_charset(tdbb, to_interp);
687 const USHORT cs2 = INTL_charset(tdbb, from_interp);
688 if (cs1 == cs2) {
689 *address = from_buf;
690 return from_len;
691 }
692 else {
693 USHORT length = INTL_convert_bytes(tdbb, cs1, NULL, 0,
694 cs2, from_buf, from_len, err);
695 UCHAR* tempptr = temp.getBuffer(length);
696 length = INTL_convert_bytes(tdbb, cs1, tempptr, length,
697 cs2, from_buf, from_len, err);
698 *address = tempptr;
699 return length;
700 }
701 }
702
703 /* Not string data, then -- convert value to varying string. */
704
705 dsc temp_desc;
706 MOVE_CLEAR(&temp_desc, sizeof(temp_desc));
707 temp_desc.dsc_length = temp.getCapacity();
708 temp_desc.dsc_address = temp.getBuffer(temp_desc.dsc_length);
709 vary* vtmp = reinterpret_cast<vary*>(temp_desc.dsc_address);
710 INTL_ASSIGN_TTYPE(&temp_desc, to_interp);
711 temp_desc.dsc_dtype = dtype_varying;
712 CVT_move(desc, &temp_desc, err);
713 *address = reinterpret_cast<UCHAR*>(vtmp->vary_string);
714
715 return vtmp->vary_length;
716 }

  ViewVC Help
Powered by ViewVC 1.1.5