/* * PROGRAM: JRD Access Method * MODULE: mov.cpp * DESCRIPTION: Data mover and converter and comparator, etc. * * The contents of this file are subject to the Interbase Public * License Version 1.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy * of the License at http://www.Inprise.com/IPL.html * * Software distributed under the License is distributed on an * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express * or implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code was created by Inprise Corporation * and its predecessors. Portions created by Inprise Corporation are * Copyright (C) Inprise Corporation. * * All Rights Reserved. * Contributor(s): ______________________________________. * * 2002.08.21 Dmitry Yemanov: fixed bug with a buffer overrun, * which at least caused invalid dependencies * to be stored (DB$xxx, for example) * Adriano dos Santos Fernandes */ #include "firebird.h" #include "../jrd/common.h" #include "../jrd/gdsassert.h" #include "../jrd/jrd.h" #include "../jrd/val.h" #include "../jrd/intl.h" #include "../jrd/blb_proto.h" #include "../jrd/cvt_proto.h" #include "../common/cvt.h" #include "../jrd/cvt2_proto.h" #include "../jrd/err_proto.h" #include "../jrd/intl_proto.h" #include "../jrd/mov_proto.h" using namespace Firebird; int MOV_compare(const dsc* arg1, const dsc* arg2) { /************************************** * * M O V _ c o m p a r e * ************************************** * * Functional description * Compare two descriptors. Return (-1, 0, 1) if ab. * **************************************/ return CVT2_compare(arg1, arg2); } double MOV_date_to_double(const dsc* desc) { /************************************** * * M O V _ d a t e _ t o _ d o u b l e * ************************************** * * Functional description * Convert a date to double precision for * date arithmetic routines. * **************************************/ return CVT_date_to_double(desc); } #ifdef NOT_USED_OR_REPLACED // Strange, I don't see this function surfaced as public. void MOV_double_to_date2(double real, dsc* desc) { /************************************** * * M O V _ d o u b l e _ t o _ d a t e 2 * ************************************** * * Functional description * Move a double to one of the many forms of a date * **************************************/ SLONG fixed[2]; MOV_double_to_date(real, fixed); switch (desc->dsc_dtype) { case dtype_timestamp: ((SLONG *) desc->dsc_address)[0] = fixed[0]; ((SLONG *) desc->dsc_address)[1] = fixed[1]; break; case dtype_sql_time: ((SLONG *) desc->dsc_address)[0] = fixed[1]; break; case dtype_sql_date: ((SLONG *) desc->dsc_address)[0] = fixed[0]; break; default: fb_assert(FALSE); break; } } #endif void MOV_double_to_date(double real, SLONG fixed[2]) { /************************************** * * M O V _ d o u b l e _ t o _ d a t e * ************************************** * * Functional description * Convert a double precision representation of a date * to a fixed point representation. Double is used for * date arithmetic. * **************************************/ CVT_double_to_date(real, fixed); } double MOV_get_double(const dsc* desc) { /************************************** * * M O V _ g e t _ d o u b l e * ************************************** * * Functional description * Convert something arbitrary to a double precision number * **************************************/ return CVT_get_double(desc, ERR_post); } SLONG MOV_get_long(const dsc* desc, SSHORT scale) { /************************************** * * M O V _ g e t _ l o n g * ************************************** * * Functional description * Convert something arbitrary to a long (32 bit) integer of given * scale. * **************************************/ return CVT_get_long(desc, scale, ERR_post); } SINT64 MOV_get_int64(const dsc* desc, SSHORT scale) { /************************************** * * M O V _ g e t _ i n t 6 4 * ************************************** * * Functional description * Convert something arbitrary to a 64 bit integer of given * scale. * **************************************/ return CVT_get_int64(desc, scale, ERR_post); } void MOV_get_metadata_str(const dsc* desc, TEXT* buffer, USHORT buffer_length) { /************************************** * * M O V _ g e t _ m e t a d a t a _ s t r * ************************************** * * Functional description * Copy string, which will afterward's * be treated as a metadata name value, * to the user-supplied buffer. * **************************************/ USHORT dummy_type; UCHAR *ptr; USHORT length = CVT_get_string_ptr(desc, &dummy_type, &ptr, NULL, 0, ERR_post); #ifdef DEV_BUILD if ((dummy_type != ttype_metadata) && (dummy_type != ttype_none) && (dummy_type != ttype_ascii)) { ERR_bugcheck_msg("Expected METADATA name"); } #endif length = ptr ? MIN(length, buffer_length - 1) : 0; memcpy(buffer, ptr, length); buffer[length] = 0; } void MOV_get_name(const dsc* desc, TEXT* string) { /************************************** * * M O V _ g e t _ n a m e * ************************************** * * Functional description * Get a name (max length 31, blank terminated) from a descriptor. * **************************************/ CVT2_get_name(desc, string); } SQUAD MOV_get_quad(const dsc* desc, SSHORT scale) { /************************************** * * M O V _ g e t _ q u a d * ************************************** * * Functional description * Convert something arbitrary to a quad * Note: a quad is NOT the same as a 64 bit integer * **************************************/ return CVT_get_quad(desc, scale, ERR_post); } int MOV_get_string_ptr( const dsc* desc, USHORT* ttype, UCHAR** address, vary* temp, USHORT length) { /************************************** * * M O V _ g e t _ s t r i n g _ p t r * ************************************** * * Functional description * Get address and length of string, converting the value to * string, if necessary. The caller must provide a sufficiently * large temporary. The address of the resultant string is returned * by reference. Get_string returns the length of the string. * * Note: If the descriptor is known to be a string type, the third * argument (temp buffer) may be omitted. * **************************************/ return CVT_get_string_ptr(desc, ttype, address, temp, length, ERR_post); } int MOV_get_string(const dsc* desc, UCHAR** address, vary* temp, USHORT length) { /************************************** * * M O V _ g e t _ s t r i n g * ************************************** * * Functional description * **************************************/ USHORT ttype; return MOV_get_string_ptr(desc, &ttype, address, temp, length); } GDS_DATE MOV_get_sql_date(const dsc* desc) { /************************************** * * M O V _ g e t _ s q l _ d a t e * ************************************** * * Functional description * Convert something arbitrary to a SQL date * **************************************/ return CVT_get_sql_date(desc); } GDS_TIME MOV_get_sql_time(const dsc* desc) { /************************************** * * M O V _ g e t _ s q l _ t i m e * ************************************** * * Functional description * Convert something arbitrary to a SQL time * **************************************/ return CVT_get_sql_time(desc); } GDS_TIMESTAMP MOV_get_timestamp(const dsc* desc) { /************************************** * * M O V _ g e t _ t i m e s t a m p * ************************************** * * Functional description * Convert something arbitrary to a timestamp * **************************************/ return CVT_get_timestamp(desc); } int MOV_make_string(const dsc* desc, USHORT ttype, const char** address, vary* temp, USHORT length) { /************************************** * * M O V _ m a k e _ s t r i n g * ************************************** * * Functional description * Make a string, in a specified text type, out of a descriptor. * The caller must provide a sufficiently * large temporary. The address of the resultant string is returned * by reference. * MOV_make_string returns the length of the string in bytes. * * Note: If the descriptor is known to be a string type in the * given ttype the argument (temp buffer) may be omitted. * But this would be a bad idea in general. * **************************************/ return CVT_make_string(desc, ttype, address, temp, length, ERR_post); } int MOV_make_string2(Jrd::thread_db* tdbb, const dsc* desc, USHORT ttype, UCHAR** address, Jrd::MoveBuffer& buffer, bool limit) { /************************************** * * M O V _ m a k e _ s t r i n g 2 * ************************************** * * Functional description * Make a string, in a specified text type, out of a descriptor. * The address of the resultant string is returned. * MOV_make_string2 returns the length of the string in bytes. * **************************************/ if (desc->isBlob()) { // fake descriptor dsc temp; temp.dsc_dtype = dtype_text; temp.setTextType(ttype); Firebird::UCharBuffer bpb; BLB_gen_bpb_from_descs(desc, &temp, bpb); Jrd::blb* blob = BLB_open2(tdbb, tdbb->getRequest()->req_transaction, reinterpret_cast(desc->dsc_address), bpb.getCount(), bpb.begin()); ULONG size; if (temp.getCharSet() == desc->getCharSet()) { size = blob->blb_length; } else { size = (blob->blb_length / INTL_charset_lookup(tdbb, desc->getCharSet())->minBytesPerChar()) * INTL_charset_lookup(tdbb, temp.getCharSet())->maxBytesPerChar(); } *address = buffer.getBuffer(size); size = BLB_get_data(tdbb, blob, *address, size, true); if (limit && size > MAX_COLUMN_SIZE) ERR_post(Arg::Gds(isc_arith_except) << Arg::Gds(isc_blob_truncation)); return size; } return CVT2_make_string2(desc, ttype, address, buffer); } void MOV_move(Jrd::thread_db* tdbb, /*const*/ dsc* from, dsc* to) { /************************************** * * M O V _ m o v e * ************************************** * * Functional description * Move (and possible convert) something to something else. * **************************************/ if (DTYPE_IS_BLOB_OR_QUAD(from->dsc_dtype) || DTYPE_IS_BLOB_OR_QUAD(to->dsc_dtype)) { BLB_move(tdbb, from, to, NULL); } else CVT_move(from, to); }