mirror of
https://github.com/MariaDB/server.git
synced 2025-01-19 13:32:33 +01:00
0ea47f3ed4
The problem was that some facilities (like CONVERT_TZ() function or server HELP statement) may require implicit access to some tables in 'mysql' database. This access was done by ordinary means of adding such tables to the list of tables the query is going to open. However, if we issued LOCK TABLES before that, we would get "table was not locked" error trying to open such implicit tables. The solution is to treat certain tables as MySQL system tables, like we already do for mysql.proc. Such tables may be opened for reading at any moment regardless of any locks in effect. The cost of this is that system table may be locked for writing only together with other system tables, it is disallowed to lock system tables for writing and have any other lock on any other table. After this patch the following tables are treated as MySQL system tables: mysql.help_category mysql.help_keyword mysql.help_relation mysql.help_topic mysql.proc (it already was) mysql.time_zone mysql.time_zone_leap_second mysql.time_zone_name mysql.time_zone_transition mysql.time_zone_transition_type These tables are now opened with open_system_tables_for_read() and closed with close_system_tables(), or one table may be opened with open_system_table_for_update() and closed with close_thread_tables() (the latter is used for mysql.proc table, which is updated as part of normal MySQL server operation). These functions may be used when some tables were opened and locked already. NOTE: online update of time zone tables is not possible during replication, because there's no time zone cache flush neither on LOCK TABLES, nor on FLUSH TABLES, so the master may serve stale time zone data from cache, while on slave updated data will be loaded from the time zone tables. mysql-test/r/help.result: Update result. mysql-test/r/lock.result: Update result. mysql-test/r/sp-error.result: Update result. mysql-test/r/timezone2.result: Add result for bug#9953: CONVERT_TZ requires mysql.time_zone_name to be locked. mysql-test/r/view.result: Update result: use table t3 rather than utilize MySQL system table. mysql-test/t/help.test: Test that we can use HELP even under LOCK TABLES. mysql-test/t/lock.test: Test LOCK TABLE on system tables. mysql-test/t/timezone2.test: Add test case for bug#9953: CONVERT_TZ requires mysql.time_zone_name to be locked. mysql-test/t/view.test: Update test: use table t3 rather that utilize MySQL system table. sql/handler.h: Fix comment for 'count' parameter of check_if_locking_is_allowed(). Add 'current' and 'system_count' parameters. sql/item_create.cc: We no longer have LEX::add_time_zone_tables_to_query_tables(). sql/item_timefunc.cc: We no longer have LEX::time_zone_tables_used, so Item_func_convert_tz::fix_fields() became the same as base Item_date_func::fix_fields(). my_tz_find() no longer takes table list, but takes THD pointer now. sql/item_timefunc.h: Remove dead field and method. sql/lock.cc: Pass values for 'current' and 'system_count' to check_if_locking_is_allowed(). sql/log_event.cc: We no longer have my_tz_find_with_opening_tz_tables(), its functions is performed by my_tz_find(). sql/mysql_priv.h: Add functions to work with MySQL system tables. sql/set_var.cc: my_tz_find() no longer takes table list, but takes THD pointer now. sql/sp.cc: Remove close_proc_table(). Use close_system_tables() instead. Use open_system_tables_for_read() and open_system_table_for_update(). sql/sp.h: Remove close_proc_table() declaration. sql/sql_base.cc: Add implementation of open_system_tables_for_read(), close_system_tables(), open_system_table_for_update(). sql/sql_help.cc: Operate on MySQL system tables mysql.help_* with open_system_tables_for_read() and close_system_tables() to allow the usage of HELP statement under LOCK TABLES. sql/sql_lex.cc: Remove LEX::time_zone_tables_used and LEX::add_time_zone_tables_to_query_tables() which are no longer used. sql/sql_lex.h: Remove LEX::time_zone_tables_used and LEX::add_time_zone_tables_to_query_tables() which are no longer used. sql/sql_parse.cc: Remove references to LEX::time_zone_tables_used and my_tz_check_n_skip_implicit_tables() which are no longer used. sql/sql_show.cc: Use close_system_tables() instead of removed close_proc_table(). sql/sql_view.cc: LEX::time_zone_tables_used is no longer there. sql/sql_yacc.yy: LEX::add_time_zone_tables_to_query_tables() is no longer there. sql/table.cc: Add more tables that should be treated as MySQL system tables. sql/share/errmsg.txt: Change the error message, as now we allow write-locking of several system tables if not mixed with ordinary tables. sql/tztime.cc: Do not add time zone tables to the list of query tables in tz_init_table_list(). Remove fake_time_zone_tables_list and my_tz_get_tables_list(). In my_tz_init(), open mysql.time_zone_leap_second with simple_open_n_lock_tables(), but pass time zone name to my_tz_find(), which will open and close time zone tables as necessary. In tz_load_from_open_tables() do not call table->use_all_columns(), as this was already done in open_system_tables_for_read(). my_tz_find() takes THD pointer instead of table list, and calls open_system_tables_for_read() and close_system_tables() as necessary. Remove my_tz_find_with_opening_tz_tables(). sql/tztime.h: Remove declarations of my_tz_get_table_list(), my_tz_find_with_opening_tz_tables(), fake_time_zone_tables_list, definition of my_tz_check_n_skip_implicit_tables(). Update prototype for my_tz_find(). storage/csv/ha_tina.cc: Add new parameters to check_if_locking_is_allowed(). storage/csv/ha_tina.h: Add new parameters to check_if_locking_is_allowed(). storage/myisam/ha_myisam.cc: Add new parameters to check_if_locking_is_allowed(). In this function we count system tables. If there are system tables, but there are also non-system tables, we report an error. storage/myisam/ha_myisam.h: Add new parameters to check_if_locking_is_allowed().
172 lines
5.7 KiB
C++
172 lines
5.7 KiB
C++
/* Copyright (C) 2003 MySQL AB
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; version 2 of the License.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <my_dir.h>
|
|
#include "transparent_file.h"
|
|
|
|
#define DEFAULT_CHAIN_LENGTH 512
|
|
/*
|
|
Version for file format.
|
|
1 - Initial Version. That is, the version when the metafile was introduced.
|
|
*/
|
|
|
|
#define TINA_VERSION 1
|
|
|
|
typedef struct st_tina_share {
|
|
char *table_name;
|
|
char data_file_name[FN_REFLEN];
|
|
uint table_name_length, use_count;
|
|
/*
|
|
Below flag is needed to make log tables work with concurrent insert.
|
|
For more details see comment to ha_tina::update_status.
|
|
*/
|
|
my_bool is_log_table;
|
|
/*
|
|
Here we save the length of the file for readers. This is updated by
|
|
inserts, updates and deletes. The var is initialized along with the
|
|
share initialization.
|
|
*/
|
|
off_t saved_data_file_length;
|
|
pthread_mutex_t mutex;
|
|
THR_LOCK lock;
|
|
bool update_file_opened;
|
|
bool tina_write_opened;
|
|
File meta_file; /* Meta file we use */
|
|
File tina_write_filedes; /* File handler for readers */
|
|
bool crashed; /* Meta file is crashed */
|
|
ha_rows rows_recorded; /* Number of rows in tables */
|
|
} TINA_SHARE;
|
|
|
|
struct tina_set {
|
|
off_t begin;
|
|
off_t end;
|
|
};
|
|
|
|
class ha_tina: public handler
|
|
{
|
|
THR_LOCK_DATA lock; /* MySQL lock */
|
|
TINA_SHARE *share; /* Shared lock info */
|
|
off_t current_position; /* Current position in the file during a file scan */
|
|
off_t next_position; /* Next position in the file scan */
|
|
off_t local_saved_data_file_length; /* save position for reads */
|
|
byte byte_buffer[IO_SIZE];
|
|
Transparent_file *file_buff;
|
|
File data_file; /* File handler for readers */
|
|
File update_temp_file;
|
|
String buffer;
|
|
/*
|
|
The chain contains "holes" in the file, occured because of
|
|
deletes/updates. It is used in rnd_end() to get rid of them
|
|
in the end of the query.
|
|
*/
|
|
tina_set chain_buffer[DEFAULT_CHAIN_LENGTH];
|
|
tina_set *chain;
|
|
tina_set *chain_ptr;
|
|
byte chain_alloced;
|
|
uint32 chain_size;
|
|
bool records_is_known;
|
|
|
|
private:
|
|
bool get_write_pos(off_t *end_pos, tina_set *closest_hole);
|
|
int open_update_temp_file_if_needed();
|
|
int init_tina_writer();
|
|
|
|
public:
|
|
ha_tina(handlerton *hton, TABLE_SHARE *table_arg);
|
|
~ha_tina()
|
|
{
|
|
if (chain_alloced)
|
|
my_free((gptr)chain, 0);
|
|
if (file_buff)
|
|
delete file_buff;
|
|
}
|
|
const char *table_type() const { return "CSV"; }
|
|
const char *index_type(uint inx) { return "NONE"; }
|
|
const char **bas_ext() const;
|
|
ulonglong table_flags() const
|
|
{
|
|
return (HA_NO_TRANSACTIONS | HA_REC_NOT_IN_SEQ | HA_NO_AUTO_INCREMENT);
|
|
}
|
|
ulong index_flags(uint idx, uint part, bool all_parts) const
|
|
{
|
|
/*
|
|
We will never have indexes so this will never be called(AKA we return
|
|
zero)
|
|
*/
|
|
return 0;
|
|
}
|
|
uint max_record_length() const { return HA_MAX_REC_LENGTH; }
|
|
uint max_keys() const { return 0; }
|
|
uint max_key_parts() const { return 0; }
|
|
uint max_key_length() const { return 0; }
|
|
/*
|
|
Called in test_quick_select to determine if indexes should be used.
|
|
*/
|
|
virtual double scan_time() { return (double) (stats.records+stats.deleted) / 20.0+10; }
|
|
/* The next method will never be called */
|
|
virtual bool fast_key_read() { return 1;}
|
|
/*
|
|
TODO: return actual upper bound of number of records in the table.
|
|
(e.g. save number of records seen on full table scan and/or use file size
|
|
as upper bound)
|
|
*/
|
|
ha_rows estimate_rows_upper_bound() { return HA_POS_ERROR; }
|
|
|
|
virtual bool check_if_locking_is_allowed(uint sql_command,
|
|
ulong type, TABLE *table,
|
|
uint count, uint current,
|
|
uint *system_count,
|
|
bool called_by_logger_thread);
|
|
int open(const char *name, int mode, uint open_options);
|
|
int close(void);
|
|
int write_row(byte * buf);
|
|
int update_row(const byte * old_data, byte * new_data);
|
|
int delete_row(const byte * buf);
|
|
int rnd_init(bool scan=1);
|
|
int rnd_next(byte *buf);
|
|
int rnd_pos(byte * buf, byte *pos);
|
|
bool check_and_repair(THD *thd);
|
|
int check(THD* thd, HA_CHECK_OPT* check_opt);
|
|
bool is_crashed() const;
|
|
int rnd_end();
|
|
int repair(THD* thd, HA_CHECK_OPT* check_opt);
|
|
/* This is required for SQL layer to know that we support autorepair */
|
|
bool auto_repair() const { return 1; }
|
|
void position(const byte *record);
|
|
int info(uint);
|
|
int extra(enum ha_extra_function operation);
|
|
int delete_all_rows(void);
|
|
int create(const char *name, TABLE *form, HA_CREATE_INFO *create_info);
|
|
bool check_if_incompatible_data(HA_CREATE_INFO *info,
|
|
uint table_changes);
|
|
|
|
THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to,
|
|
enum thr_lock_type lock_type);
|
|
|
|
/*
|
|
These functions used to get/update status of the handler.
|
|
Needed to enable concurrent inserts.
|
|
*/
|
|
void get_status();
|
|
void update_status();
|
|
|
|
/* The following methods were added just for TINA */
|
|
int encode_quote(byte *buf);
|
|
int find_current_row(byte *buf);
|
|
int chain_append();
|
|
};
|
|
|