byte* mlog_parse_index( /*=============*/ /* out: parsed record end, NULL if not a complete record */ byte* ptr, /* in: buffer */ byte* end_ptr,/* in: buffer end */ /* out: new value of log_ptr */ ibool comp, /* in: TRUE=compact record format */ dict_index_t** index) /* out, own: dummy index */ { ulint i, n, n_uniq; dict_table_t* table; dict_index_t* ind; ut_ad(comp == FALSE || comp == TRUE); if (comp) { if (end_ptr < ptr + 4) { return(NULL); } n = mach_read_from_2(ptr); ptr += 2; n_uniq = mach_read_from_2(ptr); ut_ad(n_uniq <= n); if (end_ptr < ptr + (n + 1) * 2) { return(NULL); } } else { n = n_uniq = 1; } table = dict_mem_table_create("LOG_DUMMY", DICT_HDR_SPACE, n, comp); ind = dict_mem_index_create("LOG_DUMMY", "LOG_DUMMY", DICT_HDR_SPACE, 0, n); ind->table = table; ind->n_uniq = n_uniq; if (n_uniq != n) { ind->type = DICT_CLUSTERED; } /* avoid ut_ad(index->cached) in dict_index_get_n_unique_in_tree */ ind->cached = TRUE; if (comp) { for (i = 0; i < n; i++) { ulint len = mach_read_from_2(ptr += 2); /* The high-order bit of len is the NOT NULL flag; the rest is 0 or 0x7fff for variable-length fields, and 1..0x7ffe for fixed-length fields. */ dict_mem_table_add_col(table, "DUMMY", ((len + 1) & 0x7fff) <= 1 ? DATA_BINARY : DATA_FIXBINARY, len & 0x8000 ? DATA_NOT_NULL : 0, len & 0x7fff, 0); dict_index_add_col(ind, dict_table_get_nth_col(table, i), 0, 0); } ptr += 2; } *index = ind; return(ptr); }
/********************************************************//** Parses a log record written by mlog_open_and_write_index. @return parsed record end, NULL if not a complete record */ UNIV_INTERN byte* mlog_parse_index( /*=============*/ byte* ptr, /*!< in: buffer */ const byte* end_ptr,/*!< in: buffer end */ ibool comp, /*!< in: TRUE=compact record format */ dict_index_t** index) /*!< out, own: dummy index */ { ulint i, n, n_uniq; dict_table_t* table; dict_index_t* ind; ut_ad(comp == FALSE || comp == TRUE); if (comp) { if (end_ptr < ptr + 4) { return(NULL); } n = mach_read_from_2(ptr); ptr += 2; n_uniq = mach_read_from_2(ptr); ptr += 2; ut_ad(n_uniq <= n); if (end_ptr < ptr + n * 2) { return(NULL); } } else { n = n_uniq = 1; } table = dict_mem_table_create("LOG_DUMMY", DICT_HDR_SPACE, n, comp ? DICT_TF_COMPACT : 0); ind = dict_mem_index_create("LOG_DUMMY", "LOG_DUMMY", DICT_HDR_SPACE, 0, n); ind->table = table; ind->n_uniq = (unsigned int) n_uniq; if (n_uniq != n) { ut_a(n_uniq + DATA_ROLL_PTR <= n); ind->type = DICT_CLUSTERED; } if (comp) { for (i = 0; i < n; i++) { ulint len = mach_read_from_2(ptr); ptr += 2; /* The high-order bit of len is the NOT NULL flag; the rest is 0 or 0x7fff for variable-length fields, and 1..0x7ffe for fixed-length fields. */ dict_mem_table_add_col( table, NULL, NULL, ((len + 1) & 0x7fff) <= 1 ? DATA_BINARY : DATA_FIXBINARY, len & 0x8000 ? DATA_NOT_NULL : 0, len & 0x7fff); dict_index_add_col(ind, table, dict_table_get_nth_col(table, i), 0); } dict_table_add_system_columns(table, table->heap); if (n_uniq != n) { /* Identify DB_TRX_ID and DB_ROLL_PTR in the index. */ ut_a(DATA_TRX_ID_LEN == dict_index_get_nth_col(ind, DATA_TRX_ID - 1 + n_uniq)->len); ut_a(DATA_ROLL_PTR_LEN == dict_index_get_nth_col(ind, DATA_ROLL_PTR - 1 + n_uniq)->len); ind->fields[DATA_TRX_ID - 1 + n_uniq].col = &table->cols[n + DATA_TRX_ID]; ind->fields[DATA_ROLL_PTR - 1 + n_uniq].col = &table->cols[n + DATA_ROLL_PTR]; } } /* avoid ut_ad(index->cached) in dict_index_get_n_unique_in_tree */ ind->cached = TRUE; *index = ind; return(ptr); }
/********************************************************//** Parses a log record written by mlog_open_and_write_index. @return parsed record end, NULL if not a complete record */ UNIV_INTERN byte* mlog_parse_index( /*=============*/ byte* ptr, /*!< in: buffer */ const byte* end_ptr,/*!< in: buffer end */ ibool comp, /*!< in: TRUE=compact record format */ dict_index_t** index) /*!< out, own: dummy index */ { ulint i, n, n_uniq; dict_table_t* table; dict_index_t* ind; ibool is_gcs = FALSE; ulint n_fields_before_alter = 0; /* 快速alter table前聚集索引的字段数 */ ut_ad(comp == FALSE || comp == TRUE); if (comp) { if (end_ptr < ptr + 4) { return(NULL); } n = mach_read_from_2(ptr); if (n & 0x8000) /* 最高位为1表示GCS表 */ { is_gcs = TRUE; n &= 0x7FFF; } ptr += 2; if (is_gcs) { n_fields_before_alter = mach_read_from_2(ptr); ut_ad(n_fields_before_alter < n && n_fields_before_alter > 0); ptr += 2; /* 确保地址有效!*/ if (end_ptr < ptr + 2) { return(NULL); } } n_uniq = mach_read_from_2(ptr); ptr += 2; ut_ad(n_uniq <= n); if (end_ptr < ptr + n * 2) { return(NULL); } } else { n = n_uniq = 1; } table = dict_mem_table_create("LOG_DUMMY", DICT_HDR_SPACE, n, comp ? DICT_TF_COMPACT : 0, is_gcs, n_fields_before_alter); ind = dict_mem_index_create("LOG_DUMMY", "LOG_DUMMY", DICT_HDR_SPACE, 0, n); ind->table = table; ind->n_uniq = (unsigned int) n_uniq; if (n_uniq != n) { ut_a(n_uniq + DATA_ROLL_PTR <= n); ind->type = DICT_CLUSTERED; } if (comp) { for (i = 0; i < n; i++) { ulint len = mach_read_from_2(ptr); ptr += 2; /* The high-order bit of len is the NOT NULL flag; the rest is 0 or 0x7fff for variable-length fields, and 1..0x7ffe for fixed-length fields. */ /* redo阶段压缩属性不需指定 */ dict_mem_table_add_col( table, NULL, NULL, ((len + 1) & 0x7fff) <= 1 ? DATA_BINARY : DATA_FIXBINARY, /* 若len 为0或0x7fff,可认为是变长字段;否则是定长字段 */ len & 0x8000 ? DATA_NOT_NULL : 0, len & 0x7fff); if (is_gcs && n_fields_before_alter > 0 && n_fields_before_alter <= i) { dict_col_t* col = NULL; col = dict_table_get_nth_col(table, i); /* 添加默认值信息,但只是占位符,并不需真正的默认值信息 */ if (!dict_col_is_nullable(col)) dict_mem_table_set_col_default(table, col, table->heap); } dict_index_add_col(ind, table, dict_table_get_nth_col(table, i), 0); } dict_table_add_system_columns(table, table->heap); if (n_uniq != n) { /* Identify DB_TRX_ID and DB_ROLL_PTR in the index. */ ut_a(DATA_TRX_ID_LEN == dict_index_get_nth_col(ind, DATA_TRX_ID - 1 + n_uniq)->len); ut_a(DATA_ROLL_PTR_LEN == dict_index_get_nth_col(ind, DATA_ROLL_PTR - 1 + n_uniq)->len); ind->fields[DATA_TRX_ID - 1 + n_uniq].col = &table->cols[n + DATA_TRX_ID]; ind->fields[DATA_ROLL_PTR - 1 + n_uniq].col = &table->cols[n + DATA_ROLL_PTR]; /* set the col_ind col->ind */ ind->fields[DATA_TRX_ID - 1 + n_uniq].col_ind = ind->fields[DATA_TRX_ID - 1 + n_uniq].col->ind; ind->fields[DATA_ROLL_PTR - 1 + n_uniq].col_ind = ind->fields[DATA_ROLL_PTR - 1 + n_uniq].col->ind; } if (dict_index_is_gcs_clust_after_alter_table(ind)) { ut_ad(table->n_cols == table->n_def); ut_a(table->n_cols_before_alter_table > 0 && table->n_cols_before_alter_table <= table->n_cols); ind->n_fields_before_alter = n_fields_before_alter; ind->n_nullable_before_alter = dict_index_get_first_n_field_n_nullable(ind, ind->n_fields_before_alter); } else { ind->n_fields_before_alter = 0; ind->n_nullable_before_alter = 0; } } /* avoid ut_ad(index->cached) in dict_index_get_n_unique_in_tree */ ind->cached = TRUE; *index = ind; return(ptr); }