Commit 94dfa010 authored by unknown's avatar unknown

Virtual column support for new innodb.

parent a06a844d
......@@ -2182,7 +2182,7 @@ ha_innobase::ha_innobase(
TABLE_SHARE* table_arg)
:handler(hton, table_arg),
int_table_flags(HA_REC_NOT_IN_SEQ |
HA_NULL_IN_KEY |
HA_NULL_IN_KEY | HA_CAN_VIRTUAL_COLUMNS |
HA_CAN_INDEX_BLOBS |
HA_CAN_SQL_HANDLER |
HA_PRIMARY_KEY_REQUIRED_FOR_POSITION |
......@@ -4921,7 +4921,7 @@ ha_innobase::open(
if (ib_table
&& ((!DICT_TF2_FLAG_IS_SET(ib_table, DICT_TF2_FTS_HAS_DOC_ID)
&& table->s->fields != dict_table_get_n_user_cols(ib_table))
&& table->s->stored_fields != dict_table_get_n_user_cols(ib_table))
|| (DICT_TF2_FLAG_IS_SET(ib_table, DICT_TF2_FTS_HAS_DOC_ID)
&& (table->s->fields
!= dict_table_get_n_user_cols(ib_table) - 1)))) {
......@@ -5080,7 +5080,7 @@ ha_innobase::open(
DBUG_RETURN(HA_ERR_NO_SUCH_TABLE);
}
prebuilt = row_create_prebuilt(ib_table, table->s->reclength);
prebuilt = row_create_prebuilt(ib_table, table->s->stored_rec_length);
prebuilt->default_rec = table->s->default_values;
ut_ad(prebuilt->default_rec);
......@@ -6128,9 +6128,10 @@ build_template_needs_field(
primary key columns */
dict_index_t* index, /*!< in: InnoDB index to use */
const TABLE* table, /*!< in: MySQL table object */
ulint i) /*!< in: field index in InnoDB table */
ulint i, /*!< in: field index in InnoDB table */
ulint sql_idx) /*!< in: field index in SQL table */
{
const Field* field = table->field[i];
const Field* field = table->field[sql_idx];
ut_ad(index_contains == dict_index_contains_col_or_prefix(index, i));
......@@ -6147,8 +6148,8 @@ build_template_needs_field(
return(field);
}
if (bitmap_is_set(table->read_set, i)
|| bitmap_is_set(table->write_set, i)) {
if (bitmap_is_set(table->read_set, sql_idx)
|| bitmap_is_set(table->write_set, sql_idx)) {
/* This field is needed in the query */
return(field);
......@@ -6203,7 +6204,7 @@ build_template_field(
mysql_row_templ_t* templ;
const dict_col_t* col;
ut_ad(field == table->field[i]);
//ut_ad(field == table->field[i]);
ut_ad(clust_index->table == index->table);
col = dict_table_get_nth_col(index->table, i);
......@@ -6275,10 +6276,10 @@ ha_innobase::build_template(
{
dict_index_t* index;
dict_index_t* clust_index;
ulint n_fields;
ulint n_stored_fields;
ibool fetch_all_in_key = FALSE;
ibool fetch_primary_key_cols = FALSE;
ulint i;
ulint i, sql_idx;
if (prebuilt->select_lock_type == LOCK_X) {
/* We always retrieve the whole clustered index record if we
......@@ -6331,11 +6332,11 @@ ha_innobase::build_template(
/* Below we check column by column if we need to access
the clustered index. */
n_fields = (ulint) table->s->fields; /* number of columns */
n_stored_fields= (ulint)table->s->stored_fields; /* number of stored columns */
if (!prebuilt->mysql_template) {
prebuilt->mysql_template = (mysql_row_templ_t*)
mem_alloc(n_fields * sizeof(mysql_row_templ_t));
mem_alloc(n_stored_fields * sizeof(mysql_row_templ_t));
}
prebuilt->template_type = whole_row
......@@ -6353,7 +6354,12 @@ ha_innobase::build_template(
if (active_index != MAX_KEY && active_index == pushed_idx_cond_keyno) {
/* Push down an index condition or an end_range check. */
for (i = 0; i < n_fields; i++) {
for (i = 0, sql_idx = 0; i < n_stored_fields; i++, sql_idx++) {
while (!table->field[sql_idx]->stored_in_db) {
sql_idx++;
}
const ibool index_contains
= dict_index_contains_col_or_prefix(index, i);
......@@ -6378,14 +6384,14 @@ ha_innobase::build_template(
mysql_row_templ_t* templ;
if (whole_row) {
field = table->field[i];
field = table->field[sql_idx];
} else {
field = build_template_needs_field(
index_contains,
prebuilt->read_just_key,
fetch_all_in_key,
fetch_primary_key_cols,
index, table, i);
index, table, i, sql_idx);
if (!field) {
continue;
}
......@@ -6466,7 +6472,12 @@ ha_innobase::build_template(
/* Include the fields that are not needed in index condition
pushdown. */
for (i = 0; i < n_fields; i++) {
for (i = 0, sql_idx = 0; i < n_stored_fields; i++, sql_idx++) {
while (!table->field[sql_idx]->stored_in_db) {
sql_idx++;
}
const ibool index_contains
= dict_index_contains_col_or_prefix(index, i);
......@@ -6476,14 +6487,14 @@ ha_innobase::build_template(
const Field* field;
if (whole_row) {
field = table->field[i];
field = table->field[sql_idx];
} else {
field = build_template_needs_field(
index_contains,
prebuilt->read_just_key,
fetch_all_in_key,
fetch_primary_key_cols,
index, table, i);
index, table, i, sql_idx);
if (!field) {
continue;
}
......@@ -6500,11 +6511,15 @@ ha_innobase::build_template(
/* No index condition pushdown */
prebuilt->idx_cond = NULL;
for (i = 0; i < n_fields; i++) {
for (i = 0, sql_idx = 0; i < n_stored_fields; i++, sql_idx++) {
const Field* field;
while (!table->field[sql_idx]->stored_in_db) {
sql_idx++;
}
if (whole_row) {
field = table->field[i];
field = table->field[sql_idx];
} else {
field = build_template_needs_field(
dict_index_contains_col_or_prefix(
......@@ -6512,7 +6527,7 @@ ha_innobase::build_template(
prebuilt->read_just_key,
fetch_all_in_key,
fetch_primary_key_cols,
index, table, i);
index, table, i, sql_idx);
if (!field) {
continue;
}
......@@ -6946,7 +6961,7 @@ calc_row_difference(
ulint n_changed = 0;
dfield_t dfield;
dict_index_t* clust_index;
uint i;
uint sql_idx, innodb_idx= 0;
ibool changes_fts_column = FALSE;
ibool changes_fts_doc_col = FALSE;
trx_t* trx = thd_to_trx(thd);
......@@ -6960,8 +6975,10 @@ calc_row_difference(
/* We use upd_buff to convert changed fields */
buf = (byte*) upd_buff;
for (i = 0; i < n_fields; i++) {
field = table->field[i];
for (sql_idx = 0; sql_idx < n_fields; sql_idx++) {
field = table->field[sql_idx];
if (!field->stored_in_db)
continue;
o_ptr = (const byte*) old_row + get_field_offset(table, field);
n_ptr = (const byte*) new_row + get_field_offset(table, field);
......@@ -6979,7 +6996,7 @@ calc_row_difference(
field_mysql_type = field->type();
col_type = prebuilt->table->cols[i].mtype;
col_type = prebuilt->table->cols[innodb_idx].mtype;
switch (col_type) {
......@@ -7046,7 +7063,8 @@ calc_row_difference(
from the MySQL column format to the InnoDB format */
if (n_len != UNIV_SQL_NULL) {
dict_col_copy_type(prebuilt->table->cols + i,
dict_col_copy_type(prebuilt->table->cols +
innodb_idx,
dfield_get_type(&dfield));
buf = row_mysql_store_col_in_innobase_format(
......@@ -7064,7 +7082,7 @@ calc_row_difference(
ufield->exp = NULL;
ufield->orig_len = 0;
ufield->field_no = dict_col_get_clust_pos(
&prebuilt->table->cols[i], clust_index);
&prebuilt->table->cols[innodb_idx], clust_index);
n_changed++;
/* If an FTS indexed column was changed by this
......@@ -7098,6 +7116,8 @@ calc_row_difference(
}
}
}
if (field->stored_in_db)
innodb_idx++;
}
/* If the update changes a column with an FTS index on it, we
......@@ -7217,13 +7237,14 @@ ha_innobase::update_row(
if (upd_buf == NULL) {
ut_ad(upd_buf_size == 0);
/* Create a buffer for packing the fields of a record. Why
table->reclength did not work here? Obviously, because char
fields when packed actually became 1 byte longer, when we also
stored the string length as the first byte. */
/* Create a buffer for packing the fields of a record. Why
table->stored_rec_length did not work here? Obviously,
because char fields when packed actually became 1 byte
longer, when we also stored the string length as the first
byte. */
upd_buf_size = table->s->reclength + table->s->max_key_length
+ MAX_REF_PARTS * 3;
upd_buf_size = table->s->stored_rec_length +
table->s->max_key_length + MAX_REF_PARTS * 3;
upd_buf = (uchar*) my_malloc(upd_buf_size, MYF(MY_WME));
if (upd_buf == NULL) {
upd_buf_size = 0;
......@@ -8707,18 +8728,18 @@ create_table_def(
if (flags2 & DICT_TF2_FTS) {
/* Adjust for the FTS hidden field */
if (!has_doc_id_col) {
table = dict_mem_table_create(table_name, 0, n_cols + 1,
table = dict_mem_table_create(table_name, 0, form->s->stored_fields + 1,
flags, flags2);
/* Set the hidden doc_id column. */
table->fts->doc_col = n_cols;
table->fts->doc_col = form->s->stored_fields;
} else {
table = dict_mem_table_create(table_name, 0, n_cols,
table = dict_mem_table_create(table_name, 0, form->s->stored_fields,
flags, flags2);
table->fts->doc_col = doc_id_col;
}
} else {
table = dict_mem_table_create(table_name, 0, n_cols,
table = dict_mem_table_create(table_name, 0, form->s->stored_fields,
flags, flags2);
}
......@@ -8738,6 +8759,8 @@ create_table_def(
for (i = 0; i < n_cols; i++) {
Field* field = form->field[i];
if (!field->stored_in_db)
continue;
col_type = get_innobase_type_from_mysql_type(&unsigned_type,
field);
......@@ -9644,7 +9667,7 @@ ha_innobase::create(
DBUG_ASSERT(thd != NULL);
DBUG_ASSERT(create_info != NULL);
if (form->s->fields > REC_MAX_N_USER_FIELDS) {
if (form->s->stored_fields > REC_MAX_N_USER_FIELDS) {
DBUG_RETURN(HA_ERR_TOO_MANY_FIELDS);
} else if (srv_read_only_mode) {
DBUG_RETURN(HA_ERR_TABLE_READONLY);
......
......@@ -235,7 +235,7 @@ ha_innobase::check_if_supported_inplace_alter(
DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
}
if (altered_table->s->fields > REC_MAX_N_USER_FIELDS) {
if (altered_table->s->stored_fields > REC_MAX_N_USER_FIELDS) {
/* Deny the inplace ALTER TABLE. MySQL will try to
re-create the table and ha_innobase::create() will
return an error too. This is how we effectively
......@@ -364,8 +364,7 @@ ha_innobase::check_if_supported_inplace_alter(
key_part++) {
const Create_field* new_field;
DBUG_ASSERT(key_part->fieldnr
< altered_table->s->fields);
DBUG_ASSERT(key_part->fieldnr < altered_table->s->fields);
cf_it.rewind();
for (uint fieldnr = 0; (new_field = cf_it++);
......@@ -426,7 +425,7 @@ ha_innobase::check_if_supported_inplace_alter(
}
DBUG_ASSERT(!prebuilt->table->fts || prebuilt->table->fts->doc_col
<= table->s->fields);
<= table->s->stored_fields);
DBUG_ASSERT(!prebuilt->table->fts || prebuilt->table->fts->doc_col
< dict_table_get_n_user_cols(prebuilt->table));
......@@ -1135,18 +1134,22 @@ innobase_rec_to_mysql(
const ulint* offsets)/*!< in: rec_get_offsets(
rec, index, ...) */
{
uint n_fields = table->s->fields;
uint n_fields = table->s->stored_fields;
uint sql_idx = 0;
ut_ad(n_fields == dict_table_get_n_user_cols(index->table)
- !!(DICT_TF2_FLAG_IS_SET(index->table,
DICT_TF2_FTS_HAS_DOC_ID)));
for (uint i = 0; i < n_fields; i++) {
Field* field = table->field[i];
for (uint i = 0; i < n_fields; i++, sql_idx++) {
Field* field;
ulint ipos;
ulint ilen;
const uchar* ifield;
while (!((field= table->field[sql_idx])->stored_in_db))
sql_idx++;
field->reset();
ipos = dict_index_get_nth_col_or_prefix_pos(index, i, TRUE);
......@@ -1185,16 +1188,20 @@ innobase_fields_to_mysql(
const dict_index_t* index, /*!< in: InnoDB index */
const dfield_t* fields) /*!< in: InnoDB index fields */
{
uint n_fields = table->s->fields;
uint n_fields = table->s->stored_fields;
uint sql_idx = 0;
ut_ad(n_fields == dict_table_get_n_user_cols(index->table)
- !!(DICT_TF2_FLAG_IS_SET(index->table,
DICT_TF2_FTS_HAS_DOC_ID)));
for (uint i = 0; i < n_fields; i++) {
Field* field = table->field[i];
for (uint i = 0; i < n_fields; i++, sql_idx++) {
Field* field;
ulint ipos;
while (!((field= table->field[sql_idx])->stored_in_db))
sql_idx++;
field->reset();
ipos = dict_index_get_nth_col_or_prefix_pos(index, i, TRUE);
......@@ -1228,17 +1235,21 @@ innobase_row_to_mysql(
const dict_table_t* itab, /*!< in: InnoDB table */
const dtuple_t* row) /*!< in: InnoDB row */
{
uint n_fields = table->s->fields;
uint n_fields = table->s->stored_fields;
uint sql_idx = 0;
/* The InnoDB row may contain an extra FTS_DOC_ID column at the end. */
ut_ad(row->n_fields == dict_table_get_n_cols(itab));
ut_ad(n_fields == row->n_fields - DATA_N_SYS_COLS
- !!(DICT_TF2_FLAG_IS_SET(itab, DICT_TF2_FTS_HAS_DOC_ID)));
for (uint i = 0; i < n_fields; i++) {
Field* field = table->field[i];
for (uint i = 0; i < n_fields; i++, sql_idx++) {
Field* field;
const dfield_t* df = dtuple_get_nth_field(row, i);
while (!((field= table->field[sql_idx])->stored_in_db))
sql_idx++;
field->reset();
if (dfield_is_ext(df) || dfield_is_null(df)) {
......@@ -1531,12 +1542,15 @@ innobase_fts_check_doc_id_col(
{
*fts_doc_col_no = ULINT_UNDEFINED;
const uint n_cols = altered_table->s->fields;
const uint n_cols = altered_table->s->stored_fields;
uint sql_idx = 0;
uint i;
for (i = 0; i < n_cols; i++) {
const Field* field = altered_table->s->field[i];
for (i = 0; i < n_cols; i++, sql_idx++) {
const Field* field;
while (!((field= altered_table->field[sql_idx])->
stored_in_db))
sql_idx++;
if (my_strcasecmp(system_charset_info,
field->field_name, FTS_DOC_ID_COL_NAME)) {
continue;
......@@ -1861,7 +1875,8 @@ innobase_create_key_defs(
&& !innobase_fts_check_doc_id_col(
NULL, altered_table,
&fts_doc_id_col)) {
fts_doc_id_col = altered_table->s->fields;
fts_doc_id_col =
altered_table->s->stored_fields;
add_fts_doc_id = true;
}
......@@ -1916,7 +1931,7 @@ innobase_create_key_defs(
index->name = mem_heap_strdup(
heap, FTS_DOC_ID_INDEX_NAME);
ut_ad(!add_fts_doc_id
|| fts_doc_id_col == altered_table->s->fields);
|| fts_doc_id_col == altered_table->s->stored_fields);
} else {
char* index_name;
index->name = index_name = static_cast<char*>(
......@@ -2351,13 +2366,14 @@ innobase_build_col_map(
dtuple_t* add_cols,
mem_heap_t* heap)
{
uint old_i, old_innobase_i;
DBUG_ENTER("innobase_build_col_map");
DBUG_ASSERT(altered_table != table);
DBUG_ASSERT(new_table != old_table);
DBUG_ASSERT(dict_table_get_n_cols(new_table)
>= altered_table->s->fields + DATA_N_SYS_COLS);
>= altered_table->s->stored_fields + DATA_N_SYS_COLS);
DBUG_ASSERT(dict_table_get_n_cols(old_table)
>= table->s->fields + DATA_N_SYS_COLS);
>= table->s->stored_fields + DATA_N_SYS_COLS);
DBUG_ASSERT(!!add_cols == !!(ha_alter_info->handler_flags
& Alter_inplace_info::ADD_COLUMN));
DBUG_ASSERT(!add_cols || dtuple_get_n_fields(add_cols)
......@@ -2368,34 +2384,46 @@ innobase_build_col_map(
List_iterator_fast<Create_field> cf_it(
ha_alter_info->alter_info->create_list);
uint i = 0;
uint i = 0, sql_idx = 0;
/* Any dropped columns will map to ULINT_UNDEFINED. */
for (uint old_i = 0; old_i + DATA_N_SYS_COLS < old_table->n_cols;
old_i++) {
col_map[old_i] = ULINT_UNDEFINED;
for (old_innobase_i = 0;
old_innobase_i + DATA_N_SYS_COLS < old_table->n_cols;
old_innobase_i++) {
col_map[old_innobase_i] = ULINT_UNDEFINED;
}
while (const Create_field* new_field = cf_it++) {
for (uint old_i = 0; table->field[old_i]; old_i++) {
if (!new_field->stored_in_db)
{
sql_idx++;
continue;
}
for (old_i = 0, old_innobase_i= 0;
table->field[old_i];
old_i++) {
const Field* field = table->field[old_i];
if (!table->field[old_i]->stored_in_db)
continue;
if (new_field->field == field) {
col_map[old_i] = i;
col_map[old_innobase_i] = i;
goto found_col;
}
old_innobase_i++;
}
innobase_build_col_map_add(
heap, dtuple_get_nth_field(add_cols, i),
altered_table->s->field[i],
altered_table->s->field[sql_idx],
dict_table_is_comp(new_table));
found_col:
i++;
sql_idx++;
}
DBUG_ASSERT(i == altered_table->s->fields);
DBUG_ASSERT(i == altered_table->s->stored_fields);
i = table->s->fields;
i = table->s->stored_fields;
/* Add the InnoDB hidden FTS_DOC_ID column, if any. */
if (i + DATA_N_SYS_COLS < old_table->n_cols) {
......@@ -2405,17 +2433,17 @@ innobase_build_col_map(
DICT_TF2_FTS_HAS_DOC_ID));
DBUG_ASSERT(i + DATA_N_SYS_COLS + 1 == old_table->n_cols);
DBUG_ASSERT(!strcmp(dict_table_get_col_name(
old_table, table->s->fields),
old_table, table->s->stored_fields),
FTS_DOC_ID_COL_NAME));
if (altered_table->s->fields + DATA_N_SYS_COLS
if (altered_table->s->stored_fields + DATA_N_SYS_COLS
< new_table->n_cols) {
DBUG_ASSERT(DICT_TF2_FLAG_IS_SET(
new_table,
DICT_TF2_FTS_HAS_DOC_ID));
DBUG_ASSERT(altered_table->s->fields
DBUG_ASSERT(altered_table->s->stored_fields
+ DATA_N_SYS_COLS + 1
== new_table->n_cols);
col_map[i] = altered_table->s->fields;
col_map[i] = altered_table->s->stored_fields;
} else {
DBUG_ASSERT(!DICT_TF2_FLAG_IS_SET(
new_table,
......@@ -2533,6 +2561,7 @@ prepare_inplace_alter_table_dict(
const ulint* col_map = NULL;
dtuple_t* add_cols = NULL;
ulint num_fts_index;
uint sql_idx;
DBUG_ENTER("prepare_inplace_alter_table_dict");
DBUG_ASSERT((add_autoinc_col != ULINT_UNDEFINED)
......@@ -2656,7 +2685,7 @@ prepare_inplace_alter_table_dict(
goto new_clustered_failed;
}
n_cols = altered_table->s->fields;
n_cols = altered_table->s->stored_fields;
if (add_fts_doc_id) {
n_cols++;
......@@ -2688,8 +2717,12 @@ prepare_inplace_alter_table_dict(
user_table->data_dir_path);
}
for (uint i = 0; i < altered_table->s->fields; i++) {
const Field* field = altered_table->field[i];
sql_idx= 0;
for (uint i = 0; i < altered_table->s->stored_fields; i++, sql_idx++) {
const Field* field;
while (!((field= altered_table->field[sql_idx])->
stored_in_db))
sql_idx++;
ulint is_unsigned;
ulint field_type
= (ulint) field->type();
......@@ -2766,7 +2799,7 @@ prepare_inplace_alter_table_dict(
if (add_fts_doc_id) {
fts_add_doc_id_column(indexed_table, heap);
indexed_table->fts->doc_col = fts_doc_id_col;
ut_ad(fts_doc_id_col == altered_table->s->fields);
ut_ad(fts_doc_id_col == altered_table->s->stored_fields);
} else if (indexed_table->fts) {
indexed_table->fts->doc_col = fts_doc_id_col;
}
......@@ -3674,7 +3707,7 @@ ha_innobase::prepare_inplace_alter_table(
if (!innobase_fts_check_doc_id_col(
prebuilt->table, altered_table, &fts_doc_col_no)) {
fts_doc_col_no = altered_table->s->fields;
fts_doc_col_no = altered_table->s->stored_fields;
add_fts_doc_id = true;
add_fts_doc_id_idx = true;
......@@ -3708,15 +3741,22 @@ ha_innobase::prepare_inplace_alter_table(
}
/* See if an AUTO_INCREMENT column was added. */
uint i = 0;
uint i = 0, innodb_idx= 0;
List_iterator_fast<Create_field> cf_it(
ha_alter_info->alter_info->create_list);
while (const Create_field* new_field = cf_it++) {
const Field* field;
if (!new_field->stored_in_db) {
i++;
continue;
}
DBUG_ASSERT(i < altered_table->s->fields);
DBUG_ASSERT(innodb_idx < altered_table->s->stored_fields);
for (uint old_i = 0; table->field[old_i]; old_i++) {
if (!table->field[old_i]->stored_in_db)
continue;
if (new_field->field == table->field[old_i]) {
goto found_col;
}
......@@ -3740,13 +3780,14 @@ ha_innobase::prepare_inplace_alter_table(
my_error(ER_WRONG_AUTO_KEY, MYF(0));
goto err_exit;
}
add_autoinc_col_no = i;
add_autoinc_col_no = innodb_idx;
autoinc_col_max_value = innobase_get_int_col_max_value(
field);
}
found_col:
i++;
innodb_idx++;
}
DBUG_ASSERT(user_thd == prebuilt->trx->mysql_thd);
......@@ -4369,7 +4410,7 @@ innobase_rename_columns(
uint i = 0;
for (Field** fp = table->field; *fp; fp++, i++) {
if (!((*fp)->flags & FIELD_IS_RENAMED)) {
if (!((*fp)->flags & FIELD_IS_RENAMED) || !((*fp)->stored_in_db)) {
continue;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment