2
* PROGRAM: JRD Access Method
4
* DESCRIPTION: Metadata initialization / population
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
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.
16
* The Original Code was created by Inprise Corporation
17
* and its predecessors. Portions created by Inprise Corporation are
18
* Copyright (C) Inprise Corporation.
20
* All Rights Reserved.
21
* Contributor(s): ______________________________________.
27
#include "../jrd/common.h"
28
#include "../jrd/flags.h"
29
#include "../jrd/jrd.h"
30
#include "../jrd/val.h"
31
#include "../jrd/ibase.h"
32
#include "../jrd/ods.h"
33
#include "../jrd/btr.h"
35
#include "../jrd/tra.h"
36
#include "../jrd/trig.h"
37
#include "../jrd/intl.h"
38
#include "../jrd/dflt.h"
39
#include "../jrd/ini.h"
40
#include "../jrd/idx.h"
41
#include "../jrd/gdsassert.h"
42
#include "../jrd/blb_proto.h"
43
#include "../jrd/cch_proto.h"
44
#include "../jrd/cmp_proto.h"
45
#include "../jrd/dfw_proto.h"
46
#include "../jrd/dpm_proto.h"
47
#include "../jrd/err_proto.h"
48
#include "../jrd/exe_proto.h"
49
#include "../jrd/gds_proto.h"
50
#include "../jrd/idx_proto.h"
51
#include "../jrd/ini_proto.h"
52
#include "../jrd/jrd_proto.h"
53
#include "../jrd/met_proto.h"
54
#include "../jrd/thd.h"
55
#include "../jrd/obj.h"
56
#include "../jrd/acl.h"
57
#include "../jrd/irq.h"
61
DATABASE DB = FILENAME "ODS.RDB";
63
#define PAD(string, field) jrd_vtof ((char*)(string), field, sizeof (field))
64
const int MAX_ACL_SIZE = 4096;
65
const char* DEFAULT_CLASS = "SQL$DEFAULT";
67
#ifdef NOT_USED_OR_REPLACED
68
static void add_generator(TEXT*, jrd_req**);
70
static void add_global_fields(USHORT);
71
static void add_index_set(Database*, bool, USHORT, USHORT);
72
static void add_new_triggers(USHORT, USHORT);
73
static void add_relation_fields(USHORT);
74
static void add_security_to_sys_rel(thread_db*, const Firebird::MetaName&,
75
const TEXT*, const UCHAR*, const SSHORT);
76
#ifdef NOT_USED_OR_REPLACED
77
static void add_trigger(TEXT*, jrd_req**, jrd_req**);
79
//static void add_user_priv(thread_db*, TEXT*, TEXT*, TEXT*, TEXT);
80
static int init2_helper(const int* fld, int n, jrd_rel* relation);
81
static void modify_relation_field(thread_db*, const int*, const int*, jrd_req**);
82
static void store_generator(thread_db*, const gen*, jrd_req**);
83
static void store_global_field(thread_db*, const gfld*, jrd_req**);
84
static void store_intlnames(thread_db*, Database*);
85
static void store_functions(thread_db*, Database*);
86
static void store_message(thread_db*, const trigger_msg*, jrd_req**);
87
static void store_relation_field(thread_db*, const int*, const int*, int, jrd_req**, bool);
88
static void store_trigger(thread_db*, const jrd_trg*, jrd_req**);
91
/* This is the table used in defining triggers; note that
92
RDB$TRIGGER_0 was first changed to RDB$TRIGGER_7 to make it easier to
93
upgrade a database to support field-level grant. It has since been
94
changed to RDB$TRIGGER_9 to handle SQL security on relations whose
95
name is > 27 characters */
97
static const jrd_trg triggers[] =
99
{ "RDB$TRIGGER_1", (UCHAR) nam_user_privileges,
100
RDB$TRIGGERS.RDB$TRIGGER_TYPE.PRE_MODIFY, sizeof(trigger3), trigger3,
102
{ "RDB$TRIGGER_8", (UCHAR) nam_user_privileges,
103
RDB$TRIGGERS.RDB$TRIGGER_TYPE.PRE_ERASE, sizeof(trigger2), trigger2,
105
{ "RDB$TRIGGER_9", (UCHAR) nam_user_privileges,
106
RDB$TRIGGERS.RDB$TRIGGER_TYPE.PRE_STORE, sizeof(trigger1), trigger1,
108
{ "RDB$TRIGGER_2", (UCHAR) nam_trgs,
109
RDB$TRIGGERS.RDB$TRIGGER_TYPE.PRE_MODIFY, sizeof(trigger4), trigger4,
111
{ "RDB$TRIGGER_3", (UCHAR) nam_trgs,
112
RDB$TRIGGERS.RDB$TRIGGER_TYPE.PRE_ERASE, sizeof(trigger4), trigger4,
114
{ "RDB$TRIGGER_4", (UCHAR) nam_relations,
115
RDB$TRIGGERS.RDB$TRIGGER_TYPE.PRE_STORE, sizeof(trigger5), trigger5,
117
{ "RDB$TRIGGER_5", (UCHAR) nam_relations,
118
RDB$TRIGGERS.RDB$TRIGGER_TYPE.PRE_MODIFY, sizeof(trigger6), trigger6,
120
{ "RDB$TRIGGER_6", (UCHAR) nam_gens,
121
RDB$TRIGGERS.RDB$TRIGGER_TYPE.PRE_STORE, sizeof(trigger7), trigger7,
123
{ "RDB$TRIGGER_26", (UCHAR) nam_rel_constr,
124
RDB$TRIGGERS.RDB$TRIGGER_TYPE.PRE_STORE, sizeof(trigger26), trigger26,
126
{ "RDB$TRIGGER_25", (UCHAR) nam_rel_constr,
127
RDB$TRIGGERS.RDB$TRIGGER_TYPE.PRE_MODIFY, sizeof(trigger25),
128
trigger25, 0, ODS_8_0 },
129
{ "RDB$TRIGGER_10", (UCHAR) nam_rel_constr,
130
RDB$TRIGGERS.RDB$TRIGGER_TYPE.PRE_ERASE, sizeof(trigger10), trigger10,
132
{ "RDB$TRIGGER_11", (UCHAR) nam_rel_constr,
133
RDB$TRIGGERS.RDB$TRIGGER_TYPE.POST_ERASE, sizeof(trigger11),
134
trigger11, 0, ODS_8_0 },
135
{ "RDB$TRIGGER_12", (UCHAR) nam_ref_constr,
136
RDB$TRIGGERS.RDB$TRIGGER_TYPE.PRE_STORE, sizeof(trigger12), trigger12,
138
{ "RDB$TRIGGER_13", (UCHAR) nam_ref_constr,
139
RDB$TRIGGERS.RDB$TRIGGER_TYPE.PRE_MODIFY, sizeof(trigger13),
140
trigger13, 0, ODS_8_0 },
141
{ "RDB$TRIGGER_14", (UCHAR) nam_chk_constr,
142
RDB$TRIGGERS.RDB$TRIGGER_TYPE.PRE_MODIFY, sizeof(trigger14),
143
trigger14, 0, ODS_8_0 },
144
{ "RDB$TRIGGER_15", (UCHAR) nam_chk_constr,
145
RDB$TRIGGERS.RDB$TRIGGER_TYPE.PRE_ERASE, sizeof(trigger15), trigger15,
147
{ "RDB$TRIGGER_16", (UCHAR) nam_chk_constr,
148
RDB$TRIGGERS.RDB$TRIGGER_TYPE.POST_ERASE, sizeof(trigger16),
149
trigger16, 0, ODS_8_0 },
150
{ "RDB$TRIGGER_17", (UCHAR) nam_i_segments,
151
RDB$TRIGGERS.RDB$TRIGGER_TYPE.PRE_ERASE, sizeof(trigger17), trigger17,
153
{ "RDB$TRIGGER_18", (UCHAR) nam_i_segments,
154
RDB$TRIGGERS.RDB$TRIGGER_TYPE.PRE_MODIFY, sizeof(trigger18),
155
trigger18, 0, ODS_8_0 },
156
{ "RDB$TRIGGER_19", (UCHAR) nam_indices,
157
RDB$TRIGGERS.RDB$TRIGGER_TYPE.PRE_ERASE, sizeof(trigger19), trigger19,
159
{ "RDB$TRIGGER_20", (UCHAR) nam_indices,
160
RDB$TRIGGERS.RDB$TRIGGER_TYPE.PRE_MODIFY, sizeof(trigger20),
161
trigger20, 0, ODS_8_0 },
162
{ "RDB$TRIGGER_21", (UCHAR) nam_trgs,
163
RDB$TRIGGERS.RDB$TRIGGER_TYPE.PRE_ERASE, sizeof(trigger21), trigger21,
165
{ "RDB$TRIGGER_22", (UCHAR) nam_trgs,
166
RDB$TRIGGERS.RDB$TRIGGER_TYPE.PRE_MODIFY, sizeof(trigger22),
167
trigger22, 0, ODS_8_0 },
168
{ "RDB$TRIGGER_23", (UCHAR) nam_r_fields,
169
RDB$TRIGGERS.RDB$TRIGGER_TYPE.PRE_ERASE, sizeof(trigger23), trigger23,
171
{ "RDB$TRIGGER_24", (UCHAR) nam_r_fields,
172
RDB$TRIGGERS.RDB$TRIGGER_TYPE.PRE_MODIFY, sizeof(trigger24),
173
trigger24, 0, ODS_8_0 },
174
{ "RDB$TRIGGER_27", (UCHAR) nam_r_fields,
175
RDB$TRIGGERS.RDB$TRIGGER_TYPE.POST_ERASE, sizeof(trigger27),
176
trigger27, 0, ODS_8_0 },
177
{ "RDB$TRIGGER_28", (UCHAR) nam_procedures,
178
RDB$TRIGGERS.RDB$TRIGGER_TYPE.PRE_STORE, sizeof(trigger28), trigger28,
180
{ "RDB$TRIGGER_29", (UCHAR) nam_procedures,
181
RDB$TRIGGERS.RDB$TRIGGER_TYPE.PRE_MODIFY, sizeof(trigger29),
182
trigger29, 0, ODS_8_0 },
183
{ "RDB$TRIGGER_30", (UCHAR) nam_exceptions,
184
RDB$TRIGGERS.RDB$TRIGGER_TYPE.PRE_STORE, sizeof(trigger30), trigger30,
186
{ "RDB$TRIGGER_31", (UCHAR) nam_user_privileges,
187
RDB$TRIGGERS.RDB$TRIGGER_TYPE.PRE_MODIFY, sizeof(trigger31),
188
trigger31, 0, ODS_8_1 },
189
{ "RDB$TRIGGER_32", (UCHAR) nam_user_privileges,
190
RDB$TRIGGERS.RDB$TRIGGER_TYPE.PRE_ERASE, sizeof(trigger31), trigger31,
192
{ "RDB$TRIGGER_33", (UCHAR) nam_user_privileges,
193
RDB$TRIGGERS.RDB$TRIGGER_TYPE.PRE_STORE, sizeof(trigger31), trigger31,
195
{ "RDB$TRIGGER_34", (UCHAR) nam_rel_constr,
196
RDB$TRIGGERS.RDB$TRIGGER_TYPE.POST_ERASE, sizeof(trigger34),
197
trigger34, TRG_ignore_perm, ODS_8_1 },
198
{ "RDB$TRIGGER_35", (UCHAR) nam_chk_constr,
199
RDB$TRIGGERS.RDB$TRIGGER_TYPE.POST_ERASE, sizeof(trigger35),
200
trigger35, TRG_ignore_perm, ODS_8_1 },
201
{ "RDB$TRIGGER_36", (UCHAR) nam_fields,
202
RDB$TRIGGERS.RDB$TRIGGER_TYPE.PRE_MODIFY, sizeof(trigger36),
203
trigger36, 0, ODS_11_0 },
208
/* this table is used in defining messages for system triggers */
210
static const trigger_msg trigger_messages[] =
212
{ "RDB$TRIGGER_9", 0, "grant_obj_notfound", ODS_8_0 },
213
{ "RDB$TRIGGER_9", 1, "grant_fld_notfound", ODS_8_0 },
214
{ "RDB$TRIGGER_9", 2, "grant_nopriv", ODS_8_0 },
215
{ "RDB$TRIGGER_9", 3, "nonsql_security_rel", ODS_8_0 },
216
{ "RDB$TRIGGER_9", 4, "nonsql_security_fld", ODS_8_0 },
217
{ "RDB$TRIGGER_9", 5, "grant_nopriv_on_base", ODS_8_0 },
218
{ "RDB$TRIGGER_1", 0, "existing_priv_mod", ODS_8_0 },
219
{ "RDB$TRIGGER_2", 0, "systrig_update", ODS_8_0 },
220
{ "RDB$TRIGGER_3", 0, "systrig_update", ODS_8_0 },
221
{ "RDB$TRIGGER_5", 0, "not_rel_owner", ODS_8_0 },
222
{ "RDB$TRIGGER_24", 1, "cnstrnt_fld_rename", ODS_8_0 },
223
{ "RDB$TRIGGER_23", 1, "cnstrnt_fld_del", ODS_8_0 },
224
{ "RDB$TRIGGER_22", 1, "check_trig_update", ODS_8_0 },
225
{ "RDB$TRIGGER_21", 1, "check_trig_del", ODS_8_0 },
226
{ "RDB$TRIGGER_20", 1, "integ_index_mod", ODS_8_0 },
227
{ "RDB$TRIGGER_20", 2, "integ_index_deactivate", ODS_8_0 },
228
{ "RDB$TRIGGER_20", 3, "integ_deactivate_primary", ODS_8_0 },
229
{ "RDB$TRIGGER_19", 1, "integ_index_del", ODS_8_0 },
230
{ "RDB$TRIGGER_18", 1, "integ_index_seg_mod", ODS_8_0 },
231
{ "RDB$TRIGGER_17", 1, "integ_index_seg_del", ODS_8_0 },
232
{ "RDB$TRIGGER_15", 1, "check_cnstrnt_del", ODS_8_0 },
233
{ "RDB$TRIGGER_14", 1, "check_cnstrnt_update", ODS_8_0 },
234
{ "RDB$TRIGGER_13", 1, "ref_cnstrnt_update", ODS_8_0 },
235
{ "RDB$TRIGGER_12", 1, "ref_cnstrnt_notfound", ODS_8_0 },
236
{ "RDB$TRIGGER_12", 2, "foreign_key_notfound", ODS_8_0 },
237
{ "RDB$TRIGGER_10", 1, "primary_key_ref", ODS_8_0 },
238
{ "RDB$TRIGGER_10", 2, "primary_key_notnull", ODS_8_0 },
239
{ "RDB$TRIGGER_25", 1, "rel_cnstrnt_update", ODS_8_0 },
240
{ "RDB$TRIGGER_26", 1, "constaint_on_view", ODS_8_0 },
241
{ "RDB$TRIGGER_26", 2, "invld_cnstrnt_type", ODS_8_0 },
242
{ "RDB$TRIGGER_26", 3, "primary_key_exists", ODS_8_0 },
243
{ "RDB$TRIGGER_31", 0, "no_write_user_priv", ODS_8_1 },
244
{ "RDB$TRIGGER_32", 0, "no_write_user_priv", ODS_8_1 },
245
{ "RDB$TRIGGER_33", 0, "no_write_user_priv", ODS_8_1 },
246
{ "RDB$TRIGGER_24", 2, "integ_index_seg_mod", ODS_11_0 },
247
{ "RDB$TRIGGER_36", 1, "integ_index_seg_mod", ODS_11_0 },
253
void INI_format(const TEXT* owner, const TEXT* charset)
255
/**************************************
257
* I N I _ f o r m a t
259
**************************************
261
* Functional description
262
* Initialize system relations in the database.
263
* The full complement of metadata should be
266
**************************************/
267
thread_db* tdbb = JRD_get_thread_data();
268
Database* dbb = tdbb->getDatabase();
270
/* Uppercase owner name */
271
Firebird::MetaName string(owner ? owner : "");
274
/* Uppercase charset name */
275
Firebird::MetaName string2(charset ? charset : "");
281
/* Make sure relations exist already */
284
for (const int* relfld = relfields; relfld[RFLD_R_NAME]; relfld = fld + 1)
286
if (relfld[RFLD_R_TYPE] == rel_persistent)
288
DPM_create_relation(tdbb, MET_relation(tdbb, relfld[RFLD_R_ID]));
291
for (fld = relfld + RFLD_RPT; fld[RFLD_F_NAME]; fld += RFLD_F_LENGTH)
296
/* Store RELATIONS and RELATION_FIELDS */
298
jrd_req* handle1 = NULL;
299
jrd_req* handle2 = NULL;
300
for (const int* relfld = relfields; relfld[RFLD_R_NAME]; relfld = fld + 1)
302
for (n = 0, fld = relfld + RFLD_RPT; fld[RFLD_F_NAME];
303
fld += RFLD_F_LENGTH)
305
if (!fld[RFLD_F_MINOR])
307
const int* pFld = fld;
308
const int* pRelFld = relfld;
309
store_relation_field(tdbb, pFld, pRelFld, n, &handle2, true);
314
STORE(REQUEST_HANDLE handle1) X IN RDB$RELATIONS
315
X.RDB$RELATION_ID = relfld[RFLD_R_ID];
316
PAD(names[relfld[RFLD_R_NAME]], X.RDB$RELATION_NAME);
319
X.RDB$SYSTEM_FLAG = RDB_system;
320
X.RDB$DBKEY_LENGTH = 8;
321
X.RDB$OWNER_NAME.NULL = TRUE;
322
X.RDB$RELATION_TYPE = relfld[RFLD_R_TYPE];
326
PAD(string.c_str(), X.RDB$OWNER_NAME);
327
X.RDB$OWNER_NAME.NULL = FALSE;
333
CMP_release(tdbb, handle1);
334
CMP_release(tdbb, handle2);
335
handle1 = handle2 = NULL;
337
/* Store global FIELDS */
339
for (const gfld* gfield = (gfld*) gfields; gfield->gfld_name; gfield++)
341
store_global_field(tdbb, gfield, &handle1);
344
CMP_release(tdbb, handle1);
347
STORE(REQUEST_HANDLE handle1) X IN RDB$DATABASE
348
X.RDB$RELATION_ID = (int) USER_DEF_REL_INIT_ID;
349
X.RDB$CHARACTER_SET_NAME.NULL = TRUE;
350
if (string2.length()) {
351
PAD (string2.c_str(), X.RDB$CHARACTER_SET_NAME);
352
X.RDB$CHARACTER_SET_NAME.NULL = FALSE;
355
PAD (DEFAULT_DB_CHARACTER_SET_NAME, X.RDB$CHARACTER_SET_NAME);
356
X.RDB$CHARACTER_SET_NAME.NULL = FALSE;
360
CMP_release(tdbb, handle1);
363
/* Create indices for system relations */
364
add_index_set(dbb, false, 0, 0);
366
/* Create parameter types */
370
for (const rtyp* type = types; type->rtyp_name; ++type)
372
STORE(REQUEST_HANDLE handle1) X IN RDB$TYPES
373
PAD(names[type->rtyp_field], X.RDB$FIELD_NAME);
374
PAD(type->rtyp_name, X.RDB$TYPE_NAME);
375
X.RDB$TYPE = type->rtyp_value;
376
X.RDB$SYSTEM_FLAG = RDB_system;
380
CMP_release(tdbb, handle1);
382
/* Store symbols for international character sets & collations */
384
store_intlnames(tdbb, dbb);
386
/* Create generators to be used by system triggers */
389
for (const gen* generator = generators; generator->gen_name; generator++)
391
store_generator(tdbb, generator, &handle1);
393
CMP_release(tdbb, handle1);
395
// Adjust the value of the hidden generator RDB$GENERATORS
397
DPM_gen_id(tdbb, 0, true, FB_NELEM(generators) - 1);
399
/* store system-defined triggers */
402
for (const jrd_trg* trigger = triggers; trigger->trg_relation; ++trigger)
404
store_trigger(tdbb, trigger, &handle1);
406
CMP_release(tdbb, handle1);
408
/* store trigger messages to go with triggers */
411
for (const trigger_msg* message = trigger_messages; message->trigmsg_name;
414
store_message(tdbb, message, &handle1);
416
CMP_release(tdbb, handle1);
418
// Store IUDFs declared automatically as system functions.
419
// CVC: Demonstration code to register IUDF automatically moved to functions.h
421
store_functions(tdbb, dbb);
423
DFW_perform_system_work();
425
add_relation_fields(0);
428
====================================================================
430
== Add security on RDB$ROLES system table
432
======================================================================
435
UCHAR buffer[MAX_ACL_SIZE];
437
*acl++ = ACL_version;
438
*acl++ = ACL_id_list;
441
USHORT length = string.length();
442
if (length > MAX_UCHAR)
445
*acl++ = (UCHAR)length;
448
const TEXT* p_1 = string.c_str();
449
memcpy(acl, p_1, length);
453
*acl++ = ACL_priv_list;
454
*acl++ = priv_protect;
455
*acl++ = priv_control;
456
*acl++ = priv_delete;
460
*acl++ = ACL_id_list;
462
*acl++ = ACL_priv_list;
466
length = acl - buffer;
468
add_security_to_sys_rel(tdbb, string, "RDB$ROLES", buffer, length);
469
add_security_to_sys_rel(tdbb, string, "RDB$PAGES", buffer, length);
471
add_security_to_sys_rel(tdbb, string, "RDB$FORMATS", buffer, length);
475
USHORT INI_get_trig_flags(const TEXT* trig_name)
477
/*********************************************
479
* I N I _ g e t _ t r i g _ f l a g s
481
*********************************************
483
* Functional description
484
* Return the trigger flags for a system trigger.
486
**************************************/
487
for (const jrd_trg* trig = triggers; trig->trg_length > 0; trig++)
489
if (!strcmp(trig->trg_name, trig_name))
491
return (trig->trg_flags);
501
/**************************************
505
**************************************
507
* Functional description
508
* Initialize in memory meta data. Assume that all meta data
509
* fields exist in the database even if this is not the case.
510
* Do not fill in the format length or the address in each
513
**************************************/
514
thread_db* tdbb = JRD_get_thread_data();
515
Database* dbb = tdbb->getDatabase();
519
for (const int* relfld = relfields; relfld[RFLD_R_NAME]; relfld = fld + 1)
521
jrd_rel* relation = MET_relation(tdbb, relfld[RFLD_R_ID]);
522
relation->rel_flags |= REL_system;
523
relation->rel_name = names[relfld[RFLD_R_NAME]];
525
for (fld = relfld + RFLD_RPT; fld[RFLD_F_NAME];
526
fld += RFLD_F_LENGTH)
531
/* Set a flag if their is a trigger on the relation. Later we may
532
need to compile it. */
534
for (const jrd_trg* trigger = triggers; trigger->trg_relation; trigger++)
536
if (relation->rel_name == names[trigger->trg_relation])
538
relation->rel_flags |= REL_sys_triggers;
543
vec<jrd_fld*>* fields = vec<jrd_fld*>::newVector(*dbb->dbb_permanent, n);
544
relation->rel_fields = fields;
545
vec<jrd_fld*>::iterator itr = fields->begin();
546
Format* format = Format::newFormat(*dbb->dbb_permanent, n);
547
relation->rel_current_format = format;
548
vec<Format*>* formats = vec<Format*>::newVector(*dbb->dbb_permanent, 1);
549
relation->rel_formats = formats;
550
(*formats)[0] = format;
551
Format::fmt_desc_iterator desc = format->fmt_desc.begin();
553
for (fld = relfld + RFLD_RPT; fld[RFLD_F_NAME];
554
fld += RFLD_F_LENGTH, ++desc, ++itr)
556
const gfld* gfield = &gfields[fld[RFLD_F_ID]];
557
desc->dsc_length = gfield->gfld_length;
558
desc->dsc_dtype = gfield->gfld_dtype;
559
desc->dsc_sub_type = gfield->gfld_sub_type;
560
if (desc->dsc_dtype == dtype_blob && desc->dsc_sub_type == isc_blob_text)
561
desc->dsc_scale = CS_METADATA; // blob charset
563
jrd_fld* field = FB_NEW(*dbb->dbb_permanent) jrd_fld(*dbb->dbb_permanent);
565
field->fld_name = names[fld[RFLD_F_NAME]];
573
/**************************************
577
**************************************
579
* Functional description
580
* Re-initialize in memory meta data. Fill in
581
* format 0 based on the minor ODS version of
582
* the database when it was created.
584
**************************************/
585
thread_db* tdbb = JRD_get_thread_data();
586
Database* dbb = tdbb->getDatabase();
588
const USHORT major_version = dbb->dbb_ods_version;
589
const USHORT minor_original = dbb->dbb_minor_original;
590
vec<jrd_rel*>* vector = dbb->dbb_relations;
593
for (const int* relfld = relfields; relfld[RFLD_R_NAME]; relfld = fld + 1)
595
if (relfld[RFLD_R_ODS] > ENCODE_ODS(major_version, minor_original))
597
/*****************************************************
599
** free the space allocated for RDB$ROLES
601
******************************************************/
602
const USHORT id = relfld[RFLD_R_ID];
603
jrd_rel* relation = (*vector)[id];
604
delete relation->rel_current_format;
605
delete relation->rel_formats;
606
delete relation->rel_fields;
607
(*vector)[id] = NULL;
608
fld = relfld + RFLD_RPT;
609
while (fld[RFLD_F_NAME])
611
fld += RFLD_F_LENGTH;
616
jrd_rel* relation = MET_relation(tdbb, relfld[RFLD_R_ID]);
617
Format* format = relation->rel_current_format;
620
for (fld = relfld + RFLD_RPT; fld[RFLD_F_NAME];
621
fld += RFLD_F_LENGTH)
623
/* If the ODS is less than 10, then remove all fields named
624
* RDB$FIELD_PRECISION and field RDB$CHARACTER_LENGTH from
625
* relation RDB$FUNCTION_ARGUMENTS , as they were not present
628
if (fld[RFLD_F_NAME] == nam_f_precision ||
629
(fld[RFLD_F_NAME] == nam_char_length &&
630
relfld[RFLD_R_NAME] == nam_args))
632
if (major_version >= ODS_VERSION10)
633
n = init2_helper(fld, n, relation);
635
else if (fld[RFLD_F_NAME] == nam_statistics &&
636
relfld[RFLD_R_NAME] == nam_i_segments)
638
if (major_version >= ODS_VERSION11)
639
n = init2_helper(fld, n, relation);
641
else if ((fld[RFLD_F_NAME] == nam_description ||
642
fld[RFLD_F_NAME] == nam_sys_flag) &&
643
relfld[RFLD_R_NAME] == nam_roles)
645
if (major_version >= ODS_VERSION11)
646
n = init2_helper(fld, n, relation);
648
else if (fld[RFLD_F_NAME] == nam_description &&
649
relfld[RFLD_R_NAME] == nam_gens)
651
if (major_version >= ODS_VERSION11)
652
n = init2_helper(fld, n, relation);
654
else if ((fld[RFLD_F_NAME] == nam_base_collation_name ||
655
fld[RFLD_F_NAME] == nam_specific_attr) &&
656
relfld[RFLD_R_NAME] == nam_collations)
658
if (major_version >= ODS_VERSION11)
659
n = init2_helper(fld, n, relation);
661
else if (fld[RFLD_F_NAME] == nam_r_type &&
662
relfld[RFLD_R_NAME] == nam_relations)
664
if (ENCODE_ODS(major_version, minor_original) >= ODS_11_1)
665
n = init2_helper(fld, n, relation);
667
else if (fld[RFLD_F_NAME] == nam_valid_blr &&
668
relfld[RFLD_R_NAME] == nam_trgs)
670
if (ENCODE_ODS(major_version, minor_original) >= ODS_11_1)
671
n = init2_helper(fld, n, relation);
673
else if ((fld[RFLD_F_NAME] == nam_prc_type ||
674
fld[RFLD_F_NAME] == nam_valid_blr) &&
675
relfld[RFLD_R_NAME] == nam_procedures)
677
if (ENCODE_ODS(major_version, minor_original) >= ODS_11_1)
678
n = init2_helper(fld, n, relation);
680
else if (fld[RFLD_F_NAME] == nam_debug_info &&
681
(relfld[RFLD_R_NAME] == nam_trgs ||
682
relfld[RFLD_R_NAME] == nam_procedures))
684
if (ENCODE_ODS(major_version, minor_original) >= ODS_11_1)
685
n = init2_helper(fld, n, relation);
687
else if ((fld[RFLD_F_NAME] == nam_default ||
688
fld[RFLD_F_NAME] == nam_d_source ||
689
fld[RFLD_F_NAME] == nam_collate_id ||
690
fld[RFLD_F_NAME] == nam_null_flag ||
691
fld[RFLD_F_NAME] == nam_prm_mechanism) &&
692
relfld[RFLD_R_NAME] == nam_proc_parameters)
694
if (ENCODE_ODS(major_version, minor_original) >= ODS_11_1)
695
n = init2_helper(fld, n, relation);
698
n = init2_helper(fld, n, relation);
701
relation->rel_fields->resize(n);
702
format->fmt_count = n; // We are using less than the allocated members.
703
format->fmt_length = (USHORT)FLAG_BYTES(n);
704
Format::fmt_desc_iterator desc = format->fmt_desc.begin();
705
for (fld = relfld + RFLD_RPT; fld[RFLD_F_NAME];
706
fld += RFLD_F_LENGTH, ++desc)
710
format->fmt_length = (USHORT)MET_align(dbb, &(*desc), format->fmt_length);
711
desc->dsc_address = (UCHAR*) (IPTR) format->fmt_length;
713
/* In ODS11 length of RDB$MESSAGES are
714
enlarged from 80 to 1023 bytes */
715
if ((fld[RFLD_F_NAME] == nam_msg) &&
716
(major_version < ODS_VERSION11))
718
desc->dsc_length = 80;
721
format->fmt_length += desc->dsc_length;
729
void INI_update_database()
731
/**************************************
733
* I N I _ u p d a t e _ d a t a b a s e
735
**************************************
737
* Functional description
738
* Perform changes to ODS that were required
739
* since ODS 8 and are dynamically updatable.
741
* %% Note %% Update the switch() statement to reflect new major ODS
743
**************************************/
744
thread_db* tdbb = JRD_get_thread_data();
745
Database* dbb = tdbb->getDatabase();
748
/* If database is ReadOnly, return without upgrading ODS */
749
if (dbb->dbb_flags & DBB_read_only)
752
/* check out the update version to see if we have work to do */
754
const USHORT major_version = dbb->dbb_ods_version;
755
const USHORT minor_version = dbb->dbb_minor_version;
757
/*******************************************************************
758
** when old engine is attaching a newer ODS database, do nothing
759
********************************************************************/
761
/* if database ODS is less than the server's, then upgrade */
762
if (ENCODE_ODS(major_version, minor_version) >= ODS_CURRENT_VERSION)
767
/*******************************************************************
768
** when new engine is attaching an older ODS database
769
** perform the necessary modifications
770
********************************************************************/
772
if (major_version == ODS_VERSION8)
774
/*** NOTE: The following two functions/structures need to understand
775
the difference between major ODS versions. The structure
776
which holds their information needs to have an additional field
777
to define which major ODS version they belong to.
779
add_global_fields (major_version, minor_version);
780
add_relation_fields (major_version, minor_version);
781
Look at add_new_triggers() for reference.
784
add_global_fields(minor_version);
785
add_relation_fields(minor_version);
788
add_index_set(dbb, true, major_version, minor_version);
789
add_new_triggers(major_version, minor_version);
791
/* if the database was updated; mark it with the current ODS minor
792
version so other process will attempt to do so. We mark this after
793
doing the update so that no other process can see the new minor
794
version but not the update. */
796
WIN window(HEADER_PAGE_NUMBER);
797
Ods::header_page* header =
798
(Ods::header_page*) CCH_FETCH(tdbb, &window, LCK_write, pag_header);
799
CCH_MARK(tdbb, &window);
801
/* Only minor upgrades can occur within a major ODS, define which one
803
switch (major_version)
806
header->hdr_ods_minor = ODS_CURRENT8;
809
header->hdr_ods_minor = ODS_CURRENT9;
812
header->hdr_ods_minor = ODS_CURRENT10;
815
/* Make sure we add a new case per new major ODS. Look at code above */
817
header->hdr_ods_minor = minor_version;
821
dbb->dbb_minor_version = header->hdr_ods_minor;
822
CCH_RELEASE(tdbb, &window);
824
DFW_perform_system_work();
827
#ifdef NOT_USED_OR_REPLACED
828
static void add_generator(TEXT* generator_name, jrd_req** handle)
830
/**************************************
832
* a d d _ g e n e r a t o r
834
**************************************
836
* Functional description
837
* Store a generator of the given name.
838
* This routine is used to upgrade ODS versions.
839
* DO NOT DELETE, even though it is not used
840
* now, since it may be used when we go to 8.1.
842
**************************************/
843
const gen* generator = generators;
845
thread_db* tdbb = JRD_get_thread_data();
847
/* find the new generator to be stored; assume it exists in the table */
848
/* TMN: If it doesn't exist in the table, we will CRASH here! */
850
while (strcmp(generator->gen_name, generator_name))
855
store_generator(tdbb, generator, handle);
859
static void add_global_fields( USHORT minor_version)
861
/**************************************
863
* a d d _ g l o b a l _ f i e l d s
865
**************************************
867
* Functional description
868
* Add any global fields which have a non-zero
869
* update number in the fields table. That
870
* is, those that have been added since the last
873
**************************************/
874
thread_db* tdbb = JRD_get_thread_data();
876
/* add desired global fields to system relations */
878
jrd_req* handle = NULL;
879
for (const gfld* gfield = (gfld*) gfields; gfield->gfld_name; gfield++)
881
if (minor_version < gfield->gfld_minor)
883
store_global_field(tdbb, gfield, &handle);
888
CMP_release(tdbb, handle);
891
DFW_perform_system_work();
895
static void add_index_set(Database* dbb,
897
USHORT major_version,
898
USHORT minor_version)
900
/**************************************
902
* a d d _ i n d e x _ s e t
904
**************************************
906
* Functional description
907
* Add system indices. If update_ods is true we are performing
908
* an ODS update, and only add the indices marked as newer than
909
* ODS (major_version,minor_version).
911
**************************************/
912
Firebird::MetaName string;
915
thread_db* tdbb = JRD_get_thread_data();
916
jrd_req* handle1 = NULL;
917
jrd_req* handle2 = NULL;
919
for (int n = 0; n < SYSTEM_INDEX_COUNT; n++)
921
const ini_idx_t* index = &indices[n];
923
/* For minor ODS updates, only add indices newer than on-disk ODS */
925
((index->ini_idx_version_flag <=
926
ENCODE_ODS(major_version, minor_version)) ||
927
(index->ini_idx_version_flag > ODS_CURRENT_VERSION) ||
928
(((USHORT) DECODE_ODS_MAJOR(index->ini_idx_version_flag)) !=
931
/* The DECODE_ODS_MAJOR() is used (in this case) to instruct the server
932
to perform updates for minor ODS versions only within a major ODS */
936
STORE(REQUEST_HANDLE handle1) X IN RDB$INDICES
937
jrd_rel* relation = MET_relation(tdbb, index->ini_idx_relid);
938
PAD(relation->rel_name.c_str(), X.RDB$RELATION_NAME);
939
string.printf("RDB$INDEX_%d", index->ini_idx_index_id);
940
PAD(string.c_str(), X.RDB$INDEX_NAME);
941
X.RDB$UNIQUE_FLAG = index->ini_idx_flags & idx_unique;
942
X.RDB$SEGMENT_COUNT = index->ini_idx_segment_count;
943
if (index->ini_idx_flags & idx_descending) {
944
X.RDB$INDEX_TYPE.NULL = FALSE;
945
X.RDB$INDEX_TYPE = 1;
948
X.RDB$INDEX_TYPE.NULL = TRUE;
950
X.RDB$SYSTEM_FLAG = 1;
951
X.RDB$INDEX_INACTIVE = 0;
953
/* Store each segment for the index */
954
index_desc::idx_repeat* tail = idx.idx_rpt;
955
for (USHORT position = 0;
956
position < index->ini_idx_segment_count; position++, tail++)
958
const ini_idx_t::ini_idx_segment_t* segment =
959
&index->ini_idx_segment[position];
960
STORE(REQUEST_HANDLE handle2) Y IN RDB$INDEX_SEGMENTS
961
jrd_fld* field = (*relation->rel_fields)[segment->ini_idx_rfld_id];
963
Y.RDB$FIELD_POSITION = position;
964
PAD(X.RDB$INDEX_NAME, Y.RDB$INDEX_NAME);
965
PAD(field->fld_name.c_str(), Y.RDB$FIELD_NAME);
966
tail->idx_field = segment->ini_idx_rfld_id;
967
tail->idx_itype = segment->ini_idx_type;
968
tail->idx_selectivity = 0;
971
idx.idx_count = index->ini_idx_segment_count;
972
idx.idx_flags = index->ini_idx_flags;
973
SelectivityList selectivity(*tdbb->getDefaultPool());
974
IDX_create_index(tdbb, relation, &idx, string.c_str(), NULL, NULL,
976
X.RDB$INDEX_ID = idx.idx_id + 1;
981
CMP_release(tdbb, handle1);
984
CMP_release(tdbb, handle2);
989
static void add_new_triggers(USHORT major_version, USHORT minor_version)
991
/**************************************
993
* a d d _ n e w _ t r i g g e r s
995
**************************************
997
* Functional description
998
* Store all new ODS 8.x (x > 0) triggers.
999
* The major and minor_version passed in are the ODS versions
1000
* before the ODS is upgraded.
1001
* This routine is used to upgrade ODS versions.
1003
**************************************/
1004
thread_db* tdbb = JRD_get_thread_data();
1006
jrd_req* handle1 = NULL;
1008
/* add all new triggers, that were added since the database was created */
1009
for (const jrd_trg* trig = triggers; trig->trg_length > 0; trig++)
1011
if ((trig->trg_ods_version > ENCODE_ODS(major_version, minor_version))
1012
&& (DECODE_ODS_MAJOR(trig->trg_ods_version) == major_version))
1014
store_trigger(tdbb, trig, &handle1);
1018
jrd_req* handle2 = NULL;
1019
for (const trigger_msg* message = trigger_messages; message->trigmsg_name; message++)
1021
if ((message->trg_ods_version >
1022
ENCODE_ODS(major_version, minor_version)) &&
1023
(DECODE_ODS_MAJOR(message->trg_ods_version) == major_version))
1025
store_message(tdbb, message, &handle2);
1030
CMP_release(tdbb, handle1);
1033
CMP_release(tdbb, handle2);
1038
static void add_relation_fields( USHORT minor_version)
1040
/**************************************
1042
* a d d _ r e l a t i o n _ f i e l d s
1044
**************************************
1046
* Functional description
1047
* Add any local fields which have a non-zero
1048
* update number in the relfields table. That
1049
* is, those that have been added since the last
1052
**************************************/
1053
thread_db* tdbb = JRD_get_thread_data();
1054
Database* dbb = tdbb->getDatabase();
1056
/* add desired fields to system relations, forcing a new format version */
1058
jrd_req* s_handle = NULL;
1059
jrd_req* m_handle = NULL;
1061
for (const int* relfld = relfields; relfld[RFLD_R_NAME]; relfld = fld + 1)
1064
for (fld = relfld + RFLD_RPT; fld[RFLD_F_NAME];
1065
n++, fld += RFLD_F_LENGTH)
1067
if (minor_version < fld[RFLD_F_MINOR] ||
1068
minor_version < fld[RFLD_F_UPD_MINOR])
1070
if (minor_version < fld[RFLD_F_MINOR])
1072
store_relation_field(tdbb, fld, relfld, n, &s_handle,
1077
modify_relation_field(tdbb, fld, relfld, &m_handle);
1080
desc.dsc_dtype = dtype_text;
1081
INTL_ASSIGN_DSC(&desc, CS_METADATA, COLLATE_NONE);
1082
desc.dsc_address = (UCHAR*) names[relfld[RFLD_R_NAME]];
1083
desc.dsc_length = strlen((char*)desc.dsc_address);
1084
DFW_post_work(dbb->dbb_sys_trans, dfw_update_format, &desc, 0);
1090
CMP_release(tdbb, s_handle);
1093
CMP_release(tdbb, m_handle);
1096
DFW_perform_system_work();
1100
// The caller used an UCHAR* to store the acl, it was converted to TEXT* to
1101
// be passed to this function, only to be converted to UCHAR* to be passed
1102
// to BLB_put_segment. Therefore, "acl" was changed to UCHAR* as param.
1103
static void add_security_to_sys_rel(thread_db* tdbb,
1104
const Firebird::MetaName& user_name,
1105
const TEXT* rel_name,
1107
const SSHORT acl_length)
1109
/**************************************
1111
* a d d _ s e c u r i t y _ t o _ s y s _ r e l
1113
**************************************
1115
* Functional description
1117
* Add security to system relations. Only the owner of the
1118
* database has SELECT/INSERT/UPDATE/DELETE privileges on
1119
* any system relations. Any other users only has SELECT
1122
**************************************/
1123
TEXT sec_class_name[100];
1124
Firebird::MetaName default_class;
1127
Database* dbb = tdbb->getDatabase();
1129
strcpy(sec_class_name, SQL_SECCLASS_PREFIX);
1130
strcat(sec_class_name, rel_name);
1133
blb* blob = BLB_create(tdbb, dbb->dbb_sys_trans, &blob_id_1);
1134
BLB_put_segment(tdbb, blob, acl, acl_length);
1135
BLB_close(tdbb, blob);
1138
blob = BLB_create(tdbb, dbb->dbb_sys_trans, &blob_id_2);
1139
BLB_put_segment(tdbb, blob, acl, acl_length);
1140
BLB_close(tdbb, blob);
1142
default_class.printf("%s%" SQUADFORMAT, DEFAULT_CLASS,
1143
DPM_gen_id(tdbb, MET_lookup_generator(tdbb, DEFAULT_CLASS),
1144
false, (SINT64) 1));
1146
jrd_req* handle1 = NULL;
1148
for (int cnt = 0; cnt < 6; cnt++)
1150
STORE(REQUEST_HANDLE handle1) PRIV IN RDB$USER_PRIVILEGES
1154
strcpy(PRIV.RDB$USER, user_name.c_str());
1155
PRIV.RDB$PRIVILEGE[0] = 'S';
1156
PRIV.RDB$GRANT_OPTION = 1;
1159
strcpy(PRIV.RDB$USER, user_name.c_str());
1160
PRIV.RDB$PRIVILEGE[0] = 'I';
1161
PRIV.RDB$GRANT_OPTION = 1;
1164
strcpy(PRIV.RDB$USER, user_name.c_str());
1165
PRIV.RDB$PRIVILEGE[0] = 'U';
1166
PRIV.RDB$GRANT_OPTION = 1;
1169
strcpy(PRIV.RDB$USER, user_name.c_str());
1170
PRIV.RDB$PRIVILEGE[0] = 'D';
1171
PRIV.RDB$GRANT_OPTION = 1;
1174
strcpy(PRIV.RDB$USER, user_name.c_str());
1175
PRIV.RDB$PRIVILEGE[0] = 'R';
1176
PRIV.RDB$GRANT_OPTION = 1;
1179
strcpy(PRIV.RDB$USER, "PUBLIC");
1180
PRIV.RDB$PRIVILEGE[0] = 'S';
1181
PRIV.RDB$GRANT_OPTION = 0;
1184
strcpy(PRIV.RDB$GRANTOR, user_name.c_str());
1185
PRIV.RDB$PRIVILEGE[1] = 0;
1186
strcpy(PRIV.RDB$RELATION_NAME, rel_name);
1187
PRIV.RDB$FIELD_NAME.NULL = TRUE;
1188
PRIV.RDB$USER_TYPE = obj_user;
1189
PRIV.RDB$OBJECT_TYPE = obj_relation;
1193
CMP_release(tdbb, handle1);
1197
STORE(REQUEST_HANDLE handle1)
1198
CLS IN RDB$SECURITY_CLASSES
1199
jrd_vtof((char*)sec_class_name, CLS.RDB$SECURITY_CLASS,
1200
sizeof(CLS.RDB$SECURITY_CLASS));
1201
CLS.RDB$ACL = blob_id_1;
1204
CMP_release(tdbb, handle1);
1208
STORE(REQUEST_HANDLE handle1)
1209
CLS IN RDB$SECURITY_CLASSES
1210
jrd_vtof(default_class.c_str(), CLS.RDB$SECURITY_CLASS,
1211
sizeof(CLS.RDB$SECURITY_CLASS));
1212
CLS.RDB$ACL = blob_id_2;
1215
CMP_release(tdbb, handle1);
1219
FOR(REQUEST_HANDLE handle1) REL IN RDB$RELATIONS
1220
WITH REL.RDB$RELATION_NAME EQ rel_name
1222
REL.RDB$DEFAULT_CLASS.NULL = FALSE;
1223
jrd_vtof(default_class.c_str(), REL.RDB$DEFAULT_CLASS,
1224
sizeof(REL.RDB$DEFAULT_CLASS));
1229
CMP_release(tdbb, handle1);
1233
#ifdef NOT_USED_OR_REPLACED
1234
static void add_trigger(TEXT* trigger_name, jrd_req** handle1, jrd_req** handle2)
1236
/**************************************
1238
* a d d _ t r i g g e r
1240
**************************************
1242
* Functional description
1243
* Store a trigger of the given name.
1244
* This routine is used to upgrade ODS versions.
1245
* DO NOT DELETE, even though it is not used
1246
* now, since it will be used when we go to 8.1.
1248
**************************************/
1249
thread_db* tdbb = JRD_get_thread_data();
1251
/* Find the new trigger to be stored; assume it exists in the table */
1253
const jrd_trg* trigger = triggers;
1254
while (strcmp(trigger->trg_name, trigger_name))
1259
store_trigger(tdbb, trigger, handle1);
1261
/* Look for any related trigger messages */
1263
for (const trigger_msg* message = trigger_messages; message->trigmsg_name;
1266
if (!strcmp(message->trigmsg_name, trigger->trg_name))
1268
store_message(tdbb, message, handle2);
1275
static int init2_helper(const int* fld, int n, jrd_rel* relation)
1277
if (!fld[RFLD_F_MINOR])
1280
if (fld[RFLD_F_UPD_MINOR])
1281
relation->rel_flags |= REL_force_scan;
1285
relation->rel_flags |= REL_force_scan;
1291
static void modify_relation_field(thread_db* tdbb,
1296
/**************************************
1298
* m o d i f y _ r e l a t i o n _ f i e l d
1300
**************************************
1302
* Functional description
1303
* Modify a local field according to the
1304
* passed information. Note that the field id and
1305
* field position do not change.
1307
**************************************/
1309
Database* dbb = tdbb->getDatabase();
1311
FOR(REQUEST_HANDLE * handle) X IN RDB$RELATION_FIELDS WITH
1312
X.RDB$RELATION_NAME EQ names[relfld[RFLD_R_NAME]] AND
1313
X.RDB$FIELD_NAME EQ names[fld[RFLD_F_NAME]]
1315
const gfld* gfield = &gfields[fld[RFLD_F_UPD_ID]];
1316
PAD(names[gfield->gfld_name], X.RDB$FIELD_SOURCE);
1317
X.RDB$UPDATE_FLAG = fld[RFLD_F_UPDATE];
1323
static void store_generator(thread_db* tdbb, const gen* generator, jrd_req** handle)
1325
/**************************************
1327
* s t o r e _ g e n e r a t o r
1329
**************************************
1331
* Functional description
1332
* Store the passed generator according to
1333
* the information in the generator block.
1335
**************************************/
1337
Database* dbb = tdbb->getDatabase();
1339
jrd_tra* trans = dbb->dbb_sys_trans;
1341
STORE(REQUEST_HANDLE * handle) X IN RDB$GENERATORS
1342
PAD(generator->gen_name, X.RDB$GENERATOR_NAME);
1343
X.RDB$GENERATOR_ID = generator->gen_id;
1344
X.RDB$SYSTEM_FLAG = RDB_system;
1345
if (generator->gen_description)
1347
blb* blob = BLB_create(tdbb, trans, &X.RDB$DESCRIPTION);
1348
BLB_put_segment(tdbb,
1350
reinterpret_cast<const UCHAR*>(generator->gen_description),
1351
strlen(generator->gen_description));
1352
BLB_close(tdbb, blob);
1353
X.RDB$DESCRIPTION.NULL = FALSE;
1357
X.RDB$DESCRIPTION.NULL = TRUE;
1364
static void store_global_field(thread_db* tdbb, const gfld* gfield, jrd_req** handle)
1366
/**************************************
1368
* s t o r e _ g l o b a l _ f i e l d
1370
**************************************
1372
* Functional description
1373
* Store a global field according to the
1374
* passed information.
1376
**************************************/
1378
Database* dbb = tdbb->getDatabase();
1380
jrd_tra* trans = dbb->dbb_sys_trans;
1382
STORE(REQUEST_HANDLE * handle) X IN RDB$FIELDS
1383
PAD(names[(USHORT)gfield->gfld_name], X.RDB$FIELD_NAME);
1384
X.RDB$FIELD_LENGTH = gfield->gfld_length;
1385
X.RDB$FIELD_SCALE = 0;
1386
X.RDB$SYSTEM_FLAG = RDB_system;
1387
X.RDB$FIELD_SUB_TYPE.NULL = TRUE;
1388
X.RDB$CHARACTER_SET_ID.NULL = TRUE;
1389
X.RDB$COLLATION_ID.NULL = TRUE;
1390
X.RDB$SEGMENT_LENGTH.NULL = TRUE;
1391
if (gfield->gfld_dflt_blr)
1393
blb* blob = BLB_create(tdbb, trans, &X.RDB$DEFAULT_VALUE);
1394
BLB_put_segment(tdbb,
1396
gfield->gfld_dflt_blr,
1397
gfield->gfld_dflt_len);
1398
BLB_close(tdbb, blob);
1399
X.RDB$DEFAULT_VALUE.NULL = FALSE;
1403
X.RDB$DEFAULT_VALUE.NULL = TRUE;
1405
switch (gfield->gfld_dtype)
1407
case dtype_timestamp:
1408
X.RDB$FIELD_TYPE = (int) blr_timestamp;
1411
case dtype_sql_time:
1412
X.RDB$FIELD_TYPE = (int) blr_sql_time;
1415
case dtype_sql_date:
1416
X.RDB$FIELD_TYPE = (int) blr_sql_date;
1422
if (gfield->gfld_dtype == dtype_short)
1423
X.RDB$FIELD_TYPE = (int) blr_short;
1424
else if (gfield->gfld_dtype == dtype_long)
1425
X.RDB$FIELD_TYPE = (int) blr_long;
1428
// Workaround to allow fld_counter domain
1429
// in dialect 1 databases
1430
if (dbb->dbb_flags & DBB_DB_SQL_dialect_3)
1431
X.RDB$FIELD_TYPE = (int) blr_int64;
1433
X.RDB$FIELD_TYPE = (int) blr_double;
1435
if ((gfield->gfld_sub_type == dsc_num_type_numeric) ||
1436
(gfield->gfld_sub_type == dsc_num_type_decimal))
1438
X.RDB$FIELD_SUB_TYPE.NULL = FALSE;
1439
X.RDB$FIELD_SUB_TYPE = gfield->gfld_sub_type;
1444
X.RDB$FIELD_TYPE = (int) blr_double;
1449
if (gfield->gfld_dtype == dtype_text)
1451
X.RDB$FIELD_TYPE = (int) blr_text;
1455
X.RDB$FIELD_TYPE = (int) blr_varying;
1456
X.RDB$FIELD_LENGTH -= sizeof(USHORT);
1458
if (gfield->gfld_sub_type == dsc_text_type_metadata)
1460
X.RDB$CHARACTER_SET_ID.NULL = FALSE;
1461
X.RDB$CHARACTER_SET_ID = CS_METADATA;
1462
X.RDB$COLLATION_ID.NULL = FALSE;
1463
X.RDB$COLLATION_ID = COLLATE_NONE;
1464
X.RDB$FIELD_SUB_TYPE.NULL = FALSE;
1465
X.RDB$FIELD_SUB_TYPE = gfield->gfld_sub_type;
1467
else if (gfield->gfld_sub_type == dsc_text_type_ascii)
1469
X.RDB$CHARACTER_SET_ID.NULL = FALSE;
1470
X.RDB$CHARACTER_SET_ID = CS_ASCII;
1471
X.RDB$COLLATION_ID.NULL = FALSE;
1472
X.RDB$COLLATION_ID = COLLATE_NONE;
1473
X.RDB$FIELD_SUB_TYPE.NULL = FALSE;
1474
X.RDB$FIELD_SUB_TYPE = gfield->gfld_sub_type;
1476
else if (gfield->gfld_sub_type == dsc_text_type_fixed)
1478
X.RDB$CHARACTER_SET_ID.NULL = FALSE;
1479
X.RDB$CHARACTER_SET_ID = CS_BINARY;
1480
X.RDB$COLLATION_ID.NULL = FALSE;
1481
X.RDB$COLLATION_ID = COLLATE_NONE;
1482
X.RDB$FIELD_SUB_TYPE.NULL = FALSE;
1483
X.RDB$FIELD_SUB_TYPE = gfield->gfld_sub_type;
1487
X.RDB$CHARACTER_SET_ID.NULL = FALSE;
1488
X.RDB$CHARACTER_SET_ID = CS_NONE;
1489
X.RDB$COLLATION_ID.NULL = FALSE;
1490
X.RDB$COLLATION_ID = COLLATE_NONE;
1495
X.RDB$FIELD_TYPE = (int) blr_blob;
1496
X.RDB$FIELD_SUB_TYPE.NULL = FALSE;
1497
X.RDB$SEGMENT_LENGTH.NULL = FALSE;
1498
X.RDB$FIELD_SUB_TYPE = gfield->gfld_sub_type;
1499
X.RDB$SEGMENT_LENGTH = 80;
1500
if (gfield->gfld_sub_type == isc_blob_text)
1502
X.RDB$CHARACTER_SET_ID.NULL = FALSE;
1503
X.RDB$CHARACTER_SET_ID = CS_METADATA;
1516
static void store_intlnames(thread_db* tdbb, Database* dbb)
1518
/**************************************
1520
* s t o r e _ i n t l n a m e s
1522
**************************************
1524
* Functional description
1525
* Store symbolic names & information for international
1526
* character sets & collations.
1528
**************************************/
1531
jrd_req* handle = NULL;
1532
for (const CS_TYPE* csptr = cs_types; csptr->init_charset_name; csptr++)
1534
STORE(REQUEST_HANDLE handle) X IN RDB$CHARACTER_SETS USING
1535
PAD(csptr->init_charset_name, X.RDB$CHARACTER_SET_NAME);
1536
PAD(csptr->init_charset_name, X.RDB$DEFAULT_COLLATE_NAME);
1537
X.RDB$CHARACTER_SET_ID = csptr->init_charset_id;
1538
X.RDB$BYTES_PER_CHARACTER = csptr->init_charset_bytes_per_char;
1539
X.RDB$SYSTEM_FLAG = RDB_system;
1543
CMP_release(tdbb, handle);
1546
jrd_tra* trans = dbb->dbb_sys_trans;
1548
for (const COLL_TYPE* collptr = coll_types; collptr->init_collation_name; collptr++)
1550
STORE(REQUEST_HANDLE handle) X IN RDB$COLLATIONS USING
1551
PAD(collptr->init_collation_name, X.RDB$COLLATION_NAME);
1553
if (collptr->init_collation_base_name)
1555
X.RDB$BASE_COLLATION_NAME.NULL = false;
1556
PAD(collptr->init_collation_base_name, X.RDB$BASE_COLLATION_NAME);
1559
X.RDB$BASE_COLLATION_NAME.NULL = true;
1561
X.RDB$CHARACTER_SET_ID = collptr->init_collation_charset;
1562
X.RDB$COLLATION_ID = collptr->init_collation_id;
1563
X.RDB$SYSTEM_FLAG = RDB_system;
1564
X.RDB$COLLATION_ATTRIBUTES = collptr->init_collation_attributes;
1566
if (collptr->init_collation_specific_attributes)
1568
blb* blob = BLB_create(tdbb, trans, &X.RDB$SPECIFIC_ATTRIBUTES);
1569
BLB_put_segment(tdbb,
1571
reinterpret_cast<const UCHAR*>(collptr->init_collation_specific_attributes),
1572
strlen(collptr->init_collation_specific_attributes));
1573
BLB_close(tdbb, blob);
1574
X.RDB$SPECIFIC_ATTRIBUTES.NULL = FALSE;
1577
X.RDB$SPECIFIC_ATTRIBUTES.NULL = TRUE;
1582
CMP_release(tdbb, handle);
1586
static void store_function_argument(
1587
thread_db* tdbb, Database* dbb,
1589
const char* function_name, SLONG argument_position, SLONG mechanism, SLONG type, SLONG scale,
1590
SLONG length, SLONG sub_type, SLONG charset, SLONG precision, SLONG char_length)
1592
STORE(REQUEST_HANDLE handle) FA IN RDB$FUNCTION_ARGUMENTS
1593
PAD(function_name, FA.RDB$FUNCTION_NAME);
1594
FA.RDB$FUNCTION_NAME.NULL = FALSE;
1595
FA.RDB$ARGUMENT_POSITION = argument_position;
1596
FA.RDB$MECHANISM = mechanism;
1597
FA.RDB$FIELD_TYPE = type;
1598
FA.RDB$FIELD_SCALE = scale;
1599
FA.RDB$FIELD_LENGTH = length;
1600
FA.RDB$FIELD_SUB_TYPE = sub_type;
1601
FA.RDB$CHARACTER_SET_ID = charset;
1602
FA.RDB$FIELD_PRECISION = precision;
1603
FA.RDB$CHARACTER_LENGTH = char_length;
1607
static void store_function(
1608
thread_db* tdbb, Database* dbb,
1610
const char* function_name, const char* module, const char* entrypoint, SLONG argument)
1612
STORE(REQUEST_HANDLE handle) F IN RDB$FUNCTIONS
1613
PAD(function_name, F.RDB$FUNCTION_NAME);
1614
F.RDB$FUNCTION_NAME.NULL = FALSE;
1615
//F.RDB$FUNCTION_TYPE <null>
1616
//F.RDB$QUERY_NAME <null>
1617
//F.RDB$DESCRIPTION <null>
1618
strcpy(F.RDB$MODULE_NAME, module);
1619
F.RDB$MODULE_NAME.NULL = FALSE;
1620
PAD(entrypoint, F.RDB$ENTRYPOINT);
1621
F.RDB$ENTRYPOINT.NULL = FALSE;
1622
F.RDB$RETURN_ARGUMENT = argument;
1623
F.RDB$SYSTEM_FLAG = RDB_system;
1627
static void store_functions(thread_db* tdbb, Database* dbb)
1629
/**************************************
1631
* s t o r e _ f u n c t i o n s
1633
**************************************
1635
* Functional description
1636
* Store built-in functions and their arguments
1638
**************************************/
1641
jrd_req *fun_handle = NULL, *arg_handle = NULL;
1642
const char *function_name;
1643
SLONG argument_position;
1645
#define FUNCTION(ROUTINE, FUNCTION_NAME, MODULE_NAME, ENTRYPOINT, RET_ARG) \
1646
function_name = FUNCTION_NAME; \
1647
argument_position = RET_ARG ? 1 : 0; \
1648
store_function(tdbb, dbb, fun_handle, FUNCTION_NAME, MODULE_NAME, ENTRYPOINT, RET_ARG);
1649
#define END_FUNCTION
1650
#define FUNCTION_ARGUMENT(MECHANISM, TYPE, SCALE, LENGTH, SUB_TYPE, CHARSET, PRECISION, CHAR_LENGTH) \
1651
store_function_argument(tdbb, dbb, arg_handle, function_name, argument_position, \
1652
MECHANISM, TYPE, SCALE, LENGTH, SUB_TYPE, CHARSET, PRECISION, CHAR_LENGTH); \
1653
argument_position++;
1655
#include "../jrd/functions.h"
1657
CMP_release(tdbb, fun_handle);
1658
CMP_release(tdbb, arg_handle);
1662
static void store_message(thread_db* tdbb, const trigger_msg* message, jrd_req** handle)
1664
/**************************************
1666
* s t o r e _ m e s s a g e
1668
**************************************
1670
* Functional description
1671
* Store system trigger messages.
1673
**************************************/
1675
Database* dbb = tdbb->getDatabase();
1677
/* store the trigger */
1679
STORE(REQUEST_HANDLE * handle) X IN RDB$TRIGGER_MESSAGES
1680
PAD(message->trigmsg_name, X.RDB$TRIGGER_NAME);
1681
X.RDB$MESSAGE_NUMBER = message->trigmsg_number;
1682
PAD(message->trigmsg_text, X.RDB$MESSAGE);
1687
static void store_relation_field(thread_db* tdbb,
1694
/**************************************
1696
* s t o r e _ r e l a t i o n _ f i e l d
1698
**************************************
1700
* Functional description
1701
* Store a local field according to the
1702
* passed information.
1704
**************************************/
1706
Database* dbb = tdbb->getDatabase();
1708
STORE(REQUEST_HANDLE * handle) X IN RDB$RELATION_FIELDS
1709
const gfld* gfield = (fld[RFLD_F_UPD_MINOR] && !fmt0_flag) ?
1710
&gfields[fld[RFLD_F_UPD_ID]] : &gfields[fld[RFLD_F_ID]];
1711
PAD(names[relfld[RFLD_R_NAME]], X.RDB$RELATION_NAME);
1712
PAD(names[fld[RFLD_F_NAME]], X.RDB$FIELD_NAME);
1713
PAD(names[gfield->gfld_name], X.RDB$FIELD_SOURCE);
1714
X.RDB$FIELD_POSITION = field_id;
1715
X.RDB$FIELD_ID = field_id;
1716
X.RDB$SYSTEM_FLAG = RDB_system;
1717
X.RDB$UPDATE_FLAG = fld[RFLD_F_UPDATE];
1722
static void store_trigger(thread_db* tdbb, const jrd_trg* trigger, jrd_req** handle)
1724
/**************************************
1726
* s t o r e _ t r i g g e r
1728
**************************************
1730
* Functional description
1731
* Store the trigger according to the
1732
* information in the trigger block.
1734
**************************************/
1736
Database* dbb = tdbb->getDatabase();
1738
jrd_tra* trans = dbb->dbb_sys_trans;
1740
/* indicate that the relation format needs revising */
1742
desc.dsc_dtype = dtype_text;
1743
INTL_ASSIGN_DSC(&desc, CS_METADATA, COLLATE_NONE);
1744
desc.dsc_address = (UCHAR*) names[trigger->trg_relation];
1745
desc.dsc_length = strlen((char*)desc.dsc_address);
1746
DFW_post_work(trans, dfw_update_format, &desc, 0);
1748
/* store the trigger */
1750
STORE(REQUEST_HANDLE * handle) X IN RDB$TRIGGERS
1751
PAD(trigger->trg_name, X.RDB$TRIGGER_NAME);
1752
PAD(names[trigger->trg_relation], X.RDB$RELATION_NAME);
1753
X.RDB$TRIGGER_SEQUENCE = 0;
1754
X.RDB$SYSTEM_FLAG = RDB_system;
1755
X.RDB$TRIGGER_TYPE = trigger->trg_type;
1756
X.RDB$FLAGS = trigger->trg_flags;
1757
blb* blob = BLB_create(tdbb, trans, &X.RDB$TRIGGER_BLR);
1758
BLB_put_segment(tdbb,
1761
trigger->trg_length);
1762
BLB_close(tdbb, blob);