1/*
2 * PROGRAM: JRD access method
3 * MODULE: dsc.h
4 * DESCRIPTION: Definitions associated with descriptors
5 *
6 * The contents of this file are subject to the Interbase Public
7 * License Version 1.0 (the "License"); you may not use this file
8 * except in compliance with the License. You may obtain a copy
9 * of the License at http://www.Inprise.com/IPL.html
10 *
11 * Software distributed under the License is distributed on an
12 * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
13 * or implied. See the License for the specific language governing
14 * rights and limitations under the License.
15 *
16 * The Original Code was created by Inprise Corporation
17 * and its predecessors. Portions created by Inprise Corporation are
18 * Copyright (C) Inprise Corporation.
19 *
20 * All Rights Reserved.
21 * Contributor(s): ______________________________________.
22 * 2002.04.16 Paul Beach - HP10 Define changed from -4 to (-4) to make it
23 * compatible with the HP Compiler
24 * Adriano dos Santos Fernandes
25 */
26
27#ifndef JRD_DSC_H
28#define JRD_DSC_H
29
30#include "../common/dsc_pub.h"
31#include "consts_pub.h"
32#include "../jrd/ods.h"
33#include "../intl/charsets.h"
34
35// Data type information
36
37inline bool DTYPE_IS_TEXT(UCHAR d)
38{
39 return d >= dtype_text && d <= dtype_varying;
40}
41
42inline bool DTYPE_IS_DATE(UCHAR t)
43{
44 return t >= dtype_sql_date && t <= dtype_timestamp;
45}
46
47// DTYPE_IS_BLOB includes both BLOB and ARRAY since array's are implemented over blobs.
48inline bool DTYPE_IS_BLOB(UCHAR d)
49{
50 return d == dtype_blob || d == dtype_array;
51}
52
53// DTYPE_IS_BLOB_OR_QUAD includes both BLOB, QUAD and ARRAY since array's are implemented over blobs.
54inline bool DTYPE_IS_BLOB_OR_QUAD(UCHAR d)
55{
56 return d == dtype_blob || d == dtype_quad || d == dtype_array;
57}
58
59// Exact numeric?
60inline bool DTYPE_IS_EXACT(UCHAR d)
61{
62 return d == dtype_int64 || d == dtype_long || d == dtype_short;
63}
64
65inline bool DTYPE_IS_APPROX(UCHAR d)
66{
67 return d == dtype_double || d == dtype_real;
68}
69
70inline bool DTYPE_IS_NUMERIC(UCHAR d)
71{
72 return (d >= dtype_byte && d <= dtype_d_float) || d == dtype_int64;
73}
74
75// Descriptor format
76
77typedef struct dsc
78{
79 dsc()
80 : dsc_dtype(0),
81 dsc_scale(0),
82 dsc_length(0),
83 dsc_sub_type(0),
84 dsc_flags(0),
85 dsc_address(0)
86 {}
87
88 UCHAR dsc_dtype;
89 SCHAR dsc_scale;
90 USHORT dsc_length;
91 SSHORT dsc_sub_type;
92 USHORT dsc_flags;
93 UCHAR* dsc_address; // Used either as offset in a message or as a pointer
94
95#ifdef __cplusplus
96 SSHORT dsc_blob_ttype() const { return dsc_scale | (dsc_flags & 0xFF00);}
97 SSHORT& dsc_ttype() { return dsc_sub_type;}
98 SSHORT dsc_ttype() const { return dsc_sub_type;}
99
100 bool isNullable() const
101 {
102 return dsc_flags & DSC_nullable;
103 }
104
105 void setNullable(bool nullable)
106 {
107 if (nullable)
108 dsc_flags |= DSC_nullable;
109 else
110 dsc_flags &= ~(DSC_nullable | DSC_null);
111 }
112
113 bool isNull() const
114 {
115 return dsc_flags & DSC_null;
116 }
117
118 void setNull()
119 {
120 dsc_flags |= DSC_null | DSC_nullable;
121 }
122
123 void clearNull()
124 {
125 dsc_flags &= ~DSC_null;
126 }
127
128 bool isBlob() const
129 {
130 return dsc_dtype == dtype_blob || dsc_dtype == dtype_quad;
131 }
132
133 bool isExact() const
134 {
135 return dsc_dtype == dtype_int64 || dsc_dtype == dtype_long || dsc_dtype == dtype_short;
136 }
137
138 bool isText() const
139 {
140 return dsc_dtype >= dtype_text && dsc_dtype <= dtype_varying;
141 }
142
143 bool isDateTime() const
144 {
145 return dsc_dtype >= dtype_sql_date && dsc_dtype <= dtype_timestamp;
146 }
147
148 bool isUnknown() const
149 {
150 return dsc_dtype == dtype_unknown;
151 }
152
153 SSHORT getBlobSubType() const
154 {
155 if (isBlob())
156 return dsc_sub_type;
157
158 return isc_blob_text;
159 }
160
161 void setBlobSubType(SSHORT subType)
162 {
163 if (isBlob())
164 dsc_sub_type = subType;
165 }
166
167 UCHAR getCharSet() const
168 {
169 if (isText())
170 return dsc_sub_type & 0xFF;
171
172 if (isBlob())
173 {
174 if (dsc_sub_type == isc_blob_text)
175 return dsc_scale;
176
177 return CS_BINARY;
178 }
179
180 return CS_NONE;
181 }
182
183 USHORT getTextType() const
184 {
185 if (isText())
186 return dsc_sub_type;
187
188 if (isBlob())
189 {
190 if (dsc_sub_type == isc_blob_text)
191 return dsc_scale | (dsc_flags & 0xFF00);
192
193 return CS_BINARY;
194 }
195
196 return CS_NONE;
197 }
198
199 void setTextType(USHORT ttype)
200 {
201 if (isText())
202 dsc_sub_type = ttype;
203 else if (isBlob() && dsc_sub_type == isc_blob_text)
204 {
205 dsc_scale = ttype & 0xFF;
206 dsc_flags = (dsc_flags & 0xFF) | (ttype & 0xFF00);
207 }
208 }
209
210 USHORT getCollation() const
211 {
212 return getTextType() >> 8;
213 }
214
215 void clear()
216 {
217 memset(this, 0, sizeof(*this));
218 }
219
220 void makeBlob(SSHORT subType, USHORT ttype, ISC_QUAD* address = NULL)
221 {
222 clear();
223 dsc_dtype = dtype_blob;
224 dsc_length = sizeof(ISC_QUAD);
225 setBlobSubType(subType);
226 setTextType(ttype);
227 dsc_address = (UCHAR*) address;
228 }
229
230 void makeDate(GDS_DATE* address = NULL)
231 {
232 clear();
233 dsc_dtype = dtype_sql_date;
234 dsc_length = sizeof(GDS_DATE);
235 dsc_address = (UCHAR*) address;
236 }
237
238 void makeDouble(double* address = NULL)
239 {
240 clear();
241 dsc_dtype = dtype_double;
242 dsc_length = sizeof(double);
243 dsc_address = (UCHAR*) address;
244 }
245
246 void makeInt64(SCHAR scale, SINT64* address = NULL)
247 {
248 clear();
249 dsc_dtype = dtype_int64;
250 dsc_length = sizeof(SINT64);
251 dsc_scale = scale;
252 dsc_address = (UCHAR*) address;
253 }
254
255 void makeLong(SCHAR scale, SLONG* address = NULL)
256 {
257 clear();
258 dsc_dtype = dtype_long;
259 dsc_length = sizeof(SLONG);
260 dsc_scale = scale;
261 dsc_address = (UCHAR*) address;
262 }
263
264 void makeBoolean(UCHAR* address = NULL)
265 {
266 clear();
267 dsc_dtype = dtype_boolean;
268 dsc_length = sizeof(UCHAR);
269 dsc_address = address;
270 }
271
272 void makeNullString()
273 {
274 clear();
275
276 // CHAR(1) CHARACTER SET NONE
277 dsc_dtype = dtype_text;
278 setTextType(CS_NONE);
279 dsc_length = 1;
280 dsc_flags = DSC_nullable | DSC_null;
281 }
282
283 void makeShort(SCHAR scale, SSHORT* address = NULL)
284 {
285 clear();
286 dsc_dtype = dtype_short;
287 dsc_length = sizeof(SSHORT);
288 dsc_scale = scale;
289 dsc_address = (UCHAR*) address;
290 }
291
292 void makeText(USHORT length, USHORT ttype, UCHAR* address = NULL)
293 {
294 clear();
295 dsc_dtype = dtype_text;
296 dsc_length = length;
297 setTextType(ttype);
298 dsc_address = address;
299 }
300
301 void makeTime(GDS_TIME* address = NULL)
302 {
303 clear();
304 dsc_dtype = dtype_sql_time;
305 dsc_length = sizeof(GDS_TIME);
306 dsc_scale = 0;
307 dsc_address = (UCHAR*) address;
308 }
309
310 void makeTimestamp(GDS_TIMESTAMP* address = NULL)
311 {
312 clear();
313 dsc_dtype = dtype_timestamp;
314 dsc_length = sizeof(GDS_TIMESTAMP);
315 dsc_scale = 0;
316 dsc_address = (UCHAR*) address;
317 }
318
319 void makeVarying(USHORT length, USHORT ttype, UCHAR* address = NULL)
320 {
321 clear();
322 dsc_dtype = dtype_varying;
323 dsc_length = sizeof(USHORT) + length;
324 setTextType(ttype);
325 dsc_address = address;
326 }
327
328 int getStringLength() const;
329
330 // These functions were added to have interoperability
331 // between Ods::Descriptor and struct dsc
332 dsc(const Ods::Descriptor& od)
333 : dsc_dtype(od.dsc_dtype),
334 dsc_scale(od.dsc_scale),
335 dsc_length(od.dsc_length),
336 dsc_sub_type(od.dsc_sub_type),
337 dsc_flags(od.dsc_flags),
338 dsc_address((UCHAR*)(IPTR)(od.dsc_offset))
339 {}
340
341 operator Ods::Descriptor() const
342 {
343#ifdef DEV_BUILD
344 address32bit();
345#endif
346 Ods::Descriptor d;
347 d.dsc_dtype = dsc_dtype;
348 d.dsc_scale = dsc_scale;
349 d.dsc_length = dsc_length;
350 d.dsc_sub_type = dsc_sub_type;
351 d.dsc_flags = dsc_flags;
352 d.dsc_offset = (ULONG)(IPTR)dsc_address;
353 return d;
354 }
355
356#ifdef DEV_BUILD
357 void address32bit() const;
358#endif
359
360 const char* typeToText() const;
361 void getSqlInfo(SLONG* sqlLength, SLONG* sqlSubType, SLONG* sqlScale, SLONG* sqlType) const;
362#endif // __cpluplus
363} DSC;
364
365inline SSHORT DSC_GET_CHARSET(const dsc* desc)
366{
367 return (desc->dsc_sub_type & 0x00FF);
368}
369
370inline SSHORT DSC_GET_COLLATE(const dsc* desc)
371{
372 return (desc->dsc_sub_type >> 8);
373}
374
375struct alt_dsc
376{
377 SLONG dsc_combined_type;
378 SSHORT dsc_sub_type;
379 USHORT dsc_flags; // Not currently used
380};
381
382inline bool DSC_EQUIV(const dsc* d1, const dsc* d2, bool check_collate)
383{
384 if (((alt_dsc*) d1)->dsc_combined_type == ((alt_dsc*) d2)->dsc_combined_type)
385 {
386 if (d1->dsc_dtype >= dtype_text && d1->dsc_dtype <= dtype_varying)
387 {
388 if (DSC_GET_CHARSET(d1) == DSC_GET_CHARSET(d2))
389 {
390 if (check_collate) {
391 return (DSC_GET_COLLATE(d1) == DSC_GET_COLLATE(d2));
392 }
393 return true;
394 }
395 return false;
396 }
397 return true;
398 }
399 return false;
400}
401
402// In DSC_*_result tables, DTYPE_CANNOT means that the two operands
403// cannot participate together in the requested operation.
404
405const UCHAR DTYPE_CANNOT = 127;
406
407// Historical alias definition
408const UCHAR dtype_date = dtype_timestamp;
409
410const UCHAR dtype_aligned = dtype_varying;
411const UCHAR dtype_any_text = dtype_varying;
412const UCHAR dtype_min_comp = dtype_packed;
413const UCHAR dtype_max_comp = dtype_d_float;
414
415// NOTE: For types <= dtype_any_text the dsc_sub_type field defines the text type
416
417inline USHORT TEXT_LEN(const dsc* desc)
418{
419 return ((desc->dsc_dtype == dtype_text) ?
420 desc->dsc_length :
421 (desc->dsc_dtype == dtype_cstring) ?
422 desc->dsc_length - 1u : desc->dsc_length - sizeof(USHORT));
423}
424
425
426// Text Sub types, distinct from character sets & collations
427
428const SSHORT dsc_text_type_none = 0; // Normal text
429const SSHORT dsc_text_type_fixed = 1; // strings can contain null bytes
430const SSHORT dsc_text_type_ascii = 2; // string contains only ASCII characters
431const SSHORT dsc_text_type_metadata = 3; // string represents system metadata
432
433
434// Exact numeric subtypes: with ODS >= 10, these apply when dtype
435// is short, long, or quad.
436
437const SSHORT dsc_num_type_none = 0; // defined as SMALLINT or INTEGER
438const SSHORT dsc_num_type_numeric = 1; // defined as NUMERIC(n,m)
439const SSHORT dsc_num_type_decimal = 2; // defined as DECIMAL(n,m)
440
441// Date type information
442
443inline SCHAR NUMERIC_SCALE(const dsc desc)
444{
445 return ((DTYPE_IS_TEXT(desc.dsc_dtype)) ? 0 : desc.dsc_scale);
446}
447
448#endif // JRD_DSC_H
449