~ubuntu-branches/ubuntu/karmic/firebird2.1/karmic

« back to all changes in this revision

Viewing changes to src/jrd/ini.epp

  • Committer: Bazaar Package Importer
  • Author(s): Damyan Ivanov
  • Date: 2008-05-26 23:59:25 UTC
  • Revision ID: james.westby@ubuntu.com-20080526235925-2pnqj6nxpppoeaer
Tags: upstream-2.1.0.17798-0.ds2
ImportĀ upstreamĀ versionĀ 2.1.0.17798-0.ds2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *      PROGRAM:        JRD Access Method
 
3
 *      MODULE:         ini.epp
 
4
 *      DESCRIPTION:    Metadata initialization / population
 
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
 */
 
23
 
 
24
#include "firebird.h"
 
25
#include <stdio.h>
 
26
#include <string.h>
 
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"
 
34
#include "gen/ids.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"
 
58
 
 
59
using namespace Jrd;
 
60
 
 
61
DATABASE DB = FILENAME "ODS.RDB";
 
62
 
 
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";
 
66
 
 
67
#ifdef NOT_USED_OR_REPLACED
 
68
static void add_generator(TEXT*, jrd_req**);
 
69
#endif
 
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**);
 
78
#endif
 
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**);
 
89
 
 
90
 
 
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 */
 
96
 
 
97
static const jrd_trg triggers[] =
 
98
{
 
99
        { "RDB$TRIGGER_1", (UCHAR) nam_user_privileges,
 
100
                RDB$TRIGGERS.RDB$TRIGGER_TYPE.PRE_MODIFY, sizeof(trigger3), trigger3,
 
101
                0, ODS_8_0 },
 
102
        { "RDB$TRIGGER_8", (UCHAR) nam_user_privileges,
 
103
                RDB$TRIGGERS.RDB$TRIGGER_TYPE.PRE_ERASE, sizeof(trigger2), trigger2,
 
104
                0, ODS_8_0 },
 
105
        { "RDB$TRIGGER_9", (UCHAR) nam_user_privileges,
 
106
                RDB$TRIGGERS.RDB$TRIGGER_TYPE.PRE_STORE, sizeof(trigger1), trigger1,
 
107
                0, ODS_8_0 },
 
108
        { "RDB$TRIGGER_2", (UCHAR) nam_trgs,
 
109
                RDB$TRIGGERS.RDB$TRIGGER_TYPE.PRE_MODIFY, sizeof(trigger4), trigger4,
 
110
                0, ODS_8_0 },
 
111
        { "RDB$TRIGGER_3", (UCHAR) nam_trgs,
 
112
                RDB$TRIGGERS.RDB$TRIGGER_TYPE.PRE_ERASE, sizeof(trigger4), trigger4,
 
113
                0, ODS_8_0 },
 
114
        { "RDB$TRIGGER_4", (UCHAR) nam_relations,
 
115
                RDB$TRIGGERS.RDB$TRIGGER_TYPE.PRE_STORE, sizeof(trigger5), trigger5,
 
116
                0, ODS_8_0 },
 
117
        { "RDB$TRIGGER_5", (UCHAR) nam_relations,
 
118
                RDB$TRIGGERS.RDB$TRIGGER_TYPE.PRE_MODIFY, sizeof(trigger6), trigger6,
 
119
                0, ODS_8_0 },
 
120
        { "RDB$TRIGGER_6", (UCHAR) nam_gens,
 
121
                RDB$TRIGGERS.RDB$TRIGGER_TYPE.PRE_STORE, sizeof(trigger7), trigger7,
 
122
                0, ODS_8_0 },
 
123
        { "RDB$TRIGGER_26", (UCHAR) nam_rel_constr,
 
124
                RDB$TRIGGERS.RDB$TRIGGER_TYPE.PRE_STORE, sizeof(trigger26), trigger26,
 
125
                0, ODS_8_0 },
 
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,
 
131
                0, ODS_8_0 },
 
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,
 
137
                0, ODS_8_0 },
 
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,
 
146
                0, ODS_8_0 },
 
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,
 
152
                0, ODS_8_0 },
 
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,
 
158
                0, ODS_8_0 },
 
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,
 
164
                0, ODS_8_0 },
 
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,
 
170
                0, ODS_8_0 },
 
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,
 
179
                0, ODS_8_0 },
 
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,
 
185
                0, ODS_8_0 },
 
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,
 
191
                0, ODS_8_1 },
 
192
        { "RDB$TRIGGER_33", (UCHAR) nam_user_privileges,
 
193
                RDB$TRIGGERS.RDB$TRIGGER_TYPE.PRE_STORE, sizeof(trigger31), trigger31,
 
194
                0, ODS_8_1 },
 
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 },
 
204
        { 0, 0, 0, 0, 0, 0 }
 
205
};
 
206
 
 
207
 
 
208
/* this table is used in defining messages for system triggers */
 
209
 
 
210
static const trigger_msg trigger_messages[] =
 
211
{
 
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 },
 
248
        { 0, 0, 0, 0 }
 
249
};
 
250
 
 
251
 
 
252
 
 
253
void INI_format(const TEXT* owner, const TEXT* charset)
 
254
{
 
255
/**************************************
 
256
 *
 
257
 *      I N I _ f o r m a t
 
258
 *
 
259
 **************************************
 
260
 *
 
261
 * Functional description
 
262
 *      Initialize system relations in the database.
 
263
 *      The full complement of metadata should be
 
264
 *      stored here.
 
265
 *
 
266
 **************************************/
 
267
        thread_db* tdbb = JRD_get_thread_data();
 
268
        Database* dbb = tdbb->getDatabase();
 
269
 
 
270
/* Uppercase owner name */
 
271
        Firebird::MetaName string(owner ? owner : "");
 
272
        string.upper7();
 
273
 
 
274
/* Uppercase charset name */
 
275
        Firebird::MetaName string2(charset ? charset : "");
 
276
        string2.upper7();
 
277
 
 
278
        int n;
 
279
        const int* fld;
 
280
 
 
281
/* Make sure relations exist already */
 
282
 
 
283
        { // scope for MSVC6
 
284
        for (const int* relfld = relfields; relfld[RFLD_R_NAME]; relfld = fld + 1)
 
285
        {
 
286
                if (relfld[RFLD_R_TYPE] == rel_persistent)
 
287
                {
 
288
                        DPM_create_relation(tdbb, MET_relation(tdbb, relfld[RFLD_R_ID]));
 
289
                }
 
290
 
 
291
                for (fld = relfld + RFLD_RPT; fld[RFLD_F_NAME]; fld += RFLD_F_LENGTH)
 
292
                        ;
 
293
        }
 
294
        } // scope for MSVC6
 
295
 
 
296
/* Store RELATIONS and RELATION_FIELDS */
 
297
 
 
298
        jrd_req* handle1 = NULL;
 
299
        jrd_req* handle2 = NULL;
 
300
        for (const int* relfld = relfields; relfld[RFLD_R_NAME]; relfld = fld + 1)
 
301
        {
 
302
                for (n = 0, fld = relfld + RFLD_RPT; fld[RFLD_F_NAME];
 
303
                         fld += RFLD_F_LENGTH)
 
304
                {
 
305
                        if (!fld[RFLD_F_MINOR])
 
306
                        {
 
307
                                const int* pFld    = fld;
 
308
                                const int* pRelFld = relfld;
 
309
                                store_relation_field(tdbb, pFld, pRelFld, n, &handle2, true);
 
310
                                n++;
 
311
                        }
 
312
                }
 
313
 
 
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);
 
317
                        X.RDB$FIELD_ID = n;
 
318
                        X.RDB$FORMAT = 0;
 
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];
 
323
 
 
324
                        if (string.length())
 
325
                        {
 
326
                                PAD(string.c_str(), X.RDB$OWNER_NAME);
 
327
                                X.RDB$OWNER_NAME.NULL = FALSE;
 
328
                        }
 
329
 
 
330
                END_STORE;
 
331
        }
 
332
 
 
333
        CMP_release(tdbb, handle1);
 
334
        CMP_release(tdbb, handle2);
 
335
        handle1 = handle2 = NULL;
 
336
 
 
337
/* Store global FIELDS */
 
338
 
 
339
        for (const gfld* gfield = (gfld*) gfields; gfield->gfld_name; gfield++)
 
340
        {
 
341
                store_global_field(tdbb, gfield, &handle1);
 
342
        }
 
343
 
 
344
        CMP_release(tdbb, handle1);
 
345
        handle1 = NULL;
 
346
 
 
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;
 
353
                }
 
354
                else {
 
355
                        PAD (DEFAULT_DB_CHARACTER_SET_NAME, X.RDB$CHARACTER_SET_NAME);
 
356
                        X.RDB$CHARACTER_SET_NAME.NULL = FALSE;
 
357
                }
 
358
        END_STORE
 
359
 
 
360
        CMP_release(tdbb, handle1);
 
361
        handle1 = NULL;
 
362
 
 
363
/* Create indices for system relations */
 
364
        add_index_set(dbb, false, 0, 0);
 
365
 
 
366
/* Create parameter types */
 
367
 
 
368
        handle1 = NULL;
 
369
 
 
370
        for (const rtyp* type = types; type->rtyp_name; ++type)
 
371
        {
 
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;
 
377
                END_STORE;
 
378
        }
 
379
 
 
380
        CMP_release(tdbb, handle1);
 
381
 
 
382
/* Store symbols for international character sets & collations */
 
383
 
 
384
        store_intlnames(tdbb, dbb);
 
385
 
 
386
/* Create generators to be used by system triggers */
 
387
 
 
388
        handle1 = NULL;
 
389
        for (const gen* generator = generators; generator->gen_name; generator++)
 
390
        {
 
391
                store_generator(tdbb, generator, &handle1);
 
392
        }
 
393
        CMP_release(tdbb, handle1);
 
394
 
 
395
// Adjust the value of the hidden generator RDB$GENERATORS
 
396
 
 
397
        DPM_gen_id(tdbb, 0, true, FB_NELEM(generators) - 1);
 
398
 
 
399
/* store system-defined triggers */
 
400
 
 
401
        handle1 = NULL;
 
402
        for (const jrd_trg* trigger = triggers; trigger->trg_relation; ++trigger)
 
403
        {
 
404
                store_trigger(tdbb, trigger, &handle1);
 
405
        }
 
406
        CMP_release(tdbb, handle1);
 
407
 
 
408
/* store trigger messages to go with triggers */
 
409
 
 
410
        handle1 = NULL;
 
411
        for (const trigger_msg* message = trigger_messages; message->trigmsg_name;
 
412
                ++message)
 
413
        {
 
414
                store_message(tdbb, message, &handle1);
 
415
        }
 
416
        CMP_release(tdbb, handle1);
 
417
 
 
418
// Store IUDFs declared automatically as system functions.
 
419
// CVC: Demonstration code to register IUDF automatically moved to functions.h
 
420
 
 
421
        store_functions(tdbb, dbb);
 
422
 
 
423
        DFW_perform_system_work();
 
424
 
 
425
        add_relation_fields(0);
 
426
 
 
427
/*
 
428
====================================================================
 
429
==
 
430
== Add security on RDB$ROLES system table
 
431
==
 
432
======================================================================
 
433
*/
 
434
 
 
435
        UCHAR buffer[MAX_ACL_SIZE];
 
436
        UCHAR* acl = buffer;
 
437
        *acl++ = ACL_version;
 
438
        *acl++ = ACL_id_list;
 
439
        *acl++ = id_person;
 
440
 
 
441
        USHORT length = string.length();
 
442
        if (length > MAX_UCHAR)
 
443
                length = MAX_UCHAR;
 
444
                
 
445
        *acl++ = (UCHAR)length;
 
446
        if (length)
 
447
        {
 
448
                const TEXT* p_1 = string.c_str();
 
449
                memcpy(acl, p_1, length);
 
450
                acl += length;
 
451
        }
 
452
        *acl++ = ACL_end;
 
453
        *acl++ = ACL_priv_list;
 
454
        *acl++ = priv_protect;
 
455
        *acl++ = priv_control;
 
456
        *acl++ = priv_delete;
 
457
        *acl++ = priv_write;
 
458
        *acl++ = priv_read;
 
459
        *acl++ = ACL_end;
 
460
        *acl++ = ACL_id_list;
 
461
        *acl++ = ACL_end;
 
462
        *acl++ = ACL_priv_list;
 
463
        *acl++ = priv_read;
 
464
        *acl++ = ACL_end;
 
465
        *acl++ = ACL_end;
 
466
        length = acl - buffer;
 
467
 
 
468
        add_security_to_sys_rel(tdbb, string, "RDB$ROLES", buffer, length);
 
469
        add_security_to_sys_rel(tdbb, string, "RDB$PAGES", buffer, length);
 
470
        // DFW writes here
 
471
        add_security_to_sys_rel(tdbb, string, "RDB$FORMATS", buffer, length);
 
472
}
 
473
 
 
474
 
 
475
USHORT INI_get_trig_flags(const TEXT* trig_name)
 
476
{
 
477
/*********************************************
 
478
 *
 
479
 *      I N I _ g e t _ t r i g _ f l a g s
 
480
 *
 
481
 *********************************************
 
482
 *
 
483
 * Functional description
 
484
 *      Return the trigger flags for a system trigger.
 
485
 *
 
486
 **************************************/
 
487
        for (const jrd_trg* trig = triggers; trig->trg_length > 0; trig++)
 
488
        {
 
489
                if (!strcmp(trig->trg_name, trig_name))
 
490
                {
 
491
                        return (trig->trg_flags);
 
492
                }
 
493
        }
 
494
 
 
495
        return (0);
 
496
}
 
497
 
 
498
 
 
499
void INI_init(void)
 
500
{
 
501
/**************************************
 
502
 *
 
503
 *      I N I _ i n i t
 
504
 *
 
505
 **************************************
 
506
 *
 
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
 
511
 *      format descriptor.
 
512
 *
 
513
 **************************************/
 
514
        thread_db* tdbb = JRD_get_thread_data();
 
515
        Database* dbb = tdbb->getDatabase();
 
516
        CHECK_DBB(dbb);
 
517
 
 
518
        const int* fld;
 
519
        for (const int* relfld = relfields; relfld[RFLD_R_NAME]; relfld = fld + 1)
 
520
        {
 
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]];
 
524
                int n = 0;
 
525
                for (fld = relfld + RFLD_RPT; fld[RFLD_F_NAME];
 
526
                        fld += RFLD_F_LENGTH)
 
527
                {
 
528
                        n++;
 
529
                }
 
530
 
 
531
                /* Set a flag if their is a trigger on the relation.  Later we may
 
532
                   need to compile it. */
 
533
 
 
534
                for (const jrd_trg* trigger = triggers; trigger->trg_relation; trigger++)
 
535
                {
 
536
                        if (relation->rel_name == names[trigger->trg_relation])
 
537
                        {
 
538
                                relation->rel_flags |= REL_sys_triggers;
 
539
                                break;
 
540
                        }
 
541
                }
 
542
 
 
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();
 
552
 
 
553
                for (fld = relfld + RFLD_RPT; fld[RFLD_F_NAME];
 
554
                         fld += RFLD_F_LENGTH, ++desc, ++itr)
 
555
                {
 
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
 
562
 
 
563
                        jrd_fld* field = FB_NEW(*dbb->dbb_permanent) jrd_fld(*dbb->dbb_permanent);
 
564
                        *itr = field;
 
565
                        field->fld_name = names[fld[RFLD_F_NAME]];
 
566
                }
 
567
        }
 
568
}
 
569
 
 
570
 
 
571
void INI_init2(void)
 
572
{
 
573
/**************************************
 
574
 *
 
575
 *      I N I _ i n i t 2
 
576
 *
 
577
 **************************************
 
578
 *
 
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.
 
583
 *
 
584
 **************************************/
 
585
        thread_db* tdbb = JRD_get_thread_data();
 
586
        Database* dbb = tdbb->getDatabase();
 
587
 
 
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;
 
591
 
 
592
        const int* fld;
 
593
        for (const int* relfld = relfields; relfld[RFLD_R_NAME]; relfld = fld + 1)
 
594
        {
 
595
                if (relfld[RFLD_R_ODS] > ENCODE_ODS(major_version, minor_original))
 
596
                {
 
597
                /*****************************************************
 
598
        **
 
599
        ** free the space allocated for RDB$ROLES
 
600
        **
 
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])
 
610
                        {
 
611
                                fld += RFLD_F_LENGTH;
 
612
                        }
 
613
                }
 
614
                else
 
615
                {
 
616
                        jrd_rel* relation = MET_relation(tdbb, relfld[RFLD_R_ID]);
 
617
                        Format* format = relation->rel_current_format;
 
618
 
 
619
                        int n = 0;
 
620
                        for (fld = relfld + RFLD_RPT; fld[RFLD_F_NAME];
 
621
                                 fld += RFLD_F_LENGTH)
 
622
                        {
 
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
 
626
                                 * in < 10 ODS
 
627
                                 */
 
628
                                if (fld[RFLD_F_NAME] == nam_f_precision ||
 
629
                                        (fld[RFLD_F_NAME] == nam_char_length &&
 
630
                                         relfld[RFLD_R_NAME] == nam_args))
 
631
                                {
 
632
                                        if (major_version >= ODS_VERSION10)
 
633
                                                n = init2_helper(fld, n, relation);
 
634
                                }
 
635
                                else if (fld[RFLD_F_NAME] == nam_statistics &&
 
636
                                         relfld[RFLD_R_NAME] == nam_i_segments)
 
637
                                {
 
638
                                        if (major_version >= ODS_VERSION11)
 
639
                                                n = init2_helper(fld, n, relation);
 
640
                                }
 
641
                                else if ((fld[RFLD_F_NAME] == nam_description ||
 
642
                                        fld[RFLD_F_NAME] == nam_sys_flag) &&
 
643
                                        relfld[RFLD_R_NAME] == nam_roles)
 
644
                                {
 
645
                                        if (major_version >= ODS_VERSION11)
 
646
                                                n = init2_helper(fld, n, relation);
 
647
                                }
 
648
                                else if (fld[RFLD_F_NAME] == nam_description &&
 
649
                                        relfld[RFLD_R_NAME] == nam_gens)
 
650
                                {
 
651
                                        if (major_version >= ODS_VERSION11)
 
652
                                                n = init2_helper(fld, n, relation);
 
653
                                }
 
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)
 
657
                                {
 
658
                                        if (major_version >= ODS_VERSION11)
 
659
                                                n = init2_helper(fld, n, relation);
 
660
                                }
 
661
                                else if (fld[RFLD_F_NAME] == nam_r_type &&
 
662
                                                 relfld[RFLD_R_NAME] == nam_relations)
 
663
                                {
 
664
                                        if (ENCODE_ODS(major_version, minor_original) >= ODS_11_1)
 
665
                                                n = init2_helper(fld, n, relation);
 
666
                                }
 
667
                                else if (fld[RFLD_F_NAME] == nam_valid_blr &&
 
668
                                                 relfld[RFLD_R_NAME] == nam_trgs)
 
669
                                {
 
670
                                        if (ENCODE_ODS(major_version, minor_original) >= ODS_11_1)
 
671
                                                n = init2_helper(fld, n, relation);
 
672
                                }
 
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)
 
676
                                {
 
677
                                        if (ENCODE_ODS(major_version, minor_original) >= ODS_11_1)
 
678
                                                n = init2_helper(fld, n, relation);
 
679
                                }
 
680
                                else if (fld[RFLD_F_NAME] == nam_debug_info &&
 
681
                                                 (relfld[RFLD_R_NAME] == nam_trgs ||
 
682
                                                  relfld[RFLD_R_NAME] == nam_procedures))
 
683
                                {
 
684
                                        if (ENCODE_ODS(major_version, minor_original) >= ODS_11_1)
 
685
                                                n = init2_helper(fld, n, relation);
 
686
                                }
 
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)
 
693
                                {
 
694
                                        if (ENCODE_ODS(major_version, minor_original) >= ODS_11_1)
 
695
                                                n = init2_helper(fld, n, relation);
 
696
                                }
 
697
                                else
 
698
                                        n = init2_helper(fld, n, relation);
 
699
                        }
 
700
 
 
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)
 
707
                        {
 
708
                                if (n-- > 0)
 
709
                                {
 
710
                                        format->fmt_length = (USHORT)MET_align(dbb, &(*desc), format->fmt_length);
 
711
                                        desc->dsc_address = (UCHAR*) (IPTR) format->fmt_length;
 
712
 
 
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))
 
717
                                        {
 
718
                                                desc->dsc_length = 80;
 
719
                                        }
 
720
 
 
721
                                        format->fmt_length += desc->dsc_length;
 
722
                                }
 
723
                        }
 
724
                }
 
725
        }
 
726
}
 
727
 
 
728
 
 
729
void INI_update_database()
 
730
{
 
731
/**************************************
 
732
 *
 
733
 *      I N I _ u p d a t e _ d a t a b a s e
 
734
 *
 
735
 **************************************
 
736
 *
 
737
 * Functional description
 
738
 *      Perform changes to ODS that were required
 
739
 *      since ODS 8 and are dynamically updatable.
 
740
 *
 
741
 * %% Note %% Update the switch() statement to reflect new major ODS
 
742
 *            addition
 
743
 **************************************/
 
744
        thread_db* tdbb = JRD_get_thread_data();
 
745
        Database* dbb = tdbb->getDatabase();
 
746
        CHECK_DBB(dbb);
 
747
 
 
748
/* If database is ReadOnly, return without upgrading ODS */
 
749
        if (dbb->dbb_flags & DBB_read_only)
 
750
                return;
 
751
 
 
752
/* check out the update version to see if we have work to do */
 
753
 
 
754
        const USHORT major_version = dbb->dbb_ods_version;
 
755
        const USHORT minor_version = dbb->dbb_minor_version;
 
756
 
 
757
/*******************************************************************
 
758
** when old engine is attaching a newer ODS database, do nothing
 
759
********************************************************************/
 
760
 
 
761
/* if database ODS is less than the server's, then upgrade */
 
762
        if (ENCODE_ODS(major_version, minor_version) >= ODS_CURRENT_VERSION)
 
763
        {
 
764
                return;
 
765
        }
 
766
 
 
767
/*******************************************************************
 
768
** when new engine is attaching an older ODS database
 
769
**   perform the necessary modifications
 
770
********************************************************************/
 
771
 
 
772
        if (major_version == ODS_VERSION8)
 
773
        {
 
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.
 
778
               PENDING WORK.
 
779
                 add_global_fields (major_version, minor_version);
 
780
                 add_relation_fields (major_version, minor_version);
 
781
               Look at add_new_triggers() for reference.
 
782
     ***/
 
783
 
 
784
                add_global_fields(minor_version);
 
785
                add_relation_fields(minor_version);
 
786
        }
 
787
 
 
788
        add_index_set(dbb, true, major_version, minor_version);
 
789
        add_new_triggers(major_version, minor_version);
 
790
 
 
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. */
 
795
 
 
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);
 
800
 
 
801
/* Only minor upgrades can occur within a major ODS, define which one
 
802
   occured here. */
 
803
        switch (major_version)
 
804
        {
 
805
        case ODS_VERSION8:
 
806
                header->hdr_ods_minor = ODS_CURRENT8;
 
807
                break;
 
808
        case ODS_VERSION9:
 
809
                header->hdr_ods_minor = ODS_CURRENT9;
 
810
                break;
 
811
        case ODS_VERSION10:
 
812
                header->hdr_ods_minor = ODS_CURRENT10;
 
813
                break;
 
814
        default:
 
815
                /* Make sure we add a new case per new major ODS. Look at code above */
 
816
                fb_assert(FALSE);
 
817
                header->hdr_ods_minor = minor_version;
 
818
                break;
 
819
        }
 
820
 
 
821
        dbb->dbb_minor_version = header->hdr_ods_minor;
 
822
        CCH_RELEASE(tdbb, &window);
 
823
 
 
824
        DFW_perform_system_work();
 
825
}
 
826
 
 
827
#ifdef NOT_USED_OR_REPLACED
 
828
static void add_generator(TEXT* generator_name, jrd_req** handle)
 
829
{
 
830
/**************************************
 
831
 *
 
832
 *      a d d _ g e n e r a t o r
 
833
 *
 
834
 **************************************
 
835
 *
 
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.
 
841
 *
 
842
 **************************************/
 
843
        const gen* generator = generators;
 
844
 
 
845
        thread_db* tdbb = JRD_get_thread_data();
 
846
 
 
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! */
 
849
 
 
850
        while (strcmp(generator->gen_name, generator_name))
 
851
        {
 
852
                ++generator;
 
853
        }
 
854
 
 
855
        store_generator(tdbb, generator, handle);
 
856
}
 
857
#endif
 
858
 
 
859
static void add_global_fields( USHORT minor_version)
 
860
{
 
861
/**************************************
 
862
 *
 
863
 *      a d d _ g l o b a l _ f i e l d s
 
864
 *
 
865
 **************************************
 
866
 *
 
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
 
871
 *      ODS change.
 
872
 *
 
873
 **************************************/
 
874
        thread_db* tdbb = JRD_get_thread_data();
 
875
 
 
876
/* add desired global fields to system relations  */
 
877
 
 
878
        jrd_req* handle = NULL;
 
879
        for (const gfld* gfield = (gfld*) gfields; gfield->gfld_name; gfield++)
 
880
        {
 
881
                if (minor_version < gfield->gfld_minor)
 
882
                {
 
883
                        store_global_field(tdbb, gfield, &handle);
 
884
                }
 
885
        }
 
886
 
 
887
        if (handle) {
 
888
                CMP_release(tdbb, handle);
 
889
        }
 
890
 
 
891
        DFW_perform_system_work();
 
892
}
 
893
 
 
894
 
 
895
static void add_index_set(Database*     dbb,
 
896
                                                  bool          update_ods,
 
897
                                                  USHORT        major_version,
 
898
                                                  USHORT        minor_version)
 
899
{
 
900
/**************************************
 
901
 *
 
902
 *      a d d _ i n d e x _ s e t
 
903
 *
 
904
 **************************************
 
905
 *
 
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).
 
910
 *
 
911
 **************************************/
 
912
        Firebird::MetaName string;
 
913
        index_desc idx;
 
914
 
 
915
        thread_db* tdbb = JRD_get_thread_data();
 
916
        jrd_req* handle1 = NULL;
 
917
        jrd_req* handle2 = NULL;
 
918
 
 
919
        for (int n = 0; n < SYSTEM_INDEX_COUNT; n++)
 
920
        {
 
921
                const ini_idx_t* index = &indices[n];
 
922
 
 
923
                /* For minor ODS updates, only add indices newer than on-disk ODS */
 
924
                if (update_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)) !=
 
929
                          major_version)))
 
930
                {
 
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 */
 
933
                        continue;
 
934
                }
 
935
 
 
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;
 
946
                        }
 
947
                        else {
 
948
                                X.RDB$INDEX_TYPE.NULL = TRUE;
 
949
                        }
 
950
                        X.RDB$SYSTEM_FLAG = 1;
 
951
                        X.RDB$INDEX_INACTIVE = 0;
 
952
 
 
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++)
 
957
                        {
 
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];
 
962
 
 
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;
 
969
                                END_STORE;
 
970
                        }
 
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,
 
975
                                                         selectivity);
 
976
                        X.RDB$INDEX_ID = idx.idx_id + 1;
 
977
                END_STORE;
 
978
 
 
979
        }
 
980
        if (handle1) {
 
981
                CMP_release(tdbb, handle1);
 
982
        }
 
983
        if (handle2) {
 
984
                CMP_release(tdbb, handle2);
 
985
        }
 
986
}
 
987
 
 
988
 
 
989
static void add_new_triggers(USHORT major_version, USHORT minor_version)
 
990
{
 
991
/**************************************
 
992
 *
 
993
 *      a d d _ n e w _ t r i g g e r s
 
994
 *
 
995
 **************************************
 
996
 *
 
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.
 
1002
 *
 
1003
 **************************************/
 
1004
        thread_db* tdbb = JRD_get_thread_data();
 
1005
 
 
1006
        jrd_req* handle1 = NULL;
 
1007
 
 
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++)
 
1010
        {
 
1011
                if ((trig->trg_ods_version > ENCODE_ODS(major_version, minor_version))
 
1012
                        && (DECODE_ODS_MAJOR(trig->trg_ods_version) == major_version))
 
1013
                {
 
1014
                        store_trigger(tdbb, trig, &handle1);
 
1015
                }
 
1016
        }
 
1017
 
 
1018
        jrd_req* handle2 = NULL;
 
1019
        for (const trigger_msg* message = trigger_messages; message->trigmsg_name; message++)
 
1020
        {
 
1021
                if ((message->trg_ods_version >
 
1022
                                ENCODE_ODS(major_version, minor_version)) &&
 
1023
                        (DECODE_ODS_MAJOR(message->trg_ods_version) == major_version))
 
1024
                {
 
1025
                        store_message(tdbb, message, &handle2);
 
1026
                }
 
1027
        }
 
1028
 
 
1029
        if (handle1) {
 
1030
                CMP_release(tdbb, handle1);
 
1031
        }
 
1032
        if (handle2) {
 
1033
                CMP_release(tdbb, handle2);
 
1034
        }
 
1035
}
 
1036
 
 
1037
 
 
1038
static void add_relation_fields( USHORT minor_version)
 
1039
{
 
1040
/**************************************
 
1041
 *
 
1042
 *      a d d _ r e l a t i o n _ f i e l d s
 
1043
 *
 
1044
 **************************************
 
1045
 *
 
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
 
1050
 *      ODS change.
 
1051
 *
 
1052
 **************************************/
 
1053
        thread_db* tdbb = JRD_get_thread_data();
 
1054
        Database* dbb = tdbb->getDatabase();
 
1055
 
 
1056
/* add desired fields to system relations, forcing a new format version */
 
1057
 
 
1058
        jrd_req* s_handle = NULL;
 
1059
        jrd_req* m_handle = NULL;
 
1060
        const int* fld;
 
1061
        for (const int* relfld = relfields; relfld[RFLD_R_NAME]; relfld = fld + 1)
 
1062
        {
 
1063
                int n = 0;
 
1064
                for (fld = relfld + RFLD_RPT; fld[RFLD_F_NAME];
 
1065
                         n++, fld += RFLD_F_LENGTH)
 
1066
                {
 
1067
                        if (minor_version < fld[RFLD_F_MINOR] ||
 
1068
                                minor_version < fld[RFLD_F_UPD_MINOR])
 
1069
                        {
 
1070
                                if (minor_version < fld[RFLD_F_MINOR])
 
1071
                                {
 
1072
                                        store_relation_field(tdbb, fld, relfld, n, &s_handle,
 
1073
                                                                                 false);
 
1074
                                }
 
1075
                                else
 
1076
                                {
 
1077
                                        modify_relation_field(tdbb, fld, relfld, &m_handle);
 
1078
                                }
 
1079
                                dsc desc;
 
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);
 
1085
                        }
 
1086
                }
 
1087
        }
 
1088
 
 
1089
        if (s_handle) {
 
1090
                CMP_release(tdbb, s_handle);
 
1091
        }
 
1092
        if (m_handle) {
 
1093
                CMP_release(tdbb, m_handle);
 
1094
        }
 
1095
 
 
1096
        DFW_perform_system_work();
 
1097
}
 
1098
 
 
1099
 
 
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,
 
1106
                                                                        const UCHAR*    acl,
 
1107
                                                                        const SSHORT    acl_length)
 
1108
{
 
1109
/**************************************
 
1110
 *
 
1111
 *      a d d _ s e c u r i t y _ t o _ s y s _ r e l
 
1112
 *
 
1113
 **************************************
 
1114
 *
 
1115
 * Functional description
 
1116
 *
 
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
 
1120
 *      privilege.
 
1121
 *
 
1122
 **************************************/
 
1123
        TEXT sec_class_name[100];
 
1124
        Firebird::MetaName default_class;
 
1125
 
 
1126
        SET_TDBB(tdbb);
 
1127
        Database* dbb = tdbb->getDatabase();
 
1128
 
 
1129
        strcpy(sec_class_name, SQL_SECCLASS_PREFIX);
 
1130
        strcat(sec_class_name, rel_name);
 
1131
 
 
1132
    bid blob_id_1;
 
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);
 
1136
 
 
1137
    bid blob_id_2;
 
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);
 
1141
 
 
1142
        default_class.printf("%s%" SQUADFORMAT, DEFAULT_CLASS,
 
1143
                        DPM_gen_id(tdbb, MET_lookup_generator(tdbb, DEFAULT_CLASS),
 
1144
                                           false, (SINT64) 1));
 
1145
 
 
1146
        jrd_req* handle1 = NULL;
 
1147
 
 
1148
        for (int cnt = 0; cnt < 6; cnt++)
 
1149
        {
 
1150
                STORE(REQUEST_HANDLE handle1) PRIV IN RDB$USER_PRIVILEGES
 
1151
                        switch (cnt)
 
1152
                        {
 
1153
                        case 0:
 
1154
                                strcpy(PRIV.RDB$USER, user_name.c_str());
 
1155
                                PRIV.RDB$PRIVILEGE[0] = 'S';
 
1156
                                PRIV.RDB$GRANT_OPTION = 1;
 
1157
                                break;
 
1158
                        case 1:
 
1159
                                strcpy(PRIV.RDB$USER, user_name.c_str());
 
1160
                                PRIV.RDB$PRIVILEGE[0] = 'I';
 
1161
                                PRIV.RDB$GRANT_OPTION = 1;
 
1162
                                break;
 
1163
                        case 2:
 
1164
                                strcpy(PRIV.RDB$USER, user_name.c_str());
 
1165
                                PRIV.RDB$PRIVILEGE[0] = 'U';
 
1166
                                PRIV.RDB$GRANT_OPTION = 1;
 
1167
                                break;
 
1168
                        case 3:
 
1169
                                strcpy(PRIV.RDB$USER, user_name.c_str());
 
1170
                                PRIV.RDB$PRIVILEGE[0] = 'D';
 
1171
                                PRIV.RDB$GRANT_OPTION = 1;
 
1172
                                break;
 
1173
                        case 4:
 
1174
                                strcpy(PRIV.RDB$USER, user_name.c_str());
 
1175
                                PRIV.RDB$PRIVILEGE[0] = 'R';
 
1176
                                PRIV.RDB$GRANT_OPTION = 1;
 
1177
                                break;
 
1178
                        default:
 
1179
                                strcpy(PRIV.RDB$USER, "PUBLIC");
 
1180
                                PRIV.RDB$PRIVILEGE[0] = 'S';
 
1181
                                PRIV.RDB$GRANT_OPTION = 0;
 
1182
                                break;
 
1183
                        }
 
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;
 
1190
                END_STORE;
 
1191
        }
 
1192
 
 
1193
        CMP_release(tdbb, handle1);
 
1194
 
 
1195
        handle1 = NULL;
 
1196
 
 
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;
 
1202
        END_STORE;
 
1203
 
 
1204
        CMP_release(tdbb, handle1);
 
1205
 
 
1206
        handle1 = NULL;
 
1207
 
 
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;
 
1213
        END_STORE;
 
1214
 
 
1215
        CMP_release(tdbb, handle1);
 
1216
 
 
1217
        handle1 = NULL;
 
1218
 
 
1219
        FOR(REQUEST_HANDLE handle1) REL IN RDB$RELATIONS
 
1220
                WITH REL.RDB$RELATION_NAME EQ rel_name
 
1221
                MODIFY REL USING
 
1222
                        REL.RDB$DEFAULT_CLASS.NULL = FALSE;
 
1223
            jrd_vtof(default_class.c_str(), REL.RDB$DEFAULT_CLASS,
 
1224
                     sizeof(REL.RDB$DEFAULT_CLASS));
 
1225
                END_MODIFY;
 
1226
 
 
1227
        END_FOR;
 
1228
 
 
1229
        CMP_release(tdbb, handle1);
 
1230
 
 
1231
}
 
1232
 
 
1233
#ifdef NOT_USED_OR_REPLACED
 
1234
static void add_trigger(TEXT* trigger_name, jrd_req** handle1, jrd_req** handle2)
 
1235
{
 
1236
/**************************************
 
1237
 *
 
1238
 *      a d d _ t r i g g e r
 
1239
 *
 
1240
 **************************************
 
1241
 *
 
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.
 
1247
 *
 
1248
 **************************************/
 
1249
        thread_db* tdbb = JRD_get_thread_data();
 
1250
 
 
1251
/* Find the new trigger to be stored; assume it exists in the table */
 
1252
 
 
1253
        const jrd_trg* trigger = triggers;
 
1254
        while (strcmp(trigger->trg_name, trigger_name))
 
1255
        {
 
1256
                ++trigger;
 
1257
        }
 
1258
 
 
1259
        store_trigger(tdbb, trigger, handle1);
 
1260
 
 
1261
/* Look for any related trigger messages */
 
1262
 
 
1263
        for (const trigger_msg* message = trigger_messages; message->trigmsg_name;
 
1264
                ++message)
 
1265
        {
 
1266
                if (!strcmp(message->trigmsg_name, trigger->trg_name))
 
1267
                {
 
1268
                        store_message(tdbb, message, handle2);
 
1269
                }
 
1270
        }
 
1271
}
 
1272
#endif
 
1273
 
 
1274
 
 
1275
static int init2_helper(const int* fld, int n, jrd_rel* relation)
 
1276
{
 
1277
        if (!fld[RFLD_F_MINOR])
 
1278
        {
 
1279
                ++n;
 
1280
                if (fld[RFLD_F_UPD_MINOR])
 
1281
                        relation->rel_flags |= REL_force_scan;
 
1282
        }
 
1283
        else
 
1284
        {
 
1285
                relation->rel_flags |= REL_force_scan;
 
1286
        }
 
1287
        return n;
 
1288
}
 
1289
 
 
1290
 
 
1291
static void modify_relation_field(thread_db*    tdbb,
 
1292
                                                                  const int*    fld,
 
1293
                                                                  const int*    relfld,
 
1294
                                                                  jrd_req**     handle)
 
1295
{
 
1296
/**************************************
 
1297
 *
 
1298
 *      m o d i f y _ r e l a t i o n _ f i e l d
 
1299
 *
 
1300
 **************************************
 
1301
 *
 
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.
 
1306
 *
 
1307
 **************************************/
 
1308
        SET_TDBB(tdbb);
 
1309
        Database* dbb = tdbb->getDatabase();
 
1310
 
 
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]]
 
1314
                MODIFY X USING
 
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];
 
1318
                END_MODIFY;
 
1319
        END_FOR;
 
1320
}
 
1321
 
 
1322
 
 
1323
static void store_generator(thread_db* tdbb, const gen* generator, jrd_req** handle)
 
1324
{
 
1325
/**************************************
 
1326
 *
 
1327
 *      s t o r e _ g e n e r a t o r
 
1328
 *
 
1329
 **************************************
 
1330
 *
 
1331
 * Functional description
 
1332
 *      Store the passed generator according to
 
1333
 *      the information in the generator block.
 
1334
 *
 
1335
 **************************************/
 
1336
        SET_TDBB(tdbb);
 
1337
        Database* dbb = tdbb->getDatabase();
 
1338
 
 
1339
        jrd_tra* trans = dbb->dbb_sys_trans;
 
1340
 
 
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)
 
1346
                {
 
1347
                        blb* blob = BLB_create(tdbb, trans, &X.RDB$DESCRIPTION);
 
1348
                        BLB_put_segment(tdbb,
 
1349
                                                        blob,
 
1350
                                                        reinterpret_cast<const UCHAR*>(generator->gen_description),
 
1351
                                                        strlen(generator->gen_description));
 
1352
                        BLB_close(tdbb, blob);
 
1353
                        X.RDB$DESCRIPTION.NULL = FALSE;
 
1354
                }
 
1355
                else
 
1356
                {
 
1357
                        X.RDB$DESCRIPTION.NULL = TRUE;
 
1358
                }
 
1359
 
 
1360
        END_STORE;
 
1361
}
 
1362
 
 
1363
 
 
1364
static void store_global_field(thread_db* tdbb, const gfld* gfield, jrd_req** handle)
 
1365
{
 
1366
/**************************************
 
1367
 *
 
1368
 *      s t o r e _ g l o b a l _ f i e l d
 
1369
 *
 
1370
 **************************************
 
1371
 *
 
1372
 * Functional description
 
1373
 *      Store a global field according to the
 
1374
 *      passed information.
 
1375
 *
 
1376
 **************************************/
 
1377
        SET_TDBB(tdbb);
 
1378
        Database* dbb = tdbb->getDatabase();
 
1379
 
 
1380
        jrd_tra* trans = dbb->dbb_sys_trans;
 
1381
 
 
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)
 
1392
                {
 
1393
                        blb* blob = BLB_create(tdbb, trans, &X.RDB$DEFAULT_VALUE);
 
1394
                        BLB_put_segment(tdbb,
 
1395
                                                        blob,
 
1396
                                                        gfield->gfld_dflt_blr,
 
1397
                                                        gfield->gfld_dflt_len);
 
1398
                        BLB_close(tdbb, blob);
 
1399
                        X.RDB$DEFAULT_VALUE.NULL = FALSE;
 
1400
                }
 
1401
                else
 
1402
                {
 
1403
                        X.RDB$DEFAULT_VALUE.NULL = TRUE;
 
1404
                }
 
1405
                switch (gfield->gfld_dtype)
 
1406
                {
 
1407
                case dtype_timestamp:
 
1408
                        X.RDB$FIELD_TYPE = (int) blr_timestamp;
 
1409
                        break;
 
1410
 
 
1411
                case dtype_sql_time:
 
1412
                        X.RDB$FIELD_TYPE = (int) blr_sql_time;
 
1413
                        break;
 
1414
 
 
1415
                case dtype_sql_date:
 
1416
                        X.RDB$FIELD_TYPE = (int) blr_sql_date;
 
1417
                        break;
 
1418
 
 
1419
                case dtype_short:
 
1420
                case dtype_long:
 
1421
                case dtype_int64:
 
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;
 
1426
                        else
 
1427
                        {
 
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;
 
1432
                                else
 
1433
                                        X.RDB$FIELD_TYPE = (int) blr_double;
 
1434
                        }
 
1435
                        if ((gfield->gfld_sub_type == dsc_num_type_numeric) ||
 
1436
                                (gfield->gfld_sub_type == dsc_num_type_decimal))
 
1437
                        {
 
1438
                                X.RDB$FIELD_SUB_TYPE.NULL = FALSE;
 
1439
                                X.RDB$FIELD_SUB_TYPE = gfield->gfld_sub_type;
 
1440
                        }
 
1441
                        break;
 
1442
 
 
1443
                case dtype_double:
 
1444
                        X.RDB$FIELD_TYPE = (int) blr_double;
 
1445
                        break;
 
1446
 
 
1447
                case dtype_text:
 
1448
                case dtype_varying:
 
1449
                        if (gfield->gfld_dtype == dtype_text)
 
1450
                        {
 
1451
                                X.RDB$FIELD_TYPE = (int) blr_text;
 
1452
                        }
 
1453
                        else
 
1454
                        {
 
1455
                                X.RDB$FIELD_TYPE = (int) blr_varying;
 
1456
                                X.RDB$FIELD_LENGTH -= sizeof(USHORT);
 
1457
                        }
 
1458
                        if (gfield->gfld_sub_type == dsc_text_type_metadata)
 
1459
                        {
 
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;
 
1466
                        }
 
1467
                        else if (gfield->gfld_sub_type == dsc_text_type_ascii)
 
1468
                        {
 
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;
 
1475
                        }
 
1476
                        else if (gfield->gfld_sub_type == dsc_text_type_fixed)
 
1477
                        {
 
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;
 
1484
                        }
 
1485
                        else
 
1486
                        {
 
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;
 
1491
                        }
 
1492
                        break;
 
1493
 
 
1494
                case dtype_blob:
 
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)
 
1501
                        {
 
1502
                                X.RDB$CHARACTER_SET_ID.NULL = FALSE;
 
1503
                                X.RDB$CHARACTER_SET_ID = CS_METADATA;
 
1504
                        }
 
1505
                        break;
 
1506
 
 
1507
                default:
 
1508
                        fb_assert(FALSE);
 
1509
                        break;
 
1510
                }
 
1511
 
 
1512
        END_STORE;
 
1513
}
 
1514
 
 
1515
 
 
1516
static void store_intlnames(thread_db* tdbb, Database* dbb)
 
1517
{
 
1518
/**************************************
 
1519
 *
 
1520
 *      s t o r e _ i n t l n a m e s
 
1521
 *
 
1522
 **************************************
 
1523
 *
 
1524
 * Functional description
 
1525
 *      Store symbolic names & information for international
 
1526
 *      character sets & collations.
 
1527
 *
 
1528
 **************************************/
 
1529
        SET_TDBB(tdbb);
 
1530
 
 
1531
        jrd_req* handle = NULL;
 
1532
        for (const CS_TYPE* csptr = cs_types; csptr->init_charset_name; csptr++)
 
1533
        {
 
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;
 
1540
                END_STORE;
 
1541
        }
 
1542
 
 
1543
        CMP_release(tdbb, handle);
 
1544
        handle = NULL;
 
1545
 
 
1546
        jrd_tra* trans = dbb->dbb_sys_trans;
 
1547
 
 
1548
        for (const COLL_TYPE* collptr = coll_types; collptr->init_collation_name; collptr++)
 
1549
        {
 
1550
                STORE(REQUEST_HANDLE handle) X IN RDB$COLLATIONS USING
 
1551
                        PAD(collptr->init_collation_name, X.RDB$COLLATION_NAME);
 
1552
 
 
1553
                        if (collptr->init_collation_base_name)
 
1554
                        {
 
1555
                                X.RDB$BASE_COLLATION_NAME.NULL = false;
 
1556
                                PAD(collptr->init_collation_base_name, X.RDB$BASE_COLLATION_NAME);
 
1557
                        }
 
1558
                        else
 
1559
                                X.RDB$BASE_COLLATION_NAME.NULL = true;
 
1560
 
 
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;
 
1565
 
 
1566
                        if (collptr->init_collation_specific_attributes)
 
1567
                        {
 
1568
                                blb* blob = BLB_create(tdbb, trans, &X.RDB$SPECIFIC_ATTRIBUTES);
 
1569
                                BLB_put_segment(tdbb,
 
1570
                                                                blob,
 
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;
 
1575
                        }
 
1576
                        else
 
1577
                                X.RDB$SPECIFIC_ATTRIBUTES.NULL = TRUE;
 
1578
 
 
1579
                END_STORE;
 
1580
        }
 
1581
 
 
1582
        CMP_release(tdbb, handle);
 
1583
        handle = NULL;
 
1584
}
 
1585
 
 
1586
static void store_function_argument(
 
1587
        thread_db* tdbb, Database* dbb,
 
1588
    jrd_req* &handle,
 
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)
 
1591
{
 
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;
 
1604
        END_STORE;
 
1605
}
 
1606
 
 
1607
static void store_function(
 
1608
        thread_db* tdbb, Database* dbb,
 
1609
    jrd_req* &handle,
 
1610
        const char* function_name, const char* module, const char* entrypoint, SLONG argument)
 
1611
{
 
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;
 
1624
        END_STORE;
 
1625
}
 
1626
 
 
1627
static void store_functions(thread_db* tdbb, Database* dbb)
 
1628
{
 
1629
/**************************************
 
1630
 *
 
1631
 *      s t o r e _ f u n c t i o n s
 
1632
 *
 
1633
 **************************************
 
1634
 *
 
1635
 * Functional description
 
1636
 *      Store built-in functions and their arguments
 
1637
 *
 
1638
 **************************************/
 
1639
        SET_TDBB(tdbb);
 
1640
 
 
1641
        jrd_req *fun_handle = NULL, *arg_handle = NULL;
 
1642
        const char *function_name;
 
1643
        SLONG argument_position;
 
1644
 
 
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++;
 
1654
 
 
1655
#include "../jrd/functions.h"
 
1656
 
 
1657
        CMP_release(tdbb, fun_handle);
 
1658
        CMP_release(tdbb, arg_handle);
 
1659
}
 
1660
 
 
1661
 
 
1662
static void store_message(thread_db* tdbb, const trigger_msg* message, jrd_req** handle)
 
1663
{
 
1664
/**************************************
 
1665
 *
 
1666
 *      s t o r e _ m e s s a g e
 
1667
 *
 
1668
 **************************************
 
1669
 *
 
1670
 * Functional description
 
1671
 *      Store system trigger messages.
 
1672
 *
 
1673
 **************************************/
 
1674
        SET_TDBB(tdbb);
 
1675
        Database* dbb = tdbb->getDatabase();
 
1676
 
 
1677
/* store the trigger */
 
1678
 
 
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);
 
1683
        END_STORE;
 
1684
}
 
1685
 
 
1686
 
 
1687
static void store_relation_field(thread_db*             tdbb,
 
1688
                                                                 const int*             fld,
 
1689
                                                                 const int*             relfld,
 
1690
                                                                 int                    field_id,
 
1691
                                                                 jrd_req**              handle,
 
1692
                                                                 bool                   fmt0_flag)
 
1693
{
 
1694
/**************************************
 
1695
 *
 
1696
 *      s t o r e _ r e l a t i o n _ f i e l d
 
1697
 *
 
1698
 **************************************
 
1699
 *
 
1700
 * Functional description
 
1701
 *      Store a local field according to the
 
1702
 *      passed information.
 
1703
 *
 
1704
 **************************************/
 
1705
        SET_TDBB(tdbb);
 
1706
        Database* dbb = tdbb->getDatabase();
 
1707
 
 
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];
 
1718
        END_STORE;
 
1719
}
 
1720
 
 
1721
 
 
1722
static void store_trigger(thread_db* tdbb, const jrd_trg* trigger, jrd_req** handle)
 
1723
{
 
1724
/**************************************
 
1725
 *
 
1726
 *      s t o r e _ t r i g g e r
 
1727
 *
 
1728
 **************************************
 
1729
 *
 
1730
 * Functional description
 
1731
 *      Store the trigger according to the
 
1732
 *      information in the trigger block.
 
1733
 *
 
1734
 **************************************/
 
1735
        SET_TDBB(tdbb);
 
1736
        Database* dbb = tdbb->getDatabase();
 
1737
 
 
1738
        jrd_tra* trans = dbb->dbb_sys_trans;
 
1739
 
 
1740
/* indicate that the relation format needs revising */
 
1741
        dsc desc;
 
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);
 
1747
 
 
1748
/* store the trigger */
 
1749
 
 
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,
 
1759
                                                blob,
 
1760
                                                trigger->trg_blr,
 
1761
                                                trigger->trg_length);
 
1762
                BLB_close(tdbb, blob);
 
1763
        END_STORE;
 
1764
}
 
1765