mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-27 06:43:04 +01:00
403 lines
8.8 KiB
C
403 lines
8.8 KiB
C
/*
|
|
* PROGRAM: JRD access method
|
|
* MODULE: dsc.h
|
|
* DESCRIPTION: Definitions associated with descriptors
|
|
*
|
|
* 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.04.16 Paul Beach - HP10 Define changed from -4 to (-4) to make it
|
|
* compatible with the HP Compiler
|
|
* Adriano dos Santos Fernandes
|
|
*/
|
|
|
|
#ifndef JRD_DSC_H
|
|
#define JRD_DSC_H
|
|
|
|
#include "../jrd/dsc_pub.h"
|
|
#include "consts_pub.h"
|
|
#include "../jrd/ods.h"
|
|
#include "../intl/charsets.h"
|
|
|
|
/* Data type information */
|
|
|
|
inline bool DTYPE_IS_TEXT(UCHAR d)
|
|
{
|
|
return ((d >= dtype_text) && (d <= dtype_varying));
|
|
}
|
|
|
|
inline bool DTYPE_IS_DATE(UCHAR t)
|
|
{
|
|
return ((t >= dtype_sql_date) && (t <= dtype_timestamp));
|
|
}
|
|
|
|
/* DTYPE_IS_BLOB includes both BLOB and ARRAY since array's are implemented over blobs. */
|
|
inline bool DTYPE_IS_BLOB(UCHAR d)
|
|
{
|
|
return ((d == dtype_blob) || (d == dtype_array));
|
|
}
|
|
|
|
/* DTYPE_IS_BLOB_OR_QUAD includes both BLOB, QUAD and ARRAY since array's are implemented over blobs. */
|
|
inline bool DTYPE_IS_BLOB_OR_QUAD(UCHAR d)
|
|
{
|
|
return ((d == dtype_blob) || (d == dtype_quad) || (d == dtype_array));
|
|
}
|
|
|
|
/* Exact numeric? */
|
|
inline bool DTYPE_IS_EXACT(UCHAR d)
|
|
{
|
|
return ((d == dtype_int64) || (d == dtype_long) || (d == dtype_short));
|
|
}
|
|
|
|
inline bool DTYPE_IS_APPROX(UCHAR d)
|
|
{
|
|
return ((d == dtype_double) || (d == dtype_real));
|
|
}
|
|
|
|
inline bool DTYPE_IS_NUMERIC(UCHAR d)
|
|
{
|
|
return (((d >= dtype_byte) && (d <= dtype_d_float)) || (d == dtype_int64));
|
|
}
|
|
|
|
/* Descriptor format */
|
|
|
|
typedef struct dsc
|
|
{
|
|
dsc()
|
|
: dsc_dtype(0),
|
|
dsc_scale(0),
|
|
dsc_length(0),
|
|
dsc_sub_type(0),
|
|
dsc_flags(0),
|
|
dsc_address(0)
|
|
{}
|
|
|
|
UCHAR dsc_dtype;
|
|
SCHAR dsc_scale;
|
|
USHORT dsc_length;
|
|
SSHORT dsc_sub_type;
|
|
USHORT dsc_flags;
|
|
UCHAR* dsc_address; // Used either as offset in a message or as a pointer
|
|
|
|
#ifdef __cplusplus
|
|
SSHORT dsc_blob_ttype() const { return dsc_scale | (dsc_flags & 0xFF00);}
|
|
SSHORT& dsc_ttype() { return dsc_sub_type;}
|
|
SSHORT dsc_ttype() const { return dsc_sub_type;}
|
|
|
|
bool isNullable() const
|
|
{
|
|
return dsc_flags & DSC_nullable;
|
|
}
|
|
|
|
void setNullable(bool nullable)
|
|
{
|
|
if (nullable)
|
|
dsc_flags |= DSC_nullable;
|
|
else
|
|
dsc_flags &= ~(DSC_nullable | DSC_null);
|
|
}
|
|
|
|
bool isNull() const
|
|
{
|
|
return dsc_flags & DSC_null;
|
|
}
|
|
|
|
void setNull()
|
|
{
|
|
dsc_flags |= DSC_null | DSC_nullable;
|
|
}
|
|
|
|
bool isBlob() const
|
|
{
|
|
return dsc_dtype == dtype_blob || dsc_dtype == dtype_quad;
|
|
}
|
|
|
|
bool isExact() const
|
|
{
|
|
return ((dsc_dtype == dtype_int64) || (dsc_dtype == dtype_long) || (dsc_dtype == dtype_short));
|
|
}
|
|
|
|
bool isText() const
|
|
{
|
|
return (dsc_dtype >= dtype_text) && (dsc_dtype <= dtype_varying);
|
|
}
|
|
|
|
bool isUnknown() const
|
|
{
|
|
return dsc_dtype == dtype_unknown;
|
|
}
|
|
|
|
SSHORT getBlobSubType() const
|
|
{
|
|
if (isBlob())
|
|
return dsc_sub_type;
|
|
|
|
return isc_blob_text;
|
|
}
|
|
|
|
void setBlobSubType(SSHORT subType)
|
|
{
|
|
if (isBlob())
|
|
dsc_sub_type = subType;
|
|
}
|
|
|
|
UCHAR getCharSet() const
|
|
{
|
|
if (isText())
|
|
return dsc_sub_type & 0xFF;
|
|
|
|
if (isBlob())
|
|
{
|
|
if (dsc_sub_type == isc_blob_text)
|
|
return dsc_scale;
|
|
|
|
return CS_BINARY;
|
|
}
|
|
|
|
return CS_ASCII;
|
|
}
|
|
|
|
USHORT getTextType() const
|
|
{
|
|
if (isText())
|
|
return dsc_sub_type;
|
|
|
|
if (isBlob())
|
|
{
|
|
if (dsc_sub_type == isc_blob_text)
|
|
return dsc_scale | (dsc_flags & 0xFF00);
|
|
|
|
return CS_BINARY;
|
|
}
|
|
|
|
return CS_ASCII;
|
|
}
|
|
|
|
void setTextType(USHORT ttype)
|
|
{
|
|
if (isText())
|
|
dsc_sub_type = ttype;
|
|
else if (isBlob() && dsc_sub_type == isc_blob_text)
|
|
{
|
|
dsc_scale = ttype & 0xFF;
|
|
dsc_flags = (dsc_flags & 0xFF) | (ttype & 0xFF00);
|
|
}
|
|
}
|
|
|
|
void clear()
|
|
{
|
|
memset(this, 0, sizeof(*this));
|
|
}
|
|
|
|
void makeBlob(SSHORT subType, USHORT ttype, ISC_QUAD* address = NULL)
|
|
{
|
|
clear();
|
|
dsc_dtype = dtype_blob;
|
|
dsc_length = sizeof(ISC_QUAD);
|
|
setBlobSubType(subType);
|
|
setTextType(ttype);
|
|
dsc_address = (UCHAR*) address;
|
|
}
|
|
|
|
void makeDouble(double* address = NULL)
|
|
{
|
|
clear();
|
|
dsc_dtype = dtype_double;
|
|
dsc_length = sizeof(double);
|
|
dsc_address = (UCHAR*) address;
|
|
}
|
|
|
|
void makeInt64(SCHAR scale, SINT64* address = NULL)
|
|
{
|
|
clear();
|
|
dsc_dtype = dtype_int64;
|
|
dsc_length = sizeof(SINT64);
|
|
dsc_scale = scale;
|
|
dsc_address = (UCHAR*) address;
|
|
}
|
|
|
|
void makeLong(SCHAR scale, SLONG* address = NULL)
|
|
{
|
|
clear();
|
|
dsc_dtype = dtype_long;
|
|
dsc_length = sizeof(SLONG);
|
|
dsc_scale = scale;
|
|
dsc_address = (UCHAR*) address;
|
|
}
|
|
|
|
void makeNullString()
|
|
{
|
|
clear();
|
|
|
|
// VARCHAR(1) CHARACTER SET NONE
|
|
dsc_dtype = dtype_varying;
|
|
setTextType(CS_NONE);
|
|
dsc_length = sizeof(USHORT) + 1;
|
|
dsc_flags = DSC_nullable | DSC_null;
|
|
}
|
|
|
|
void makeShort(SCHAR scale, SSHORT* address = NULL)
|
|
{
|
|
clear();
|
|
dsc_dtype = dtype_short;
|
|
dsc_length = sizeof(SSHORT);
|
|
dsc_scale = scale;
|
|
dsc_address = (UCHAR*) address;
|
|
}
|
|
|
|
void makeText(USHORT length, USHORT ttype, UCHAR* address = NULL)
|
|
{
|
|
clear();
|
|
dsc_dtype = dtype_text;
|
|
dsc_length = length;
|
|
setTextType(ttype);
|
|
dsc_address = address;
|
|
}
|
|
|
|
void makeTimestamp(GDS_TIMESTAMP* address = NULL)
|
|
{
|
|
clear();
|
|
dsc_dtype = dtype_timestamp;
|
|
dsc_length = sizeof(GDS_TIMESTAMP);
|
|
dsc_scale = 0;
|
|
dsc_address = (UCHAR*) address;
|
|
}
|
|
|
|
void makeVarying(USHORT length, USHORT ttype, UCHAR* address = NULL)
|
|
{
|
|
clear();
|
|
dsc_dtype = dtype_varying;
|
|
dsc_length = sizeof(USHORT) + length;
|
|
setTextType(ttype);
|
|
dsc_address = address;
|
|
}
|
|
|
|
int getStringLength() const;
|
|
#endif
|
|
|
|
// this functions were added to have interoperability
|
|
// between Ods::Descriptor and struct dsc
|
|
dsc(const Ods::Descriptor& od)
|
|
: dsc_dtype(od.dsc_dtype),
|
|
dsc_scale(od.dsc_scale),
|
|
dsc_length(od.dsc_length),
|
|
dsc_sub_type(od.dsc_sub_type),
|
|
dsc_flags(od.dsc_flags),
|
|
dsc_address((UCHAR*)(IPTR)(od.dsc_offset))
|
|
{}
|
|
|
|
operator Ods::Descriptor() const
|
|
{
|
|
#ifdef DEV_BUILD
|
|
address32bit();
|
|
#endif
|
|
Ods::Descriptor d;
|
|
d.dsc_dtype = dsc_dtype;
|
|
d.dsc_scale = dsc_scale;
|
|
d.dsc_length = dsc_length;
|
|
d.dsc_sub_type = dsc_sub_type;
|
|
d.dsc_flags = dsc_flags;
|
|
d.dsc_offset = (ULONG)(IPTR)dsc_address;
|
|
return d;
|
|
}
|
|
#ifdef DEV_BUILD
|
|
void address32bit() const;
|
|
#endif
|
|
|
|
} DSC;
|
|
|
|
inline SSHORT DSC_GET_CHARSET(const dsc* desc)
|
|
{
|
|
return (desc->dsc_sub_type & 0x00FF);
|
|
}
|
|
|
|
inline SSHORT DSC_GET_COLLATE(const dsc* desc)
|
|
{
|
|
return (desc->dsc_sub_type >> 8);
|
|
}
|
|
|
|
struct alt_dsc
|
|
{
|
|
SLONG dsc_combined_type;
|
|
SSHORT dsc_sub_type;
|
|
USHORT dsc_flags; /* Not currently used */
|
|
};
|
|
|
|
inline bool DSC_EQUIV(const dsc* d1, const dsc* d2, bool check_collate)
|
|
{
|
|
if (((alt_dsc*) d1)->dsc_combined_type == ((alt_dsc*) d2)->dsc_combined_type)
|
|
{
|
|
if (d1->dsc_dtype >= dtype_text && d1->dsc_dtype <= dtype_varying) {
|
|
if (DSC_GET_CHARSET(d1) == DSC_GET_CHARSET(d2)) {
|
|
if (check_collate) {
|
|
return (DSC_GET_COLLATE(d1) == DSC_GET_COLLATE(d2));
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/* In DSC_*_result tables, DTYPE_CANNOT means that the two operands
|
|
cannot participate together in the requested operation. */
|
|
|
|
const UCHAR DTYPE_CANNOT = 127;
|
|
|
|
/* Historical alias definition */
|
|
const UCHAR dtype_date = dtype_timestamp;
|
|
|
|
const UCHAR dtype_aligned = dtype_varying;
|
|
const UCHAR dtype_any_text = dtype_varying;
|
|
const UCHAR dtype_min_comp = dtype_packed;
|
|
const UCHAR dtype_max_comp = dtype_d_float;
|
|
|
|
/* NOTE: For types <= dtype_any_text the dsc_sub_type field defines
|
|
the text type */
|
|
|
|
inline USHORT TEXT_LEN(const dsc* desc)
|
|
{
|
|
return ((desc->dsc_dtype == dtype_text) ? desc->dsc_length :
|
|
(desc->dsc_dtype == dtype_cstring) ? desc->dsc_length - 1 : desc->dsc_length - sizeof(USHORT));
|
|
}
|
|
|
|
|
|
/* Text Sub types, distinct from character sets & collations */
|
|
|
|
const SSHORT dsc_text_type_none = 0; /* Normal text */
|
|
const SSHORT dsc_text_type_fixed = 1; /* strings can contain null bytes */
|
|
const SSHORT dsc_text_type_ascii = 2; /* string contains only ASCII characters */
|
|
const SSHORT dsc_text_type_metadata = 3; /* string represents system metadata */
|
|
|
|
|
|
/* Exact numeric subtypes: with ODS >= 10, these apply when dtype
|
|
is short, long, or quad. */
|
|
|
|
const SSHORT dsc_num_type_none = 0; /* defined as SMALLINT or INTEGER */
|
|
const SSHORT dsc_num_type_numeric = 1; /* defined as NUMERIC(n,m) */
|
|
const SSHORT dsc_num_type_decimal = 2; /* defined as DECIMAL(n,m) */
|
|
|
|
/* Date type information */
|
|
|
|
inline SCHAR NUMERIC_SCALE(const dsc desc)
|
|
{
|
|
return ((DTYPE_IS_TEXT(desc.dsc_dtype)) ? 0 : desc.dsc_scale);
|
|
}
|
|
|
|
#endif /* JRD_DSC_H */
|