diff --git a/HACKING b/HACKING index a15676a..336db8e 100644 --- a/HACKING +++ b/HACKING @@ -242,6 +242,11 @@ Number of characters in a Memo field: 65,535 when entering data through the user interface; 2 gigabytes of character storage when entering data programmatically. That would mean 31 bits for length. +Note: if a memo field is marked for compression, only at value which is at +most 1024 characters when uncompressed can be compressed. fields longer than +that _must_ be stored uncompressed. + + LVAL (Long Value) Pages ----------------------- @@ -306,7 +311,7 @@ next_pg field. | ???? | 2 bytes | max_cols | Max columns a row will have (deletions) | | ???? | 2 bytes | num_var_cols| Number of variable columns in table | | ???? | 2 bytes | num_cols | Number of columns in table (repeat) | -| ???? | 4 bytes | num_idx | Number of indexes in table | +| ???? | 4 bytes | num_idx | Number of logical indexes in table | | ???? | 4 bytes | num_real_idx| Number of index entries | | ???? | 4 bytes | used_pages | Points to a record containing the | | | | | usage bitmask for this table. | @@ -337,14 +342,14 @@ next_pg field. | ???? | 1 byte | col_name_len| len of the name of the column | | ???? | n bytes | col_name | Name of the column | +-------------------------------------------------------------------------+ -| Iterate for indexes with index_type 0 or 1 (30+9 = 39 bytes) | +| Iterate for the number of num_real_idx (30+9 = 39 bytes) | +-------------------------------------------------------------------------+ | Iterate 10 times for 10 possible columns (10*3 = 30 bytes) | +-------------------------------------------------------------------------+ | ???? | 2 bytes | col_num | number of a column (0xFFFF= none) | | ???? | 1 byte | col_order | 0x01 = ascendency order | +-------------------------------------------------------------------------+ -| ???? | 4 bytes | unknown | | +| ???? | 4 bytes | used_pages | Points to usage bitmap for index | | ???? | 4 bytes | first_dp | Data pointer of the index page | | ???? | 1 byte | flags | See flags table for indexes | +-------------------------------------------------------------------------+ @@ -353,11 +358,14 @@ next_pg field. | ???? | 4 bytes | index_num | Number of the index | | | | |(warn: not always in the sequential order)| | ???? | 4 bytes | index_num2 | Index into index cols list | -| 0x00 | 1 byte | ??? | | -| 0xFF | 4 bytes | ??? | | -| 0x00 | 4 bytes | ??? | | -| 0x04 | 2 bytes | ??? | | -| ???? | 1 byte | primary_key | 0x01 if this index is primary | +| 0x00 | 1 byte | rel_tbl_type| type of the other table in this fk | +| | | | (same values as index_type) | +| 0xFF | 4 bytes | rel_idx_num | index number of other index in fk | +| | | | (or -1 if this index is not a fk) | +| 0x00 | 4 bytes | rel_tbl_page| page number of other table in fk | +| 0x01 | 1 byte | cascade_ups | flag indicating if updates are cascaded | +| 0x01 | 1 byte | cascade_dels| flag indicating if deletes are cascaded | +| ???? | 1 byte | index_type | 0x01 if index is primary, 0x02 if foreign| +-------------------------------------------------------------------------+ | Iterate for the number of num_idx | +-------------------------------------------------------------------------+ @@ -367,8 +375,10 @@ next_pg field. | Iterate while col_num != 0xffff | +-------------------------------------------------------------------------+ | ???? | 2 bytes | col_num | Column number with variable length | -| ???? | 4 bytes | arg1 | | -| ???? | 4 bytes | arg2 | | +| ???? | 4 bytes | used_pages | Points to a record containing the | +| | | | usage bitmask for this column. | +| ???? | 4 bytes | free_pages | Points to a similar record as above, | +| | | | listing pages which contain free space. | +-------------------------------------------------------------------------+ +-------------------------------------------------------------------------+ @@ -390,7 +400,7 @@ next_pg field. | ???? | 2 bytes | max_cols | Max columns a row will have (deletions) | | ???? | 2 bytes | num_var_cols| Number of variable columns in table | | ???? | 2 bytes | num_cols | Number of columns in table (repeat) | -| ???? | 4 bytes | num_idx | Number of indexes in table | +| ???? | 4 bytes | num_idx | Number of logical indexes in table | | ???? | 4 bytes | num_real_idx| Number of index entries | | ???? | 4 bytes | used_pages | Points to a record containing the | | | | | usage bitmask for this table. | @@ -425,7 +435,7 @@ next_pg field. | ???? | 2 bytes | col_name_len| len of the name of the column | | ???? | n bytes | col_name | Name of the column (UCS-2 format) | +-------------------------------------------------------------------------+ -| Iterate for indexes with index_type 0 or 1 (30+22 = 52 bytes) | +| Iterate for the number of num_real_idx (30+22 = 52 bytes) | +-------------------------------------------------------------------------+ | ???? | 4 bytes | ??? | | +-------------------------------------------------------------------------+ @@ -434,7 +444,7 @@ next_pg field. | ???? | 2 bytes | col_num | number of a column (0xFFFF= none) | | ???? | 1 byte | col_order | 0x01 = ascendency order | +-------------------------------------------------------------------------+ -| ???? | 4 bytes | unknown | | +| ???? | 4 bytes | used_pages | Points to usage bitmap for index | | ???? | 4 bytes | first_dp | Data pointer of the index page | | ???? | 1 byte | flags | See flags table for indexes | | ???? | 9 bytes | unknown | | @@ -445,12 +455,14 @@ next_pg field. | ???? | 4 bytes | index_num | Number of the index | | | | |(warn: not always in the sequential order)| | ???? | 4 bytes | index_num2 | Index into index cols list | -| 0x00 | 1 byte | ??? | | -| 0xFF | 4 bytes | ??? | | -| 0x00 | 4 bytes | ??? | | -| 0x04 | 2 bytes | ??? | | -| ???? | 1 byte | primary_key | 0x01 if this index is primary | -| ???? | 4 bytes | unknown | | +| 0x00 | 1 byte | rel_tbl_type| type of the other table in this fk | +| | | | (same values as index_type) | +| 0xFF | 4 bytes | rel_idx_num | index number of other index in fk | +| | | | (or -1 if this index is not a fk) | +| 0x00 | 4 bytes | rel_tbl_page| page number of other table in fk | +| 0x01 | 1 byte | cascade_ups | flag indicating if updates are cascaded | +| 0x01 | 1 byte | cascade_dels| flag indicating if deletes are cascaded | +| ???? | 1 byte | index_type | 0x01 if index is primary, 0x02 if foreign| +-------------------------------------------------------------------------+ | Iterate for the number of num_idx | +-------------------------------------------------------------------------+ @@ -460,8 +472,10 @@ next_pg field. | Iterate while col_num != 0xffff | +-------------------------------------------------------------------------+ | ???? | 2 bytes | col_num | Column number with variable length | -| ???? | 4 bytes | arg1 | | -| ???? | 4 bytes | arg2 | | +| ???? | 4 bytes | used_pages | Points to a record containing the | +| | | | usage bitmask for this column. | +| ???? | 4 bytes | free_pages | Points to a similar record as above, | +| | | | listing pages which contain free space. | +-------------------------------------------------------------------------+ Columns flags (not complete): @@ -500,6 +514,29 @@ Column Type may be one of the following (not complete): REPID = 0x0F /* GUID */ NUMERIC = 0x10 /* Scaled decimal (17 bytes) */ +Notes on reading index metadata: + +There are 2 types of index metadata, "physical" index info (denoted by +num_real_idx) and "logical" index info (denoted by num_idx). Normally, there +is a 1 to 1 relationship between these 2 types of information. However there +can be more logical index infos than physical index infos (currently only seen +for foreign key indexes). In this situation, one or more of the logical +indexes actually share the same underlying physical index (the index_num2 +indicates which physical index backs which logical index). + +As noted in the previous paragraph, physical index sharing is generally only +seen when a foreign key index has been created. When access creates a +relationship between 2 tables with "enforce referential integrity" enabled, +each of the tables gets an extra logical index with type 2 (foreign key). +These logical indexes contain extra information, primarily pointers to the +related table (rel_tbl_page) and logical index (rel_idx_num). Also, the +rel_tbl_type value indicates which table in the relationship is the "primary" +table (the one one from which cascaded updates/deletes flow). If the indexed +columns for the foreign key are already indexed by another logical index in +the table (e.g. an index which the user has explicitly created), then the +logical foreign key index will simply share the underlying physical index +data. + Notes on deleted and added columns: (sort of Jet4 specific) If a fixed length column is deleted the offset_F field will contain the offsets