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 | |
37 | inline bool DTYPE_IS_TEXT(UCHAR d) |
38 | { |
39 | return d >= dtype_text && d <= dtype_varying; |
40 | } |
41 | |
42 | inline 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. |
48 | inline 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. |
54 | inline 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? |
60 | inline bool DTYPE_IS_EXACT(UCHAR d) |
61 | { |
62 | return d == dtype_int64 || d == dtype_long || d == dtype_short; |
63 | } |
64 | |
65 | inline bool DTYPE_IS_APPROX(UCHAR d) |
66 | { |
67 | return d == dtype_double || d == dtype_real; |
68 | } |
69 | |
70 | inline 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 | |
77 | typedef 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 | |
365 | inline SSHORT DSC_GET_CHARSET(const dsc* desc) |
366 | { |
367 | return (desc->dsc_sub_type & 0x00FF); |
368 | } |
369 | |
370 | inline SSHORT DSC_GET_COLLATE(const dsc* desc) |
371 | { |
372 | return (desc->dsc_sub_type >> 8); |
373 | } |
374 | |
375 | struct alt_dsc |
376 | { |
377 | SLONG dsc_combined_type; |
378 | SSHORT dsc_sub_type; |
379 | USHORT dsc_flags; // Not currently used |
380 | }; |
381 | |
382 | inline 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 | |
405 | const UCHAR DTYPE_CANNOT = 127; |
406 | |
407 | // Historical alias definition |
408 | const UCHAR dtype_date = dtype_timestamp; |
409 | |
410 | const UCHAR dtype_aligned = dtype_varying; |
411 | const UCHAR dtype_any_text = dtype_varying; |
412 | const UCHAR dtype_min_comp = dtype_packed; |
413 | const 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 | |
417 | inline 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 | |
428 | const SSHORT dsc_text_type_none = 0; // Normal text |
429 | const SSHORT dsc_text_type_fixed = 1; // strings can contain null bytes |
430 | const SSHORT dsc_text_type_ascii = 2; // string contains only ASCII characters |
431 | const 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 | |
437 | const SSHORT dsc_num_type_none = 0; // defined as SMALLINT or INTEGER |
438 | const SSHORT dsc_num_type_numeric = 1; // defined as NUMERIC(n,m) |
439 | const SSHORT dsc_num_type_decimal = 2; // defined as DECIMAL(n,m) |
440 | |
441 | // Date type information |
442 | |
443 | inline 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 | |