8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-24 20:43:04 +01:00
firebird-mirror/src/dsql/blob.epp

308 lines
8.2 KiB
Plaintext
Raw Normal View History

2001-05-23 15:26:42 +02:00
/*
* PROGRAM: InterBase layered support library
2001-12-24 03:51:06 +01:00
* MODULE: blob.epp
2001-05-23 15:26:42 +02:00
* DESCRIPTION: Dynamic blob support
*
* 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-06-29 08:56:51 +02:00
*
* 2001.09.10 Claudio Valderrama: get_name() was preventing the API calls
* isc_blob_default_desc, isc_blob_lookup_desc & isc_blob_set_desc
* from working properly with dialect 3 names. Therefore, incorrect names
* could be returned or a lookup for a blob field could fail. In addition,
* a possible buffer overrun due to unchecked bounds was closed. The fc
* get_name() as been renamed copy_exact_name().
*
2001-05-23 15:26:42 +02:00
*/
#include "firebird.h"
2001-05-23 15:26:42 +02:00
#include "../jrd/common.h"
#include <stdarg.h>
2003-11-08 00:27:24 +01:00
#include "../jrd/ibase.h"
2001-05-23 15:26:42 +02:00
#include "../jrd/intl.h"
#include "../dsql/blob_proto.h"
2002-12-16 17:25:09 +01:00
DATABASE DB = STATIC "yachts.lnk";
2001-05-23 15:26:42 +02:00
2003-10-16 10:51:06 +02:00
static void copy_exact_name (const UCHAR*, UCHAR*, SSHORT);
static ISC_STATUS copy_status(const ISC_STATUS*, ISC_STATUS*);
static ISC_STATUS error(ISC_STATUS*, SSHORT, ...);
2001-05-23 15:26:42 +02:00
void API_ROUTINE isc_blob_default_desc(
2003-10-16 10:51:06 +02:00
ISC_BLOB_DESC* desc,
const UCHAR* relation_name,
const UCHAR* field_name)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* i s c _ b l o b _ d e f a u l t _ d e s c
*
**************************************
*
* Functional description
*
* This function will set the default
* values in the blob_descriptor.
*
**************************************/
desc->blob_desc_subtype = isc_blob_text;
2001-05-23 15:26:42 +02:00
desc->blob_desc_charset = CS_dynamic;
desc->blob_desc_segment_size = 80;
2002-06-29 08:56:51 +02:00
copy_exact_name (field_name, desc->blob_desc_field_name,
sizeof(desc->blob_desc_field_name));
copy_exact_name (relation_name, desc->blob_desc_relation_name,
sizeof(desc->blob_desc_relation_name));
2001-05-23 15:26:42 +02:00
}
2003-04-10 08:32:58 +02:00
ISC_STATUS API_ROUTINE isc_blob_gen_bpb(
2003-10-16 10:51:06 +02:00
ISC_STATUS* status,
const ISC_BLOB_DESC* to_desc,
const ISC_BLOB_DESC* from_desc,
USHORT bpb_buffer_length,
UCHAR* bpb_buffer,
USHORT* bpb_length)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* i s c _ b l o b _ g e n _ b p b
*
**************************************
*
* Functional description
*
* This function will generate a bpb
* given a to_desc and a from_desc
* which contain the subtype and
* character set information.
*
**************************************/
if (bpb_buffer_length < 17)
2003-11-08 00:27:24 +01:00
return error(status, 3, (ISC_STATUS) isc_random,
(ISC_STATUS) isc_arg_string,
2003-04-10 08:32:58 +02:00
(ISC_STATUS) "BPB buffer too small");
2001-05-23 15:26:42 +02:00
2003-10-16 10:51:06 +02:00
UCHAR* p = bpb_buffer;
2001-05-23 15:26:42 +02:00
*p++ = isc_bpb_version1;
*p++ = isc_bpb_target_type;
*p++ = 2;
*p++ = (UCHAR)to_desc->blob_desc_subtype;
*p++ = (UCHAR)(to_desc->blob_desc_subtype >> 8);
*p++ = isc_bpb_source_type;
*p++ = 2;
*p++ = (UCHAR)from_desc->blob_desc_subtype;
*p++ = (UCHAR)(from_desc->blob_desc_subtype >> 8);
*p++ = isc_bpb_target_interp;
*p++ = 2;
*p++ = (UCHAR)to_desc->blob_desc_charset;
*p++ = (UCHAR)(to_desc->blob_desc_charset >> 8);
*p++ = isc_bpb_source_interp;
*p++ = 2;
*p++ = (UCHAR)from_desc->blob_desc_charset;
*p++ = (UCHAR)(from_desc->blob_desc_charset >> 8);
*bpb_length = p - bpb_buffer;
2003-04-10 08:32:58 +02:00
return error(status, 1, (ISC_STATUS) FB_SUCCESS);
2001-05-23 15:26:42 +02:00
}
2003-10-16 10:51:06 +02:00
ISC_STATUS API_ROUTINE isc_blob_lookup_desc(ISC_STATUS* status,
2004-05-03 01:06:37 +02:00
FB_API_HANDLE* db_handle,
FB_API_HANDLE* trans_handle,
2003-10-16 10:51:06 +02:00
const UCHAR* relation_name,
const UCHAR* field_name,
ISC_BLOB_DESC* desc, UCHAR* global)
2001-05-23 15:26:42 +02:00
{
/***********************************************
*
* i s c _ b l o b _ l o o k u p _ d e s c
*
***********************************************
*
* Functional description
*
* This routine will lookup the subtype,
* character set and segment size information
* from the metadata, given a relation name
* and column name. it will fill in the information
* in the BLOB_DESC.
*
***********************************************/
if (DB && DB != *db_handle)
RELEASE_REQUESTS;
DB = *db_handle;
2001-12-24 03:51:06 +01:00
gds_trans = *trans_handle;
2002-06-29 08:56:51 +02:00
copy_exact_name (field_name, desc->blob_desc_field_name,
sizeof(desc->blob_desc_field_name));
copy_exact_name (relation_name, desc->blob_desc_relation_name,
sizeof(desc->blob_desc_relation_name));
2001-05-23 15:26:42 +02:00
2003-10-16 10:51:06 +02:00
bool flag = false;
2001-05-23 15:26:42 +02:00
FOR X IN RDB$RELATION_FIELDS CROSS Y IN RDB$FIELDS
WITH X.RDB$FIELD_SOURCE EQ Y.RDB$FIELD_NAME AND
X.RDB$RELATION_NAME EQ desc->blob_desc_relation_name AND
2003-10-16 10:51:06 +02:00
X.RDB$FIELD_NAME EQ desc->blob_desc_field_name
flag = true;
2001-05-23 15:26:42 +02:00
2002-06-29 08:56:51 +02:00
desc->blob_desc_subtype = Y.RDB$FIELD_SUB_TYPE;
desc->blob_desc_charset = Y.RDB$CHARACTER_SET_ID;
desc->blob_desc_segment_size = Y.RDB$SEGMENT_LENGTH;
if (global) {
2003-10-16 10:51:06 +02:00
copy_exact_name ((UCHAR*) Y.RDB$FIELD_NAME, global,
2002-06-29 08:56:51 +02:00
sizeof(Y.RDB$FIELD_NAME));
}
END_FOR
ON_ERROR
return copy_status(gds_status, status);
2001-05-23 15:26:42 +02:00
END_ERROR;
if (!flag)
2003-11-08 00:27:24 +01:00
return error(status, 5, (ISC_STATUS) isc_fldnotdef,
(ISC_STATUS) isc_arg_string,
2003-04-10 08:32:58 +02:00
(ISC_STATUS) desc->blob_desc_field_name,
2003-11-08 00:27:24 +01:00
(ISC_STATUS) isc_arg_string,
2003-04-10 08:32:58 +02:00
(ISC_STATUS) desc->blob_desc_relation_name);
2001-05-23 15:26:42 +02:00
2003-04-10 08:32:58 +02:00
return error(status, 1, (ISC_STATUS) FB_SUCCESS);
2001-05-23 15:26:42 +02:00
}
2003-10-16 10:51:06 +02:00
ISC_STATUS API_ROUTINE isc_blob_set_desc(ISC_STATUS* status,
const UCHAR* relation_name,
const UCHAR* field_name,
2001-05-23 15:26:42 +02:00
SSHORT subtype,
SSHORT charset,
SSHORT segment_size,
2003-10-16 10:51:06 +02:00
ISC_BLOB_DESC* desc)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* i s c _ b l o b _ s e t _ d e s c
*
**************************************
*
* Functional description
*
* This routine will set the subtype
* and character set information in the
* BLOB_DESC based on the information
* specifically passed in by the user.
*
**************************************/
2002-06-29 08:56:51 +02:00
copy_exact_name (field_name, desc->blob_desc_field_name,
sizeof(desc->blob_desc_field_name));
copy_exact_name (relation_name, desc->blob_desc_relation_name,
sizeof(desc->blob_desc_relation_name));
2001-05-23 15:26:42 +02:00
desc->blob_desc_subtype = subtype;
desc->blob_desc_charset = charset;
desc->blob_desc_segment_size = segment_size;
2003-04-10 08:32:58 +02:00
return error(status, 1, (ISC_STATUS) FB_SUCCESS);
2001-05-23 15:26:42 +02:00
}
2002-06-29 08:56:51 +02:00
static void copy_exact_name (
2003-10-16 10:51:06 +02:00
const UCHAR* from,
UCHAR* to,
SSHORT bsize)
2002-06-29 08:56:51 +02:00
{
/**************************************
*
* c o p y _ e x a c t _ n a m e
*
**************************************
*
* Functional description
* Copy null terminated name ot stops at bsize - 1.
* CVC: This is just another fc like DYN_terminate.
*
**************************************/
2003-10-16 10:51:06 +02:00
const UCHAR* const from_end = from + bsize - 1;
UCHAR *to2 = to - 1;
while (*from && from < from_end) {
if (*from != ' ') {
to2 = to;
}
*to++ = *from++;
}
*++to2 = 0;
2002-06-29 08:56:51 +02:00
}
2003-10-16 10:51:06 +02:00
static ISC_STATUS copy_status( const ISC_STATUS* from, ISC_STATUS* to)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* c o p y _ s t a t u s
*
**************************************
*
* Functional description
* Copy a status vector.
*
**************************************/
2003-10-16 10:51:06 +02:00
const ISC_STATUS status = from[1];
2001-05-23 15:26:42 +02:00
2003-10-16 10:51:06 +02:00
const ISC_STATUS* const end = from + ISC_STATUS_LENGTH;
while (from < end)
2001-05-23 15:26:42 +02:00
*to++ = *from++;
return status;
}
2003-10-16 10:51:06 +02:00
static ISC_STATUS error( ISC_STATUS* status, SSHORT count, ...)
2001-05-23 15:26:42 +02:00
{
/**************************************
*
* e r r o r
*
**************************************
*
* Functional description
* Stuff a status vector.
*
**************************************/
2003-04-10 08:32:58 +02:00
ISC_STATUS *stat;
2001-05-23 15:26:42 +02:00
va_list ptr;
va_start(ptr, count);
2001-05-23 15:26:42 +02:00
stat = status;
2003-11-08 00:27:24 +01:00
*stat++ = isc_arg_gds;
2001-05-23 15:26:42 +02:00
for (; count; --count)
2003-04-10 08:32:58 +02:00
*stat++ = (ISC_STATUS) va_arg(ptr, ISC_STATUS);
2001-05-23 15:26:42 +02:00
va_end(ptr);
2003-11-08 00:27:24 +01:00
*stat = isc_arg_end;
2001-05-23 15:26:42 +02:00
return status[1];
}