Commit f4ac3b78 authored by Marko Mäkelä's avatar Marko Mäkelä

Add member functions to dictionary objects

dict_col_t::is_nullable(): Determine if the column can be set NULL.

dict_col_t::is_nullable(): Determine if the column is virtual.

dict_col_t::is_instant(): Determine if the column has been instantly added.

dict_col_t::instant_value(): Get the default value of an instantly-added
column.

dict_index_t::get_n_nullable(n_prefix): Determine the number of nullable
index fields in the prefix.

dict_index_t::instant_field_value(): Get the default value of a
clustered index field of an instantly-added column.
parent 0f6ef542
......@@ -494,12 +494,8 @@ btr_cur_instant_root_init(dict_index_t* index, const page_t* page)
uint16_t n = page_get_instant(page);
ut_ad(index->n_core_fields == index->n_fields);
ut_ad(n <= index->n_fields);
ut_ad(n > 0);
index->n_core_fields = n;
uint16_t n_null_bytes = UT_BITS_IN_BYTES(
dict_index_get_first_n_field_n_nullable(index, n));
index->n_core_null_bytes = n_null_bytes;
index->n_core_null_bytes = UT_BITS_IN_BYTES(index->get_n_nullable(n));
}
/** Optimistically latches the leaf page or pages requested.
......
......@@ -341,7 +341,7 @@ struct ha_innobase_inplace_ctx : public inplace_alter_handler_ctx
i < instant_table->n_def - DATA_N_SYS_COLS;
i++) {
dict_col_t& col = old_table->cols[i];
ut_ad(col.def_val.len != UNIV_SQL_DEFAULT);
DBUG_ASSERT(col.is_instant());
if (col.def_val.len == 0) {
col.def_val.data = field_ref_zero;
} else if (const void*& def = col.def_val.data) {
......@@ -4208,8 +4208,7 @@ innobase_add_instant_try(
DBUG_ASSERT(!strcmp((*af)->field_name.str,
dict_table_get_col_name(new_table, i)));
DBUG_ASSERT(!col->def_val.data);
DBUG_ASSERT(col->def_val.len == UNIV_SQL_DEFAULT);
DBUG_ASSERT(!col->is_instant());
dfield_t* dfield = dtuple_get_nth_field(row, i);
if (new_field->field) {
......@@ -4217,30 +4216,41 @@ innobase_add_instant_try(
DBUG_ASSERT(col->prtype == old_col->prtype);
DBUG_ASSERT(col->mbminmaxlen == old_col->mbminmaxlen);
DBUG_ASSERT(col->len >= old_col->len);
DBUG_ASSERT(old_col->is_instant()
== (dict_col_get_clust_pos(
old_col, old_index)
>= old_index->n_core_fields));
col->def_val = old_col->def_val;
if (old_col->def_val.len == UNIV_SQL_DEFAULT) {
/* We may only have missing DEFAULT
value for 'core' columns. */
DBUG_ASSERT(dict_col_get_clust_pos(
old_col, old_index)
< old_index->n_core_fields);
if ((*af)->real_maybe_null()) {
/* Store NULL for nullable
'core' columns. */
dfield_set_null(dfield);
} else if ((*af)->type()
== MYSQL_TYPE_VARCHAR) {
/* Store the empty string for
pre-existing VARCHAR NOT NULL
columns. */
if (old_col->is_instant()) {
dfield_set_data(dfield, old_col->def_val.data,
old_col->def_val.len);
} else if ((*af)->real_maybe_null()) {
/* Store NULL for nullable 'core' columns. */
dfield_set_null(dfield);
} else {
switch ((*af)->type()) {
case MYSQL_TYPE_VARCHAR:
case MYSQL_TYPE_GEOMETRY:
case MYSQL_TYPE_TINY_BLOB:
case MYSQL_TYPE_MEDIUM_BLOB:
case MYSQL_TYPE_BLOB:
case MYSQL_TYPE_LONG_BLOB:
/* Store the empty string for 'core'
variable-length NOT NULL columns. */
dfield_set_data(dfield, "", 0);
} else {
break;
default:
/* For fixed-length NOT NULL
'core' columns, get a dummy
default value from SQL. Note
that we should preserve the
old values of these columns
when updating the 'default
row' record, to avoid
unnecessary updates. */
goto set_not_null_default_from_sql;
}
} else {
dfield_set_data(dfield, old_col->def_val.data,
old_col->def_val.len);
}
} else if ((*af)->is_real_null()) {
/* Store NULL for added DEFAULT NULL columns. */
......@@ -4263,11 +4273,6 @@ innobase_add_instant_try(
case MYSQL_TYPE_MEDIUM_BLOB:
case MYSQL_TYPE_BLOB:
case MYSQL_TYPE_LONG_BLOB:
if (new_field->field) {
/* Store the empty string for
pre-existing BLOB NOT NULL columns. */
dfield_set_data(dfield, "", 0);
}
dfield_set_data(dfield,
reinterpret_cast
<const Field_blob*>
......@@ -4288,12 +4293,12 @@ innobase_add_instant_try(
: NULL, true, (*af)->ptr, len,
dict_table_is_comp(user_table));
}
}
if (!new_field->field) {
col->def_val.data = dfield_get_data(dfield);
col->def_val.len = dfield_get_len(dfield);
}
if (!new_field->field) {
pars_info_t* info = pars_info_create();
pars_info_add_ull_literal(info, "id", user_table->id);
pars_info_add_int4_literal(info, "pos", i);
......
......@@ -193,7 +193,6 @@ dict_col_set_mbminmaxlen(
ulint mbmaxlen) /*!< in: minimum multi-byte
character size, in bytes */
MY_ATTRIBUTE((nonnull));
/*********************************************************************//**
Gets the column data type. */
UNIV_INLINE
......@@ -900,7 +899,6 @@ dict_v_col_t*
dict_table_get_nth_v_col(
const dict_table_t* table,
ulint pos);
/********************************************************************//**
Gets the given system column of a table.
@return pointer to column object */
......@@ -1174,15 +1172,6 @@ dict_index_get_n_fields(
representation of index (in
the dictionary cache) */
MY_ATTRIBUTE((nonnull, warn_unused_result));
/********************************************************************//**
@return nullable count of n_core_fields */
UNIV_INLINE
ulint
dict_index_get_first_n_field_n_nullable(
/*================*/
const dict_index_t* index, /*!< in: index */
ulint first_n_fields) /*!< in: Precede n fields */
MY_ATTRIBUTE((nonnull, warn_unused_result));
/********************************************************************//**
Gets the number of fields in the internal representation of an index
......@@ -1272,25 +1261,6 @@ dict_index_get_nth_col_no(
const dict_index_t* index, /*!< in: index */
ulint pos) /*!< in: position of the field */
MY_ATTRIBUTE((nonnull, warn_unused_result));
/** Get the default value of a clustered index field.
@param[in] index clustered index
@param[in] pos field position in the clustered index
@param[out] len length of the value (in bytes), or UNIV_SQL_NULL
@return default value
@retval NULL if the default value is SQL NULL */
inline
const byte*
dict_index_get_nth_field_def(const dict_index_t* index, uint pos, ulint* len)
{
ut_ad(dict_index_is_clust(index));
const dict_col_t* col = dict_index_get_nth_col(index, pos);
ut_ad(col->def_val.len != UNIV_SQL_DEFAULT);
*len = col->def_val.len;
return static_cast<const byte*>(col->def_val.data);
}
/********************************************************************//**
Looks for column n in an index.
@return position in internal representation of the index;
......@@ -2026,21 +1996,7 @@ dict_index_node_ptr_max_size(
/*=========================*/
const dict_index_t* index) /*!< in: index */
MY_ATTRIBUTE((warn_unused_result));
/** Check if a column is a virtual column
@param[in] col column
@return true if it is a virtual column, false otherwise */
UNIV_INLINE
bool
dict_col_is_virtual(
const dict_col_t* col);
/*********************************************************************//**
Gets the column is nullable.
@return TRUE if nullable */
UNIV_INLINE
ibool
dict_col_is_nullable(
const dict_col_t* col); /*!< in: column */
#define dict_col_is_virtual(col) (col)->is_virtual()
/** encode number of columns and number of virtual columns in one
4 bytes value. We could do this because the number of columns in
......
......@@ -72,7 +72,6 @@ dict_col_set_mbminmaxlen(
col->mbminmaxlen = DATA_MBMINMAXLEN(mbminlen, mbmaxlen);
}
/*********************************************************************//**
Gets the column data type. */
UNIV_INLINE
......@@ -90,28 +89,6 @@ dict_col_copy_type(
type->len = col->len;
type->mbminmaxlen = col->mbminmaxlen;
}
/** Check if a column is a virtual column
@param[in] col column
@return true if it is a virtual column, false otherwise */
UNIV_INLINE
bool
dict_col_is_virtual(
const dict_col_t* col)
{
return(col->prtype & DATA_VIRTUAL);
}
/*********************************************************************//**
Gets the column is nullable.
@return TRUE if nullable */
UNIV_INLINE
ibool
dict_col_is_nullable(
/*============*/
const dict_col_t* col) /*!< in: column */
{
return (col->prtype & DATA_NOT_NULL) == 0;
}
#ifdef UNIV_DEBUG
/*********************************************************************//**
......@@ -1255,32 +1232,6 @@ dict_index_get_lock(
return(&(index->lock));
}
/********************************************************************//**
@return nullable count of n_core_fields */
UNIV_INLINE
ulint
dict_index_get_first_n_field_n_nullable(
/*================*/
const dict_index_t* index, /*!< in: index */
ulint first_n_fields) /*!< in: Precede n fields */
{
ulint n_nullable = index->n_nullable;
const dict_field_t* ifield;
ulint i = 0;
ulint n_fields;
n_fields = dict_index_get_n_fields(index);
ut_a(first_n_fields <= n_fields);
for (i = first_n_fields ; i < n_fields; ++i) {
ifield = dict_index_get_nth_field(index, i);
if (dict_col_is_nullable(dict_field_get_col(ifield)))
n_nullable--;
}
return n_nullable;
}
/********************************************************************//**
Returns free space reserved for future updates of records. This is
relevant only in the case of many consecutive inserts, as updates
......
......@@ -244,18 +244,11 @@ created with old versions of InnoDB that only implemented
ROW_FORMAT=REDUNDANT. InnoDB engines do not check these flags
for unknown bits in order to protect backward incompatibility. */
/* @{ */
/* The higher two bytes of SYS_TABLES.MIX_LEN is used by
instant add columns */
#define DICT_TF2_MAX_BITS 16
/** Total number of bits in table->flags2. */
#define DICT_TF2_BITS 7
#define DICT_TF2_UNUSED_BIT_MASK (~0U << DICT_TF2_BITS)
#define DICT_TF2_BIT_MASK ~DICT_TF2_UNUSED_BIT_MASK
#if DICT_TF2_BITS > DICT_TF2_MAX_BITS
#error "DICT_TF2_BITS > DICT_TF2_MAX_BITS"
#endif
/** TEMPORARY; TRUE for tables from CREATE TEMPORARY TABLE. */
#define DICT_TF2_TEMPORARY 1U
......@@ -336,7 +329,7 @@ void
dict_mem_table_free(
/*================*/
dict_table_t* table); /*!< in: table */
/****************************************************************//**
/**********************************************************************//**
Adds a column definition to a table. */
void
dict_mem_table_add_col(
......@@ -631,6 +624,27 @@ struct dict_col_t{
/** Retrieve the column name.
@param[in] table table name */
const char* name(const dict_table_t& table) const;
/** @return whether this is a virtual column */
bool is_virtual() const { return prtype & DATA_VIRTUAL; }
/** @return whether NULL is an allowed value for this column */
bool is_nullable() const { return !(prtype & DATA_NOT_NULL); }
/** @return whether this is an instantly-added column */
bool is_instant() const
{
DBUG_ASSERT(def_val.len != UNIV_SQL_DEFAULT || !def_val.data);
return def_val.len != UNIV_SQL_DEFAULT;
}
/** Get the default value of an instantly-added column.
@param[out] len value length (in bytes), or UNIV_SQL_NULL
@return default value
@retval NULL if the default value is SQL NULL (len=UNIV_SQL_NULL) */
const byte* instant_value(ulint* len) const
{
DBUG_ASSERT(is_instant());
*len = def_val.len;
return static_cast<const byte*>(def_val.data);
}
};
/** Index information put in a list of virtual column structure. Index
......@@ -1014,6 +1028,37 @@ struct dict_index_t{
/** @return whether the index is the clustered index */
bool is_clust() const { return type & DICT_CLUSTERED; }
/** Determine how many fields of a given prefix can be set NULL.
@param[in] n_prefix number of fields in the prefix
@return number of fields 0..n_prefix-1 that can be set NULL */
unsigned get_n_nullable(ulint n_prefix) const
{
DBUG_ASSERT(is_instant());
DBUG_ASSERT(n_prefix > 0);
DBUG_ASSERT(n_prefix <= n_fields);
unsigned n = n_nullable;
for (; n_prefix < n_fields; n_prefix++) {
const dict_col_t* col = fields[n_prefix].col;
DBUG_ASSERT(col->is_instant());
n -= col->is_nullable();
}
DBUG_ASSERT(n < n_def);
return n;
}
/** Get the default value of an instantly-added clustered index field.
@param[in] n instantly added field position
@param[out] len value length (in bytes), or UNIV_SQL_NULL
@return default value
@retval NULL if the default value is SQL NULL (len=UNIV_SQL_NULL) */
const byte* instant_field_value(uint n, ulint* len) const
{
DBUG_ASSERT(is_instant());
DBUG_ASSERT(n >= n_core_fields);
DBUG_ASSERT(n < n_fields);
return fields[n].col->instant_value(len);
}
/** Check whether two indexes have the same metadata.
@param[in] old the other index
@param[in] add whether to ignore added fields in other
......
......@@ -427,7 +427,7 @@ Note: FIL_PAGE_TYPE_INSTANT maps to the same as FIL_PAGE_INDEX. */
/** @return whether the page type is B-tree or R-tree index */
inline bool fil_page_type_is_index(ulint page_type)
{
switch (page_type) {
switch (page_type) {
case FIL_PAGE_TYPE_INSTANT:
case FIL_PAGE_INDEX:
case FIL_PAGE_RTREE:
......
......@@ -601,21 +601,6 @@ rec_get_nth_field_offs(
#define rec_get_nth_field(rec, offsets, n, len) \
((rec) + rec_get_nth_field_offs(offsets, n, len))
/** Get the nth field from an index.
@param[in] rec index record
@param[in] index index
@param[in] offsets rec_get_offsets(rec, index)
@param[in] n field number
@param[out] len length of the field in bytes, or UNIV_SQL_NULL
@return a read-only copy of the index field */
const byte*
rec_get_nth_cfield(
const rec_t* rec,
const dict_index_t* index,
const ulint* offsets,
ulint n,
ulint* len);
/******************************************************//**
Determine if the offsets are for a record containing null BLOB pointers.
@return first field containing a null BLOB pointer, or NULL if none found */
......@@ -698,7 +683,7 @@ rec_offs_nth_flag(const ulint* offsets, ulint n, ulint flag)
}
/** Determine if a record field is missing
(should be replaced by dict_col_t::def_val).
(should be replaced by dict_index_t::instant_field_value()).
@param[in] offsets rec_get_offsets()
@param[in] n nth field
@return nonzero if default bit is set */
......@@ -710,7 +695,7 @@ rec_offs_nth_default(const ulint* offsets, ulint n)
}
/** Determine if a record field is SQL NULL
(should be replaced by dict_col_t::def_val).
(should be replaced by dict_index_t::instant_field_value()).
@param[in] offsets rec_get_offsets()
@param[in] n nth field
@return nonzero if SQL NULL set */
......@@ -757,7 +742,8 @@ rec_offs_any_extern(const ulint* offsets)
/** Determine if the offsets are for a record that is missing fields.
@param[in] offsets rec_get_offsets()
@return nonzero if any fields need to be replaced with dict_col_t::def_val. */
@return nonzero if any fields need to be replaced with
dict_index_t::instant_field_value() */
inline
ulint
rec_offs_any_default(const ulint* offsets)
......@@ -792,6 +778,29 @@ rec_is_default_row(const rec_t* rec, const dict_index_t* index)
return is;
}
/** Get the nth field from an index.
@param[in] rec index record
@param[in] index index
@param[in] offsets rec_get_offsets(rec, index)
@param[in] n field number
@param[out] len length of the field in bytes, or UNIV_SQL_NULL
@return a read-only copy of the index field */
inline
const byte*
rec_get_nth_cfield(
const rec_t* rec,
const dict_index_t* index,
const ulint* offsets,
ulint n,
ulint* len)
{
ut_ad(rec_offs_validate(rec, index, offsets));
if (!rec_offs_nth_default(offsets, n)) {
return rec_get_nth_field(rec, offsets, n, len);
}
return index->instant_field_value(n, len);
}
/******************************************************//**
Gets the physical size of a field.
@return length of field */
......
......@@ -633,8 +633,7 @@ mlog_parse_index(
if (n_core_fields) {
ind->n_core_fields = n_core_fields;
ind->n_core_null_bytes = UT_BITS_IN_BYTES(
dict_index_get_first_n_field_n_nullable(
ind, ind->n_core_fields));
ind->get_n_nullable(n_core_fields));
} else {
ind->n_core_null_bytes = UT_BITS_IN_BYTES(
ind->n_nullable);
......
......@@ -312,9 +312,7 @@ rec_init_offsets_comp_ordinary(
ut_ad(n_fields > index->n_core_fields);
ut_ad(extra_bytes == REC_N_NEW_EXTRA_BYTES);
nulls = rec - (1 + REC_N_NEW_EXTRA_BYTES) - len;
const ulint n_nullable
= dict_index_get_first_n_field_n_nullable(index,
n_fields);
const ulint n_nullable = index->get_n_nullable(n_fields);
const ulint n_null_bytes = UT_BITS_IN_BYTES(n_nullable);
ut_d(n_null = n_nullable);
ut_ad(n_null <= index->n_nullable);
......@@ -342,9 +340,7 @@ rec_init_offsets_comp_ordinary(
/* set default value flag */
if (i >= n_fields) {
ulint dlen;
ut_ad(index->is_instant());
if (!dict_index_get_nth_field_def(index, i, &dlen)) {
if (!index->instant_field_value(i, &dlen)) {
len = offs | REC_OFFS_SQL_NULL;
ut_ad(dlen == UNIV_SQL_NULL);
} else {
......@@ -959,30 +955,6 @@ rec_get_offsets_reverse(
| REC_OFFS_COMPACT | any_ext;
}
/** Get the nth field from an index.
@param[in] rec index record
@param[in] index index
@param[in] offsets rec_get_offsets(rec, index)
@param[in] n field number
@param[out] len length of the field in bytes, or UNIV_SQL_NULL
@return a read-only copy of the index field */
const byte*
rec_get_nth_cfield(
const rec_t* rec,
const dict_index_t* index,
const ulint* offsets,
ulint n,
ulint* len)
{
ut_ad(rec_offs_validate(rec, index, offsets));
if (!rec_offs_nth_default(offsets, n)) {
return rec_get_nth_field(rec, offsets, n, len);
}
return dict_index_get_nth_field_def(index, n, len);
}
/************************************************************//**
The following function is used to get the offset to the nth
data field in an old-style record.
......@@ -1958,10 +1930,8 @@ rec_copy_prefix_to_buf(
ulint n_fields_rec = rec_get_field_count(rec, &len);
ut_ad(len == rec_get_field_count_len(n_fields_rec));
ut_ad(n_fields_rec >= n_fields);
const ulint n_nullable
= dict_index_get_first_n_field_n_nullable(
index, n_fields_rec);
ut_ad(n_nullable <= index->n_nullable);
const ulint n_nullable = index->get_n_nullable(
n_fields_rec);
nulls = rec - (REC_N_NEW_EXTRA_BYTES + 1) - len;
lens = nulls - UT_BITS_IN_BYTES(n_nullable);
break;
......
......@@ -509,7 +509,7 @@ row_build_low(
const void* field = rec_get_nth_field(
copy, offsets, i, &len);
if (len == UNIV_SQL_DEFAULT) {
field = dict_index_get_nth_field_def(index, i, &len);
field = index->instant_field_value(i, &len);
if (field && type != ROW_COPY_POINTERS) {
ut_ad(univ_is_stored(len));
field = mem_heap_dup(heap, field, len);
......@@ -650,7 +650,7 @@ row_build_w_add_vcol(
}
/** Convert an index record to a data tuple.
@tparam def whether the dict_col_t::def_val needs to be accessed
@tparam def whether the index->instant_field_value() needs to be accessed
@param[in] rec index record
@param[in] index index
@param[in] offsets rec_get_offsets(rec, index)
......@@ -659,6 +659,7 @@ row_build_w_add_vcol(
@return index entry built; does not set info_bits, and the data fields
in the entry will point directly to rec */
template<bool def>
static inline
dtuple_t*
row_rec_to_index_entry_impl(
const rec_t* rec,
......
......@@ -3038,7 +3038,6 @@ row_sel_store_mysql_field_func(
rec, offsets,
dict_table_page_size(prebuilt->table),
field_no, &len, heap);
//field_no, &len, heap, NULL);
if (UNIV_UNLIKELY(!data)) {
/* The externally stored field was not written
......@@ -3074,8 +3073,7 @@ row_sel_store_mysql_field_func(
const dict_index_t* clust_index
= dict_table_get_first_index(prebuilt->table);
ut_ad(index == clust_index);
data = dict_index_get_nth_field_def(
clust_index, field_no, &len);
data = clust_index->instant_field_value(field_no,&len);
} else {
data = rec_get_nth_field(rec, offsets, field_no, &len);
}
......
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