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

311 lines
8.1 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>
#include "../jrd/gds.h"
2001-05-23 15:26:42 +02:00
#include "../jrd/intl.h"
#include "../jrd/constants.h"
#include "../dsql/blob_proto.h"
//DATABASE DB = STATIC "yachts.lnk";
DATABASE DB = STATIC "ok:C:\GDB\ODS.RDB";
2001-05-23 15:26:42 +02:00
2002-06-29 08:56:51 +02:00
static void copy_exact_name (UCHAR *, UCHAR *, SSHORT);
2001-05-23 15:26:42 +02:00
static STATUS copy_status(STATUS *, STATUS *);
static STATUS error(STATUS *, SSHORT, ...);
void API_ROUTINE isc_blob_default_desc(
ISC_BLOB_DESC * desc,
UCHAR * relation_name,
UCHAR * field_name)
{
/**************************************
*
* 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 = BLOB_text;
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
}
STATUS API_ROUTINE isc_blob_gen_bpb(
STATUS * status,
ISC_BLOB_DESC * to_desc,
ISC_BLOB_DESC * from_desc,
USHORT bpb_buffer_length, UCHAR * bpb_buffer, USHORT * bpb_length)
{
/**************************************
*
* 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.
*
**************************************/
UCHAR *p;
if (bpb_buffer_length < 17)
return error(status, 3, (STATUS) gds_random,
2001-05-23 15:26:42 +02:00
(STATUS) gds_arg_string,
(STATUS) "BPB buffer too small");
p = bpb_buffer;
*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;
return error(status, 1, (STATUS) FB_SUCCESS);
2001-05-23 15:26:42 +02:00
}
STATUS API_ROUTINE isc_blob_lookup_desc(STATUS * status,
FRBRD **db_handle,
FRBRD **trans_handle,
2001-05-23 15:26:42 +02:00
UCHAR * relation_name,
UCHAR * field_name,
ISC_BLOB_DESC * desc, UCHAR * global)
{
/***********************************************
*
* 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.
*
***********************************************/
SSHORT flag;
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
flag = FALSE;
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
X.RDB$FIELD_NAME EQ desc->blob_desc_field_name flag = TRUE;
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) {
copy_exact_name ((UCHAR *) Y.RDB$FIELD_NAME, global,
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)
return error(status, 5, (STATUS) gds_fldnotdef,
2001-05-23 15:26:42 +02:00
(STATUS) gds_arg_string,
(STATUS) desc->blob_desc_field_name,
(STATUS) gds_arg_string,
(STATUS) desc->blob_desc_relation_name);
return error(status, 1, (STATUS) FB_SUCCESS);
2001-05-23 15:26:42 +02:00
}
STATUS API_ROUTINE isc_blob_set_desc(STATUS * status,
UCHAR * relation_name,
UCHAR * field_name,
SSHORT subtype,
SSHORT charset,
SSHORT segment_size,
ISC_BLOB_DESC * desc)
{
/**************************************
*
* 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;
return error(status, 1, (STATUS) FB_SUCCESS);
2001-05-23 15:26:42 +02:00
}
2002-06-29 08:56:51 +02:00
static void copy_exact_name (
UCHAR *from,
UCHAR *to,
SSHORT bsize)
{
/**************************************
*
* 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.
*
**************************************/
UCHAR *from_end = from + bsize - 1, *to2 = to - 1;
while (*from && from < from_end) {
if (*from != ' ') {
to2 = to;
}
*to++ = *from++;
}
*++to2 = 0;
}
2001-05-23 15:26:42 +02:00
static STATUS copy_status( STATUS * from, STATUS * to)
{
/**************************************
*
* c o p y _ s t a t u s
*
**************************************
*
* Functional description
* Copy a status vector.
*
**************************************/
STATUS status, *end;
status = from[1];
for (end = from + 20; from < end;)
*to++ = *from++;
return status;
}
static STATUS error( STATUS * status, SSHORT count, ...)
{
/**************************************
*
* e r r o r
*
**************************************
*
* Functional description
* Stuff a status vector.
*
**************************************/
STATUS *stat;
va_list ptr;
VA_START(ptr, count);
stat = status;
*stat++ = gds_arg_gds;
for (; count; --count)
*stat++ = (STATUS) va_arg(ptr, STATUS);
*stat = gds_arg_end;
return status[1];
}