WL#7899: InnoDB: Map compressed temporary tables to uncompressed

Affects: Server-8.0   —   Status: Complete   —   Priority: Medium

Remove InnoDB support for compressed temporary tables.

Temporary tables are supposed to be short-lived, ideally never written back to
files, unless the buffer pool space is tight. It does not seem to make sense to
try to reduce the file I/O by increasing the memory and CPU usage.

With this change, all temporary tables will be created in the shared temporary
tablespace "ibtmp1" introduced in WL#6560.

Two columns will be dropped from the INFORMATION_SCHEMA table introduced in
WL#6469, because they will be always FALSE:

INNODB_TEMP_TABLE_INFO.PER_TABLE_TABLESPACE
INNODB_TEMP_TABLE_INFO.IS_COMPRESSED

After a long discussion, we come to the agreement:
1) innodb_strict_mode would be default ON in 5.7
2) When innodb_strict_mode is ON, we should reject compressed temporary tables
by throwing an explicit error, telling customers to try other row formats,
if innodb_strict_mode is OFF, we should try to accept all current SQL statement
which is currently handled. So compressed related options would be ignored and
some warnings would be thrown.

Let's consider the following case, when innodb_strict_mode is OFF:

SET INNODB_FILE_PER_TABLE=ON;
CREATE TEMPORARY TABLE temp1 (...) KEY_BLOCK_SIZE=4 ROW_FORMAT=COMPRESSED;

would be interpreted as:

CREATE TEMPORARY TABLE temp1 (...) ROW_FORMAT=DYNAMIC;

since DYNAMIC row format is closer to COMPRESSED in that it supports better
support for large BLOBs.

WARNING log messages should be written that indicates what is being ignored and
what it is being changed to.

If innodb_strict_mode is ON, we don't do the silent conversion rather throw an
error ER_UNSUPPORT_COMPRESSED_TEMPORARY_TABLE:

CREATE TEMPORARY TABLE is not allowed with ROW_FORMAT=COMPRESSED or 
KEY_BLOCK_SIZE.
FR1: All temporary tables shall be stored in the same shared temporary tablespace
"ibtmp1". We could verify it by looking up the space field of
information_schema.innodb_temp_table_info. So innodb_file_per_table would be
ignored when creating or altering a temporary table.

FR2: Two columns PER_TABLE_TABLESPACE and IS_COMPRESSED of
information_schema.innodb_temp_table_info would be removed away.

FR3: When we try to create a compressed temporary table, there would be 2 cases:
1. innodb_strict_mode=ON, an error would be thrown to tell customers to try
other row formats.
2. innodb_strict_mode=OFF, we would try to throw warnings in these rules:
a) if key_block_size is specified, a warning would show key_block_size is
ignored for TEMPORARY TABLE.
b) if row_format=compressed is specified, 2 warnings would show
ROW_FORMAT=COMPRESSED is ignored for TEMPORARY and row_format would be converted
to DYNAMIC.
c) if both these 2 are specified, we would throw all the 3 warnings

Other than this, temporary tables in non-compressed format should act as is.
Warnings for other row formats should be also kept as is.

FR4: If we set create_intrinsic to true, we should always create the intrinsic
temporary table since all temporary tables are in the same tablespace.
(FR4: This point may not be considered by QA as this parameter was no longer exist 
in 5.8,this parameter was introduced in 5.7.5 & removed in 5.7.6 )
- All temporary tables shall reside in the same shared temporary tablespace,
  named ibtmp1 or specified by innodb_temp_data_file_path. There is no need to
  remember the dir path of a temp table in dict_table_t. We don't change the
  default value of innodb_temp_data_file_path here.

- Since we don't support compressed temporary tables, the variable
  innodb_file_per_table would not affect the table creation or alteration
  any more. For temporary tables, we won't check this variable any more.

- Please note that after WL#6560, we wouldn't do checking for
  innodb_file_per_table if row_format=DYNAMIC for a temporary table silencely,
  which makes changing row_format to DYNAMIC is possible for temporary table.
  We still skip this checking in this WL.

- When creating compressed temporary tables with innodb_strict_mode=ON, we
  should throw an explicit error like:
  'TEMPORARY TABLE cannot be created with ROW_FORMAT=Compressed and(or)
  KEY_BLOCK_SIZE=N.'(Here N would be the number specified.)
  and do nothing.

  But if innodb_strict_mode=OFF, we would throw warnings and convert silently.
  When checking for key_block_size and row_format=COMPRESSED, which are used for
  compressed table, we have following policies:
  1. If only key_block_size is specified for temporary table, a warning would
     indicate key_block_size would be ignored in this case. And the row_format
     would be changed to COMPACT if it's not specified, otherwise the requested
     row_format would be kept as is.
  2. If only row_format=COMPRESSED is specified for temporary table, 2 warnings
     would show that COMPRESSED format would be ignored for TEMPORARY TABLE and
     the row_format would be changed to DYNAMIC automatically.
  3. If 1 & 2 are both specified, all these warnings would be got, row_format
     would be changed to DYNAMIC.
  4. Other cases keep the same rules as is.

  Both 'CREATE TABLE' and 'ALTER TABLE' would generate these warnings and make
  these conversions of row_format.

  The newly introduced warnigs are:
  +---------+------+---------------------------------------------------------+
  |  Level  | Code |                     Message                             |
  +---------+------+---------------------------------------------------------+
  | Warning | 1478 | InnoDB: KEY_BLOCK_SIZE is ignored for TEMPORARY TABLE   |
  +---------+------+---------------------------------------------------------+
  | Warning | 1478 | InnoDB: ROW_FORMAT=COMPRESSED is ignored for TEMPORARY  |
  |         |      | TABLE.                                                  |
  +---------+------+---------------------------------------------------------+
  | Warning | 1478 | InnoDB: assuming ROW_FORMAT=DYNAMIC.                    |
  +---------+------+---------------------------------------------------------+

- We now handle a mismatch by renaming when the space read from the ibd file
  is different from the space in system tables. After we disable compressed
  temporary table, all temporary tables won't go to system tables any more.
  So it's impossible to find a temporary table space in system tables, Let alone
  the mismatch.

- Regarding to PER_TABLE_TABLESPACE and IS_COMPRESSED of
  information_schema.innodb_temp_table_info, we just simply remove them away,
  since they would be always false now.

Disable innodb_file_per_table for temporary table
-------------------------------------------------

We will turn innodb_file_per_table off silencely for temporary tables,
which happens in ha_innodb::create(). So we could remove

innobase_table_is_noncompressed_temporary away, since it should always
return TRUE and becomes unnecessary now.


Checking for key_block_size and row_format
------------------------------------------

In innobase_table_flags, warnings would be printed if we find key_block_size
or row_format is specified for temporary tables. And specified COMPRESSED
temporary tables would be changed to DYNAMIC automatically.

In create_options_are_invalid, we should check kbs and row_format for
temporary table, and throw an error if any of them are on. For non-temporary
tables, they are checked as is.


I_S.innodb_temp_table_info
--------------------------

We will remove the PER_TABLE_TABLESPACE and IS_COMPRESSED fields, so in
i_s_innodb_temp_table_info_fields_info, these 2 structs would be removed:

#define IDX_TEMP_TABLE_PTT              4
        {STRUCT_FLD(field_name,         "PER_TABLE_TABLESPACE"),
        ...},

#define IDX_TEMP_TABLE_IS_COMPRESSED    5
        {STRUCT_FLD(field_name,         "IS_COMPRESSED"),
        ...},

The last 2 variables in temp_table_info_t, which are m_per_table_tablespace
and m_is_compressed would be removed away.

We also won't populate and fill these 2 fields in following functions:
1. i_s_innodb_temp_table_info_fill
2. innodb_temp_table_populate_cache


Error we introduce
------------------
We need to introduce a new error for compressed temporary tables with
innodb_strict_mode ON, like:

+ER_UNSUPPORT_COMPRESSED_TEMPORARY_TABLE
+  eng "TEMPORARY TABLE can't be created with ROW_FORMAT=Compressed and(or)
KEY_BLOCK_SIZE."


Others
------

In btr_cur_optimistic_insert(),
btr_cur_update_in_place(),
btr_cur_optimistic_update(),
btr_cur_pessimistic_update(),
page_create_empty(),
page_zip_reorganize(),
page_zip_copy_recs()
row_drop_table_for_mysql()
row_truncate_table_for_mysql()
there are some invalid judgements for compressed temporary tables, which should
be removed and replaced by ut_ad(!temporary_table).

Some error message should be changed accordingly in
fil_report_missing_tablespace().

We don't load temporary tables from system tables, so in dict_load_table_one(),
we don't need to mark a temporary table as file missing.

Remove dir_path_of_temp_table in dict_table_t, since temporary tables would
only reside in the shared tablespace spcified by innodb_temp_data_file_path.
So any references to table->dir_path_of_temp_table could be cleaned up
Also we could do following clean-ups:
Remove the parameter 'dir_path' of fil_create_new_single_table_tablespace().
Remove the parameter 'temp_path' of create_table_def().
Remove the parameter 'temp_path' of ha_innobase::parse_table_name().

Remove the parameter 'adjust_space' of fil_space_for_table_exists_in_mem(),
since it's impossible to find the mismatch space between a user table and
its temporary table.

Introduce a function for assertion only:
+/** Check if a table is a temporary table with compressed row format,
+we should always expect false.
+@param[in]     table   table
+@return true if it's a compressed temporary table, false otherwise */
+inline
+bool
+dict_table_is_compressed_temporary(
+       const dict_table_t*     table)
+{
+       return(dict_table_is_temporary(table)
+              && dict_table_page_size(table).is_compressed()
+              && fsp_is_system_temporary(table->space));
+}

assert a intrinsic table must be a temporary table in dict_table_is_intrinsic().