WinTarif
Firebird ODS для FbOdsViewer
Menu

Приветствую Вас, Гость · RSS 26.04.2024, 21:40


see FbOdsViewer

Standard Database Page Header

Pag_type: One byte, signed. Byte 0x00 on the page. This byte defines the page type for the page. Valid page types are:
  • 0x00 - Undefined page. You should never see this in a database.

  • 0x01 - The database header page. Only ever seen on the very first page of the database, or, on the first page of each database file in a multi-file database.

  • 0x02 - The Page Inventory Page (PIP). This page keeps track of allocated and free pages using a bitmap where a 1 means the page is free and a zero shows a used page. There may be more than one PIP in a database, but the first PIP is always page 1.

  • 0x03 - Transaction Inventory Page (TIP). A page that keeps track of the stat of transactions. Each transaction is represented by a pair of bits in a bitmap. Valid values in these two bits are:

    • 00 - this transaction is active.

    • 01 - this transaction is in limbo.

    • 10 - this transaction is dead.

    • 11 - this transaction has committed.

  • 0x04 - Pointer Page. Each table has one or more of these and this page type keeps track of all the pages that make up the table. Pointer pages are owned by one and only one table, there is no sharing allowed. Each pointer in the array on these pages holds the page number for a type 5 page holding data for the table.

  • 0x05 - Data Page. These pages store the actual data for a table.

  • 0x06 - Index Root Page. Similar to a type 4 Pointer Page, but applies to indexes only.

  • 0x07 - Index B-Tree Page. Similar to the type 5 Data Page, but applies to indexex only.

  • 0x08 - Blob Page. Blobs have their own storage within the database. Very large blobs will require a sequence of pages and the type 8 page holds blob data.

  • 0x09 - Generator Page. Holds an array of 64 bit generators.

  • 0x0a - Page 2 of any database is a Write Ahead Log page. These pages are no longer used. The page will remain blank (filled with binary zero) as it is never used. This page has a standard header like all others.

Pag_flags: One byte, unsigned. Byte 0x01 on the page. This byte holds various flags for the page.

Pag_checksum: Two bytes, unsigned. Bytes 0x02 - 0x03. Checksum for the whole page. No longer used, always 12345, 0x3039. Databases using ODS8 on Windows NT do have a valid checksum here.

Pag_generation: Four bytes, unsigned. Bytes 0x04 - 0x07. The page generation number. Increments each time the page is written back to disc.

Pag_scn: Four bytes, unsigned. Bytes 0x08 - 0x0b. Originally used as the sequence number in the Write Ahead Log, but WAL is no longer used. The field was converted to be the SCN number to avoid an ODS change and is now used by nbackup.

Pag_reserved: Four bytes, unsigned. Bytes 0x0c - 0x0f. Reserved for future use. It was originally used for the offset of a page's entry in the Write Ahead Log (WAL), but this is no longer in use.


Database Header page

Hdr_header: The database header page has a standard page header, as do all pages.

Hdr_page_size: Two bytes, unsigned. Bytes 0x10 - 0x11 on the page. This is the page size, in bytes, for each and every page in the database.

Hds_ods_version: Two bytes, unsigned. Bytes 0x12 and 0x13 on the page. The ODS major version for the database. The format of this word is the ODS major version ANDed with the Firebird flag of 0x8000. In the example below, the value is 0x800b for ODS version 11. The minor ODS version is held elsewhere in the header page - see hdr_ods_minor below.

Hdr_pages: Four bytes, signed. Bytes 0x14 - 0x17 on the page. This is the page number of the first pointer page for the table named RDB$PAGES. When this location is known, the database engine uses it to determine the locations of all other matadata pages in the database. This field is only valid in the header page of the first file in a multi-file database. The remaining files in the database have this field set to zero.

Hdr_next_page: Four bytes, unsigned. Bytes 0x18 - 0x1b on the page. The page number of the header page in the next file of the database - if this is a multi-file database. Zero otherwise.

Hdr_oldest_transaction: Four bytes, signed. Bytes 0x1c - 0x1f on the page. The transaction id of the oldest active (ie, uncommitted - but may be in limbo or rolled back) transaction against this database. This field is only valid in the header page of the first file in a multi-file database. The remaining files in the database have this field set to zero.

Hdr_oldest_active: Four bytes, signed. Bytes 0x20 - 0x23 on the page. The transaction id of the oldest active transaction against this database, when any active transaction started. This field is only valid in the header page of the first file in a multi-file database. The remaining files in the database have this field set to zero.

Hdr_next_transaction: Four bytes, signed. Bytes 0x24 - 0x27 on the page. The transaction id that will be assigned to the next transaction against this database. This field is only valid in the header page of the first file in a multi-file database. The remaining files in the database have this field set to zero.

Hdr_sequence: Two bytes, unsigned. Bytes 0x28 and 0x29 on the page. The sequence number of this file within the database.

Hdr_flags: Two bytes, unsigned. Bytes 0x2a and 0x2b on the page. The database flags. The bits in the flag bytes are used as follows:

Flag Name Flag value Description
hdr_active_shadow 0x01 (bit 0) This file is an active shadow file.
hdr_force_write 0x02 (bit 1) The database is in forced writes mode.
Unused 0x04 (bit 2) Was previously for short term journalling, no longer used.
Unused 0x08 (bit 3) Was previously for long term journalling, no longer used.
hdr_no_checksums 0x10 (bit 4) Don't calculate checksums.
hdr_no_reserve 0x20 (bit 5) Don'r reserve space for record versions in pages.
Unused 0x40 (bit 6) Was used to indicate that the shared cache file was disabled.
hdr_shutdown_mask (bit one of two) 0x1080 (bits 7 and 12) Used with bit 12 (see below) to indicate the database shutdown mode.
hdr_sql_dialect_3 0x100 (bit 8) If set, the database is using SQL dialect 3.
hdr_read_only 0x200 (bit 9) Database is in read only mode.
hdr_backup_mask 0xC00 (bits 10 and 11) Indicates the current backup mode.
hdr_shutdown_mask (bit two of two) 0x1080 (bits 7 and 12) Used with bit 7 (see above) to indicate the database shutdown mode.

The final two database flags use a pair of bits to indicate various states of backup and shutdown.

Hdr_backup_mask: These two bits determine the current database backup mode, as follows:

Flag Value Description
0x00 (Both bits zero) Database is not in backup mode. User changes are written directly to the database files.
0x400 The database is running in backup mode so all changed made by the users are written to the diff file.
0x800 The database is still in backup mode, but changes are being merged from the diff file into the main pages.
0xC00 The current database state is unknown and changes need to be read from disc.

Hdr_shutdown_mask: The shutdown mask uses two bits to indicate the current database shutdown status, as follows:

Flag Value Description
0x00 (Both bits 7 and 12 are zero) Database is not shutdown. Any valid user can connect.
0x80 The database has been shutdown to, or started up in multi-user maintenance mode. The database can only be conncted to by SYSDBA or the database owner.
0x1000 The database has been fully shutdown. No connections are permitted.
0x1080 The database has been shutdown to, or started up in single-user maintenance mode. Only one SYSDBA or database owner connection is permitted.

Hdr_creation_date: Eight bytes, signed. Bytes 0x2c - 0x33 on the page. The data and time (in Firebird's own internal format) that the database was either originally created/rewritten or created from a backup.

Hdr_attachment_id: Four bytes, signed. Bytes 0x34 - 0x37 on the page. The id number that will be assigned to the next connection to this database. As this is signed, the maximum value here is 232-1 and any database which reaches this maximum value must be backed up and restored in order to allow new connections. This field is only valid in the header page of the first file in a multi-file database. The remaining files in the database have this field set to zero.

Hdr_shadow_count: Four bytes, signed. Bytes 0x38 - 0x3c on the page. Holds the event count for shadow file synchronisation for this database. The remaining files in the database have this field set to zero.

Hdr_implementation: Two bytes, signed. Bytes 0x3c and 0x3d on the page. This is a number which indicates the environment on which the database was originally created. It is used to determine if the database file can be used sucessfully on the current hardware. This avoids problems caused by little-endian numerical values as compared with big-endian, for example.

Hdr_ods_minor: Two bytes, unsigned. Bytes 0x3e and 0x3f on the page. The current ODS minor version.

Hdr_ods_minor_original: Two bytes, unsigned. Bytes 0x40 and 0x41 on the page. The ODS minor version when the database was originally created.

Hdr_end: Two bytes, unsigned. Bytes 0x42 and 0x43 on the page. The offset on the page where the hdr_data finishes. In other words, where a new clumplet will be stored if required. This is effectively a pointer to the current location of HDR_end (see clumplet details below) on this page.

Hdr_page_buffers: Four bytes, unsigned. Bytes 0x44 - 0x47 on the page. Holds the number of buffers to be used for the database cache, or zero to indicate that the default value should be used. This field is only valid in the header page of the first file in a multi-file database. The remaining files in the database have this field set to zero.

Hdr_bumped_transaction: Four bytes, signed. Bytes 0x48 - 0x4b on the page. Used to be used for the bumped transaction id for log optimisation, but is currently always set to 0x01. This field is only valid in the header page of the first file in a multi-file database. The remaining files in the database have this field set to zero.

Hdr_oldest_snapshot: Four bytes, signed. Bytes 0x4c - 0x4f on the page. Holds the transaction number for the oldest snapshot of active transactions. This is also documented as the confusing and redundant variant of Oldest Active Transaction.

Hdr_backup_pages: Four bytes, signed. Bytes 0x50 - 0x53 on the page. Holds the number of pages in the database currently locked for a backup using nbackup. This field is only valid in the header page of the first file in a multi-file database. The remaining files in the database have this field set to zero.

Hdr_misc: Twelve bytes. Bytes 0x54 - 0x5f on the page. Set to zero. These 12 bytes are currently unused.

Hdr_data: The variable data area on the header page begins at offset 0x60. Data stored here is held in clumplets and there are a number of different clumplet types, see below. This area is used to store filenames for the next file and other miscellaneous pieces of data relating to the database.

The format of each clumplet is as follows:

Type_byte: The first byte - unsigned - in each clumplet determines the type of data stored within the clumplet. There are a number of different clumplet types:

Type Name Value Description
HDR_end 0x00 End of clumplets.
HDR_root_file_name 0x01 Original name of the root file for this database.
HDR_journal_server 0x02 Name of the journal server.
HDR_file 0x03 Secondary file name.
HDR_last_page 0x04 Last logical page of the current file.
HDR_unlicemsed 0x05 Count of unlicensed activity. No longer used.
HDR_sewwp_interval 0x06 Number of transactions between sweep.
HDR_log_name 0x07 Replay log name.
HDR_journal_file 0x08 Intermediate journal filename.
HDR_password_file_key 0x09 Key to compare with the password database.
HDR_backup_info 0x0a Write Ahead Log (WAL) backup information. No longer used.
HDR_cache_file 0x0b Shared cache file. No longer used.
HDR_difference_file 0x0c Diff file used during the times when the database is in backup mode.
HDR_backup_guid 0x0d UID generated when database is in backup mode. Overwritten on subsequent backups.

Length_byte: The second byte - again unsigned - in each clumplet specifies the size of the data that follows.


Page Inventory Page

Every database has at least one Page Inventory Page (PIP) with the first one always being page 1, just after the database header page. If more are required, the current PIP points to the next PIP by way of the very last bit on the page itself. The C code representation of the PIP page is:

Pip_header: The PIP starts off with a standard page header.

Pip_min: Four bytes, signed. Bytes 0x10 - 0x13 on the page. This is the bit number of the first page, on this PIP, which is currently free for use.

Pip_bits: Bytes 0x14 onwards. The remainder of the page, is an array of single bits where each bit represents a page in the database. If the bit is set (1) then that page is free for use. If the bit is unset (0) then the page has been used.

If the database is large, and requires another PIP elsewhere in the database, then the last bit on this PIP represents the page number for the next PIP. For example, on a 4,096 byte page we have a total of 4,076 bytes to represent different pages in the database. As each byte has 8 bits, we have a total of 32,608 pages before we need a new PIP.


Transaction Inventory Page

Every database has at least one Transaction Inventory Page (TIP).

The highest possible transaction number is 2,147,483,647 or 0x7fffffff in a 32 bit system. Once you hit this transaction, no more can be created and the database needs to be shutdown, backed up and then restored to reset the transaction numbers back to zero. The reason it has this maximum value is simply because the code for allocating transaction numbers uses a signed value.

Tip_header: The TIP starts off with a standard page header.

Tip_next: Four bytes, signed. Bytes 0x10 - 0x13 on the page. This is the page number of the next TIP page, if one exists, within the database. Zero here indicates that the current TIP page is the last TIP page.

Tip_transactions: Bytes 0x14 onwards. The remainder of the page, is an array of two bit values where each pair of bits represents a transaction and its status. Each transaction can have one of 4 status values:

  • 0x00 - this transaction is active, or has not yet started.

  • 0x01 - this transaction is in limbo. A two phase transaction has committed the first phase but the second phase has not committed.

  • 0x02 - this transaction is dead (was rolled back).

  • 0x03 - this transaction was committed.


Pointer Page

A pointer page is used internally to hold a list of all - or as may will fit on one pointer page - data pages (see below) that make up a single table. Large tables may have more than one pointer page but every table, system or user, will have a minimum of one pointer page. The RDB$PAGES table is where the Firebird engine looks to find out where a table is located within the physical database, however, RDB$PAGES is itself a table, and when the database is running, how exactly can it find the start page for RDB$PAGES in order to look it up?

The database header page contains the page number for RDB$PAGES at bytes 0x14 - 0x17 on the page. From experimentation, it appears as if this is always page 0x03, however, this cannot be relied upon and if you need to do this, you should always check the database header page to determine where RDB$PAGES is to be found.

Ppg_header: A pointer page starts with a standard page header. In the header, the pag_flags field is used and is set to the value 1 if this is the final pointer page for the relation.

Ppg_sequence: Four bytes, signed. Offset 0x10 to 0x13 on the page. The sequence number of this pointer page in the list of pointer pages for the table. Starts at zero.

Ppg_next: Four bytes, signed. Offset 0x14 to 0x17 on the page. The page number of the next pointer page for this table. Zero indicates that this is the final pointer page.

Ppg_count: Two bytes, unsigned. Offset 0x18 and 0x19 on the page. This field holds the count of active slots (in the ppg_page[] array) on this pointer page, that are in use. As the array starts at zero, this is also the index of the first free slot on this pointer page.

Ppg_relation: Two bytes, unsigned. Offset 0x1a and 0x1b on the page. This field holds the RDB$RELATIONS.RDB$REALTION_ID for the table that this pointer page represents.

Ppg_min_space: Two bytes, unsigned. Offset 0x1c and 0x1d on the page. This indicates the first entry in the ppg_page array holding a page number which has free space in the page.

Ppg_max_space: Two bytes, unsigned. Offset 0x1e and 0x1f on the page. This was intended to indicate the last entry in the ppg_page array holding a page number which has free space in the page, but it has never been used. These two bytes are invariably set to zero.

Ppg_page: An array of four byte signed values, starting at offset 0x20. Each value in this array represents a page number where a part of the current table is to be found. A value of zero in a slot indicates that the slot is not in use. Deleting all the data from a table will result in all slots being set to zero.

Page fill bitmaps: At the end of each pointer page is a bitmap array of two bit entries which is indexed by the same index as the ppg_page array. These bitmaps indicate that the page is available for use in storing records (or record versions) or not. The two bits in the bitmap indicate whether a large object (BLOB?) is on this page and the other bit indicates that the page is full. If either bit is set (page has a large object or page is full, then the page is not used for new records or record versions.

The location of the bitmaps on each page is dependent on the page size. The bigger the page, the more slots in the ppg_page array it can hold and so the bitmap is bigger. A bigger bitmap starts at a lower address in the page and so on. From looking inside a few databases with a 4Kb page size, the bitmaps begin at offset 0x0f10 on the page.


Data page

A data page belongs exclusively to a single table. The page starts off, as usual, with the standard page header and is followed by an array of pairs of unsigned two byte values representing the 'table of contents' for this page. This array fills from the top of the page (lowest address, increasing) while the actual data it points to is stored on the page and fills from the bottom of the page (highest address, descending).

Dpg_header: The page starts with a standard page header. In this page type, the pag_flags byte is used as follows:
  • Bit 0 - dpg_orphan. Setting this bit indicates that this page is an orphan - it has no entry in the pointer page for this relation. This may indicate a possible database corruption.

  • Bit 1 - dpg_full. Setting this bit indicates that the page is full up. This will be also seen in the bitmap array on the corresponding pointer page for this table.

  • Bit 2 - dpg_large. Setting this bit indicates that a large object is stored on this page. This will be also seen in the bitmap array on the corresponding pointer page for this table.

Dpg_sequence: Four bytes, signed. Offset 0x10 on the page. This field holds the sequence number for this page in the list of pages assigned to this table within the database. The first page of any table has sequence zero.

Dpg_relation: Two bytes, unsigned. Offset 0x12 on the page. The relation number for this table. This corresponds to RDB$RELATIONS.RDB$RELATION_ID.

Dpg_count: Two bytes, unsigned. Offset 0x14 on the page. The number of records (or record fragments) on this page. In other words, the number of entries in the dpg_rpt array.

Dpg_rpt: This is an array of two byte unsigned values. The array begins at offset 0x18 on the page and counts upwards from the low address to the higher address as each new record fragment is added.

The two fields in this array are:

Dpg_offset: Two bytes, unsigned. The offset on the page where the record fragment starts. If the value here is zero and the length is zero, then this is an unused array entry. The offset is from the start address of the page. For example, if the offset is 0x0fc8 and this is a database with a 4Kb page size, and the page in question is page 0xcd (205 decimal) then we have the offset of 0xcdfc8 because 0xcd000 is the actual address (in the database file) of the start of the page.

Dpg_length: Two bytes, unsigned. The length of this record fragment in bytes.

The raw record data is structured into a header and the data.

Record Header

Each record's data is preceeded by a record header. The format of the header is shown below. Note that there are two different record headers, one for fragmented records and the other for unfragmented records.

Both headers are identical up to the rhd_format field. In the case of an unfragmented record there are no more fields in the header while the header for a fragmented record has a few more fields. How to tell the difference? See the details of the rdf_flags field below.

Rhd_transaction: Four bytes, signed. Offset 0x00 in the header. This is the id of the transaction that created this record.

Rhd_b_page: Four bytes, signed. Offset 0x04 in the header. This is the record's back pointer page.

Rhd_b_line: Two bytes, unsigned. Offset 0x08 in the header. This is the record's back line pointer.

Rhd_flags: Two bytes, unsigned. Offset 0x0a in the header. The flags for this record or record fragment. The flags are discussed below.

Flag Name Flag value Description
rhd_deleted 0x01 (bit 0) Record is logically deleted.
rhd_chain 0x02 (bit 1) Record is an old version.
rhd_fragment 0x04 (bit 2) Record is a fragment.
rhd_incomplete 0x08 (bit 3) Record is incomplete.
rhd_blob 0x10 (bit 4) This is not a record, it is a blob. This bit also affects the usage of bit 5.
rhd_stream_blob/rhd_delta 0x20 (bit 5) This blob (bit 4 set) is a stream blob, or, prior version is differences only (bit 4 clear).
rhd_large 0x40 (bit 6) Object is large.
rhd_damaged 0x80 (bit 7) Object is know to be damaged.
rhd_gc_active 0x100 (bit 8) Garbage collecting a dead record version.

Rhd_format: One byte, unsigned. Offset 0x0c in the header. The record format version.

Rhd_data: Unsigned byte data. Offset 0x0d in the header. This is the start of the compressed data. For a fragmented record header, this field is not applicable.

The following only apply to the fragmented record header. For an unfragmented record, the data begins at offset 0x0d. Fragmented records store their data at offset 0x16.

Rhdf_f_page: Four bytes, signed. Offset 0x10 (Padding bytes inserted). The page number on which the next fragment of this record can be found.

Rhdf_f_line: Two bytes, unsigned. Offset 0x14. The line number on which the next fragment for this record can be found.

Rhdf_data: Unsigned byte data. Offset 0x16 in the header. This is the start of the compressed data for this record fragment.

Record Data

Record data is always stored in a compressed format, even if the data itself cannot be compressed.

The compression is a type known as Run Length Encoding (RLE) where a sequence of repeating characters is reduced to a control byte that determines the repeat count followed by the actual byte to be repeated. Where data cannot be compressed, the control byte indicates that "the next 'n' characters are to be output unchanged".

The usage of a control byte is as follows:

  • Positive n - the next 'n' bytes are stored 'verbatim'.

  • Negative n - the next byte is repeated 'n' times, but stored only once.

  • Zero - if detected, end of data. Normally a padding byte.

The data in a record is not compressed based on data found in a previously inserted record - it cannot be. If you have the word 'Firebird' in two records, it will be stored in full in both. The same applies to fields in the same record - all storage compression is done within each individual field and previously compressed fields have no effect on the current one. (In other words, Firebird doesn't use specialised 'dictionary' based compression routines such as LHZ, ZIP, GZ etc)

Repeating short strings such as 'abcabcabc' are also not compressed.

Once the compression of the data in a column has been expanded, the data consists of three parts - a field header, the actual data and, if necessary, some padding bytes.

Obviously, when decompressing the data, the decompression code needs to be able to know which bytes in the data are control bytes. This is done by making the first byte a control byte. Knowing this, the decompression code is easily able to convert the stored data back to the uncompressed state.


Index Root Page

Every table in the database has an Index Root Page which holds data that describes the indexes for that table. Even tables that have no indices defined have an index root page.

Irt_header: The page starts with a standard page header. The flags byte - pag_flags - is not used on this page type.

Irt_relation: Two bytes, unsigned. Offset 0x10 on the page. The relation id. This is the value of RDB$RELATIONS.RDB$RELATION_ID.

Irt_count: Two bytes, unsigned. Offset 0x12 on the page. The number of indices defined for this table. If there are no indices defined this counter will show the value zero. (Every table in the database has an Index Root Page regardless of whether or not it has any indices defined.)

Irt_rpt: This is an array of index descriptors. The array begins at offset 0x14 on the page with the descriptor for the first index defined for the table. Descriptors are added to the 'top' of the array so the next index defined will have its descriptor at a higher page address than the previous descriptor. The descriptor entries consist of the following 6 fields (irt_root through irt_flags). Each descriptor is 0x0b bytes long.

Irt_root: Four bytes, signed. Offset 0x00 in each descriptor array entry. This field is the page number where the root page for the individual index (page type 0x07) is located.

Irt_selectivity: Four bytes, signed floating point. Offset 0x04 in each descriptor array entry. This is the same offset as for irt_transaction below. In ODS versions previous to 11.0 this field holds the index selectivity in floating point format.

Irt_transaction: Four bytes, signed. Offset 0x04 in each descriptor array entry - the same offset as irt_selectivity above. Normally this field will be zero but if an index is in the process of being created, the transaction id will be found here.

Irt_desc: Two bytes, unsigned. Offset 0x08 in each descriptor array entry. This field holds the offset, from the start of the page, to the index field descriptors which are located at the bottom end (ie, highest addresses) of the page. To calculate the starting address, add the value in this field to the address of the start of the page.

Irt_keys: One byte, unsigned. Offset 0x0a in each descriptor array entry. This defines the number of keys (columns) in this index.

Irt_flags: One byte, unsigned. Offset 0x0b in each descriptor array entry. The flags define various attributes for this index, these are encoded into various bits in the field, as follows:

  • Bit 0 : Index is unique (set) or not (unset).

  • Bit 1 : Index is descending (set) or ascending (unset).

  • Bit 2 : Index [creation?] is in progress (set) or not (unset).

  • Bit 3 : Index is a foreign key index (set) or not (unset).

  • Bit 4 : Index is a primary key index (set) or not (unset).

  • Bit 5 : Index is expression based (set) or not (unset).

Each descriptor entry in the array holds an offset to a list of key descriptors. These start at the highest address on the page and extend towards the lowest address. (The array of index descriptors (irt_rpt) starts at a low address on the page and increases upwards. At some point, they will meet and the page will be full.

The index field descriptors are defined as follows:

Irtd_field: Two bytes, unsigned. Offset 0x00 in each field descriptor. This field defines the field number of the table that makes up 'this' field in the index. This number is equivalent to RDB$RELATION_FIELDS.RDB$FIELD_ID.

Irtd_itype: Two bytes, unsigned. Offset 0x02 in each field descriptor. This determines the data type of the appropriate field in the index. The allowed values in this field are:

  • 0 : field is numeric, but is not a 64 bit integer.

  • 1 : field is string data.

  • 3 : Field is a byte array.

  • 4 : Field is metadata.

  • 5 : Field is a date.

  • 6 : Field is a time.

  • 7 : Field is a timestamp.

  • 8 : field is numeric - and is a 64 bit integer.

You may note from the above that an irtd_itype with value 2 is not permitted.

Irtd_selectivity: Four bytes, floating point format. Offset 0x04 in each field descriptor. This field holds the selectivity of this particular column in the index. This applies to ODS 11.0 onwards. In pre ODS 11.0 databases, this field is not part of the index field descriptors and selectivity is applied to the index as a whole. See irt_selectivity above.


Index B-Tree Page

B-Tree Header

Btr_header: The page starts off with a standard page header. The pag_flags byte is used on these pages. The bits used and why are:
  • Bit 0 : set means do not garbage collect this page.

  • Bit 1 : set means this page is not propogated upwards.

  • Bit 3 : set means that this page/bucket is part of a descending index.

  • Bit 4 : set means that non-leaf nodes will contain record number information.

  • Bit 5 : set means that large keys are permitted/used.

  • Bit 6 : set means that the page contains index jump nodes.

Btr_sibling: Four bytes, signed. Bytes 0x10 - 0x13 on the page. This is the page number of the next page of this index. The values on the next page are higher than all of those on this page. A value of zero here indicates that this is the final page in the index.

Btr_left_sibling: Four bytes, signed. Bytes 0x14 - 0x17 on the page. This is the page number of the previous page of this index. The values on the previous page are lower than all of those on this page. A value of zero here indicates that this is the first page in the index.

Btr_prefix_total: Four bytes, signed. Bytes 0x18 - 0x1b on the page. The sum of all the bytes saved on this page by using prefix compression.

Btr_relation: Two bytes, unsigned. Bytes 0x1c and 0x1d on the page. The relation id (RDB$RELATION_ID in RDB$RELATIONS) for the table that this index applies to.

Btr_length: Two bytes, unsigned. Bytes 0x1e and 0x1f on the page. The number of bytes used, for data, on this page. Acts as an offste to the first unused byte on the page.

Btr_id: One byte, unsigned. Byte 0x20 on the page. The index id (RDB$INDEX_ID in RDB$INDICES) for this index.

Btr_level: One byte, unsigned. Byte 0x21 on the page. The index level. Level zero indicates a leaf node.

Index Jump Info

FirstNodeOffset: Two bytes, unsigned. Offset 0x00 in the structure. This is the offset, in bytes, to the first of the Index Nodes (see below) on this page.

JumpAreaSize: Two bytes, unsigned. Offset 0x02 in the structure. The value here is the number of bytes left to be used before we have to create a new jump node.

Jumpers: One byte, unsigned. Offset 0x05 in the structure. The running total of the current number of Jump Nodes on this page. There can be a maximum of 255 Index Jump Nodes on a page.

Index Jump Nodes

The Index Jump Info structure described above is followed by zero or more Index Jump Nodes. The number to be found is determined by the jumpers value in the Index Jump Info structure.

Index Nodes

Btr_nodes: Index nodes are described below and are used to hold the data for one entry in this index.

Btn_prefix: One byte, unsigned. Byte 0x00 in the node. This is the size of the compressed prefix.

Btn_length: One byte, unsigned. Byte 0x01 in the node. This is the size of the data in the index entry.

Btn_number: Four bytes, unsigned. Bytes 0x02 - 0x05 in the node. The page number (or record number) where the data that this index entry represents, is to be found.

Index Data

Btn_data: The data that makes up the index entry is found at bytes 0x06 onwards in the node.


Blob Data Page

Blp_header: The blob page starts off with a standard page header.

Blp_lead_page: Four bytes, signed. Bytes 0x10 - 0x13. This field holds the page number for the first page for this blob.

Blp_sequence: Four bytes, signed. Bytes 0x14 - 0x17. The sequence number of this page within the page range for this blob.

Blp_length: Two bytes, unsigned. Bytes 0x18 and 0x19. The length of the blob data on this page, in bytes.

Blp_pad: Two bytes, unsigned. Bytes 0x1a and 0x1b. Not used for any data, used as padding.

Blp_page: This location in the page is at byte 0x1c. It has two purposes:

  • An array of four byte, signed page numbers representing all the pages in this blob; or

  • An array of bytes making up the blob data on this page.

If the flag byte in the standard page header (pag_flags) is set to 1, this blob page contains no data but acts as a pointer page to all the other blob pages for this particular blob.


Generator Page

Every database has at least one Generator Page, even if no generators (also known as sequences in Firebird 2.x) have been defined by the user. A blank database consisting only of system tables and indices already has a number of generators created for use in naming constraints, indices, etc.

Gpg_header: The generator page starts off with a standard page header.

Gpg_sequence: Four bytes, signed. Bytes 0x10 - 0x13. The sequence number of this generator page, starting from zero. If so many generators have been created that new generator pages are required, the sequence number will be incremented for each one.

Gpg_waste: Twelve bytes. Bytes 0x14 to 0x1f. To quote the source code, these values are overhead carried forward for backward compatibility. In other words, most likely unused.

Gpg_values: An array of 64 bit values, one for each generator in the database.

© 2024 Vladimir Klimov WinTarif@narod.ru
Конструктор сайтов - uCoz