Commit 0d8d39c8 authored by unknown's avatar unknown

Merge bk-internal.mysql.com:/home/bk/mysql-5.1

into serg.mylan:/usr/home/serg/Abk/m51


sql/log.cc:
  Auto merged
parents a245f597 1e56f376
...@@ -4944,10 +4944,10 @@ val ...@@ -4944,10 +4944,10 @@ val
UPDATE bug13894 SET val=6 WHERE val=10; UPDATE bug13894 SET val=6 WHERE val=10;
SELECT * FROM bug13894; SELECT * FROM bug13894;
val val
5
11
6 6
6 6
5
11
DROP TABLE bug13894; DROP TABLE bug13894;
DROP TABLE IF EXISTS bug14672; DROP TABLE IF EXISTS bug14672;
CREATE TABLE bug14672 (c1 integer) engine = CSV; CREATE TABLE bug14672 (c1 integer) engine = CSV;
......
...@@ -453,7 +453,7 @@ static void ndbcluster_binlog_wait(THD *thd) ...@@ -453,7 +453,7 @@ static void ndbcluster_binlog_wait(THD *thd)
} }
/* /*
Called from MYSQL_LOG::reset_logs in log.cc when binlog is emptied Called from MYSQL_BIN_LOG::reset_logs in log.cc when binlog is emptied
*/ */
static int ndbcluster_reset_logs(THD *thd) static int ndbcluster_reset_logs(THD *thd)
{ {
...@@ -477,7 +477,7 @@ static int ndbcluster_reset_logs(THD *thd) ...@@ -477,7 +477,7 @@ static int ndbcluster_reset_logs(THD *thd)
} }
/* /*
Called from MYSQL_LOG::purge_logs in log.cc when the binlog "file" Called from MYSQL_BIN_LOG::purge_logs in log.cc when the binlog "file"
is removed is removed
*/ */
......
This diff is collapsed.
...@@ -147,33 +147,85 @@ typedef struct st_log_info ...@@ -147,33 +147,85 @@ typedef struct st_log_info
class Log_event; class Log_event;
class Rows_log_event; class Rows_log_event;
enum enum_log_type { LOG_CLOSED, LOG_TO_BE_OPENED, LOG_NORMAL, LOG_NEW, LOG_BIN}; enum enum_log_type { LOG_UNKNOWN, LOG_NORMAL, LOG_BIN };
enum enum_log_state { LOG_OPENED, LOG_CLOSED, LOG_TO_BE_OPENED };
/* /*
TODO split MYSQL_LOG into base MYSQL_LOG and
MYSQL_QUERY_LOG, MYSQL_SLOW_LOG, MYSQL_BIN_LOG
most of the code from MYSQL_LOG should be in the MYSQL_BIN_LOG
only (TC_LOG included)
TODO use mmap instead of IO_CACHE for binlog TODO use mmap instead of IO_CACHE for binlog
(mmap+fsync is two times faster than write+fsync) (mmap+fsync is two times faster than write+fsync)
*/ */
class MYSQL_LOG: public TC_LOG class MYSQL_LOG
{
public:
MYSQL_LOG();
void init_pthread_objects();
void cleanup();
bool open(const char *log_name,
enum_log_type log_type,
const char *new_name,
enum cache_type io_cache_type_arg);
void init(enum_log_type log_type_arg,
enum cache_type io_cache_type_arg);
void close(uint exiting);
inline bool is_open() { return log_state != LOG_CLOSED; }
const char *generate_name(const char *log_name, const char *suffix,
bool strip_ext, char *buff);
int generate_new_name(char *new_name, const char *log_name);
protected:
/* LOCK_log is inited by init_pthread_objects() */
pthread_mutex_t LOCK_log;
char *name;
char log_file_name[FN_REFLEN];
char time_buff[20], db[NAME_LEN + 1];
bool write_error, inited;
IO_CACHE log_file;
enum_log_type log_type;
volatile enum_log_state log_state;
enum cache_type io_cache_type;
friend class Log_event;
};
class MYSQL_QUERY_LOG: public MYSQL_LOG
{
public:
MYSQL_QUERY_LOG() : last_time(0) {}
void reopen_file();
bool write(time_t event_time, const char *user_host,
uint user_host_len, int thread_id,
const char *command_type, uint command_type_len,
const char *sql_text, uint sql_text_len);
bool write(THD *thd, time_t current_time, time_t query_start_arg,
const char *user_host, uint user_host_len,
longlong query_time, longlong lock_time, bool is_command,
const char *sql_text, uint sql_text_len);
bool open_slow_log(const char *log_name)
{
char buf[FN_REFLEN];
return open(generate_name(log_name, "-slow.log", 0, buf), LOG_NORMAL, 0,
WRITE_CACHE);
}
bool open_query_log(const char *log_name)
{
char buf[FN_REFLEN];
return open(generate_name(log_name, ".log", 0, buf), LOG_NORMAL, 0,
WRITE_CACHE);
}
private:
time_t last_time;
};
class MYSQL_BIN_LOG: public TC_LOG, private MYSQL_LOG
{ {
private: private:
/* LOCK_log and LOCK_index are inited by init_pthread_objects() */ /* LOCK_log and LOCK_index are inited by init_pthread_objects() */
pthread_mutex_t LOCK_log, LOCK_index; pthread_mutex_t LOCK_index;
pthread_mutex_t LOCK_prep_xids; pthread_mutex_t LOCK_prep_xids;
pthread_cond_t COND_prep_xids; pthread_cond_t COND_prep_xids;
pthread_cond_t update_cond; pthread_cond_t update_cond;
ulonglong bytes_written; ulonglong bytes_written;
time_t last_time,query_start;
IO_CACHE log_file;
IO_CACHE index_file; IO_CACHE index_file;
char *name; char index_file_name[FN_REFLEN];
char time_buff[20],db[NAME_LEN+1];
char log_file_name[FN_REFLEN],index_file_name[FN_REFLEN];
/* /*
The max size before rotation (usable only if log_type == LOG_BIN: binary The max size before rotation (usable only if log_type == LOG_BIN: binary
logs and relay logs). logs and relay logs).
...@@ -186,13 +238,10 @@ class MYSQL_LOG: public TC_LOG ...@@ -186,13 +238,10 @@ class MYSQL_LOG: public TC_LOG
*/ */
ulong max_size; ulong max_size;
ulong prepared_xids; /* for tc log - number of xids to remember */ ulong prepared_xids; /* for tc log - number of xids to remember */
volatile enum_log_type log_type;
enum cache_type io_cache_type;
// current file sequence number for load data infile binary logging // current file sequence number for load data infile binary logging
uint file_id; uint file_id;
uint open_count; // For replication uint open_count; // For replication
int readers_count; int readers_count;
bool write_error, inited;
bool need_start_event; bool need_start_event;
/* /*
no_auto_events means we don't want any of these automatic events : no_auto_events means we don't want any of these automatic events :
...@@ -202,13 +251,21 @@ class MYSQL_LOG: public TC_LOG ...@@ -202,13 +251,21 @@ class MYSQL_LOG: public TC_LOG
In 5.0 it's 0 for relay logs too! In 5.0 it's 0 for relay logs too!
*/ */
bool no_auto_events; bool no_auto_events;
friend class Log_event;
ulonglong m_table_map_version; ulonglong m_table_map_version;
int write_to_file(IO_CACHE *cache); int write_to_file(IO_CACHE *cache);
/*
This is used to start writing to a new log file. The difference from
new_file() is locking. new_file_without_locking() does not acquire
LOCK_log.
*/
void new_file_without_locking();
void new_file_impl(bool need_lock);
public: public:
MYSQL_LOG::generate_name;
MYSQL_LOG::is_open;
/* /*
These describe the log's format. This is used only for relay logs. These describe the log's format. This is used only for relay logs.
_for_exec is used by the SQL thread, _for_queue by the I/O thread. It's _for_exec is used by the SQL thread, _for_queue by the I/O thread. It's
...@@ -220,9 +277,9 @@ class MYSQL_LOG: public TC_LOG ...@@ -220,9 +277,9 @@ class MYSQL_LOG: public TC_LOG
Format_description_log_event *description_event_for_exec, Format_description_log_event *description_event_for_exec,
*description_event_for_queue; *description_event_for_queue;
MYSQL_LOG(); MYSQL_BIN_LOG();
/* /*
note that there's no destructor ~MYSQL_LOG() ! note that there's no destructor ~MYSQL_BIN_LOG() !
The reason is that we don't want it to be automatically called The reason is that we don't want it to be automatically called
on exit() - but only during the correct shutdown process on exit() - but only during the correct shutdown process
*/ */
...@@ -264,9 +321,7 @@ class MYSQL_LOG: public TC_LOG ...@@ -264,9 +321,7 @@ class MYSQL_LOG: public TC_LOG
void signal_update(); void signal_update();
void wait_for_update(THD* thd, bool master_or_slave); void wait_for_update(THD* thd, bool master_or_slave);
void set_need_start_event() { need_start_event = 1; } void set_need_start_event() { need_start_event = 1; }
void init(enum_log_type log_type_arg, void init(bool no_auto_events_arg, ulong max_size);
enum cache_type io_cache_type_arg,
bool no_auto_events_arg, ulong max_size);
void init_pthread_objects(); void init_pthread_objects();
void cleanup(); void cleanup();
bool open(const char *log_name, bool open(const char *log_name,
...@@ -275,35 +330,10 @@ class MYSQL_LOG: public TC_LOG ...@@ -275,35 +330,10 @@ class MYSQL_LOG: public TC_LOG
enum cache_type io_cache_type_arg, enum cache_type io_cache_type_arg,
bool no_auto_events_arg, ulong max_size, bool no_auto_events_arg, ulong max_size,
bool null_created); bool null_created);
const char *generate_name(const char *log_name, const char *suffix,
bool strip_ext, char *buff);
/* simplified open_xxx wrappers for the gigantic open above */
bool open_query_log(const char *log_name)
{
char buf[FN_REFLEN];
return open(generate_name(log_name, ".log", 0, buf),
LOG_NORMAL, 0, WRITE_CACHE, 0, 0, 0);
}
bool open_slow_log(const char *log_name)
{
char buf[FN_REFLEN];
return open(generate_name(log_name, "-slow.log", 0, buf),
LOG_NORMAL, 0, WRITE_CACHE, 0, 0, 0);
}
bool open_index_file(const char *index_file_name_arg, bool open_index_file(const char *index_file_name_arg,
const char *log_name); const char *log_name);
void new_file(bool need_lock); /* Use this to start writing a new log file */
/* log a command to the old-fashioned general log */ void new_file();
bool write(time_t event_time, const char *user_host,
uint user_host_len, int thread_id,
const char *command_type, uint command_type_len,
const char *sql_text, uint sql_text_len);
/* log a query to the old-fashioned slow query log */
bool write(THD *thd, time_t current_time, time_t query_start_arg,
const char *user_host, uint user_host_len,
longlong query_time, longlong lock_time, bool is_command,
const char *sql_text, uint sql_text_len);
bool write(Log_event* event_info); // binary log write bool write(Log_event* event_info); // binary log write
bool write(THD *thd, IO_CACHE *cache, Log_event *commit_event); bool write(THD *thd, IO_CACHE *cache, Log_event *commit_event);
...@@ -319,7 +349,6 @@ class MYSQL_LOG: public TC_LOG ...@@ -319,7 +349,6 @@ class MYSQL_LOG: public TC_LOG
bool appendv(const char* buf,uint len,...); bool appendv(const char* buf,uint len,...);
bool append(Log_event* ev); bool append(Log_event* ev);
int generate_new_name(char *new_name,const char *old_name);
void make_log_name(char* buf, const char* log_ident); void make_log_name(char* buf, const char* log_ident);
bool is_active(const char* log_file_name); bool is_active(const char* log_file_name);
int update_log_index(LOG_INFO* linfo, bool need_update_threads); int update_log_index(LOG_INFO* linfo, bool need_update_threads);
...@@ -339,7 +368,6 @@ class MYSQL_LOG: public TC_LOG ...@@ -339,7 +368,6 @@ class MYSQL_LOG: public TC_LOG
int find_next_log(LOG_INFO* linfo, bool need_mutex); int find_next_log(LOG_INFO* linfo, bool need_mutex);
int get_current_log(LOG_INFO* linfo); int get_current_log(LOG_INFO* linfo);
uint next_file_id(); uint next_file_id();
inline bool is_open() { return log_type != LOG_CLOSED; }
inline char* get_index_fname() { return index_file_name;} inline char* get_index_fname() { return index_file_name;}
inline char* get_log_fname() { return log_file_name; } inline char* get_log_fname() { return log_file_name; }
inline char* get_name() { return name; } inline char* get_name() { return name; }
...@@ -416,7 +444,8 @@ class Log_to_csv_event_handler: public Log_event_handler ...@@ -416,7 +444,8 @@ class Log_to_csv_event_handler: public Log_event_handler
class Log_to_file_event_handler: public Log_event_handler class Log_to_file_event_handler: public Log_event_handler
{ {
MYSQL_LOG mysql_log, mysql_slow_log; MYSQL_QUERY_LOG mysql_log;
MYSQL_QUERY_LOG mysql_slow_log;
bool is_initialized; bool is_initialized;
public: public:
Log_to_file_event_handler(): is_initialized(FALSE) Log_to_file_event_handler(): is_initialized(FALSE)
......
...@@ -470,7 +470,7 @@ enum Int_event_type ...@@ -470,7 +470,7 @@ enum Int_event_type
#ifndef MYSQL_CLIENT #ifndef MYSQL_CLIENT
class String; class String;
class MYSQL_LOG; class MYSQL_BIN_LOG;
class THD; class THD;
#endif #endif
......
...@@ -1537,7 +1537,7 @@ extern char *default_tz_name; ...@@ -1537,7 +1537,7 @@ extern char *default_tz_name;
extern my_bool opt_large_pages; extern my_bool opt_large_pages;
extern uint opt_large_page_size; extern uint opt_large_page_size;
extern MYSQL_LOG mysql_bin_log; extern MYSQL_BIN_LOG mysql_bin_log;
extern LOGGER logger; extern LOGGER logger;
extern TABLE_LIST general_log, slow_log; extern TABLE_LIST general_log, slow_log;
extern FILE *bootstrap_file; extern FILE *bootstrap_file;
......
...@@ -2635,10 +2635,10 @@ static int init_common_variables(const char *conf_file_name, int argc, ...@@ -2635,10 +2635,10 @@ static int init_common_variables(const char *conf_file_name, int argc,
global_system_variables.time_zone= my_tz_SYSTEM; global_system_variables.time_zone= my_tz_SYSTEM;
/* /*
Init mutexes for the global MYSQL_LOG objects. Init mutexes for the global MYSQL_BIN_LOG objects.
As safe_mutex depends on what MY_INIT() does, we can't init the mutexes of As safe_mutex depends on what MY_INIT() does, we can't init the mutexes of
global MYSQL_LOGs in their constructors, because then they would be inited global MYSQL_BIN_LOGs in their constructors, because then they would be
before MY_INIT(). So we do it here. inited before MY_INIT(). So we do it here.
*/ */
mysql_bin_log.init_pthread_objects(); mysql_bin_log.init_pthread_objects();
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
/* inline since it's called below */ /* inline since it's called below */
inline inline
injector::transaction::transaction(MYSQL_LOG *log, THD *thd) injector::transaction::transaction(MYSQL_BIN_LOG *log, THD *thd)
: m_state(START_STATE), m_thd(thd) : m_state(START_STATE), m_thd(thd)
{ {
/* /*
......
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
/* Forward declarations */ /* Forward declarations */
class handler; class handler;
class MYSQL_LOG; class MYSQL_BIN_LOG;
class st_table; class st_table;
typedef st_table TABLE; typedef st_table TABLE;
...@@ -219,7 +219,7 @@ class injector ...@@ -219,7 +219,7 @@ class injector
private: private:
/* Only the injector may construct these object */ /* Only the injector may construct these object */
transaction(MYSQL_LOG *, THD *); transaction(MYSQL_BIN_LOG *, THD *);
void swap(transaction& o) { void swap(transaction& o) {
/* std::swap(m_start_pos, o.m_start_pos); */ /* std::swap(m_start_pos, o.m_start_pos); */
......
...@@ -69,7 +69,7 @@ typedef struct st_relay_log_info ...@@ -69,7 +69,7 @@ typedef struct st_relay_log_info
Protected with internal locks. Protected with internal locks.
Must get data_lock when resetting the logs. Must get data_lock when resetting the logs.
*/ */
MYSQL_LOG relay_log; MYSQL_BIN_LOG relay_log;
LOG_INFO linfo; LOG_INFO linfo;
IO_CACHE cache_buf,*cur_log; IO_CACHE cache_buf,*cur_log;
......
...@@ -4658,7 +4658,7 @@ static Log_event* next_event(RELAY_LOG_INFO* rli) ...@@ -4658,7 +4658,7 @@ static Log_event* next_event(RELAY_LOG_INFO* rli)
When the relay log is created when the I/O thread starts, easy: the When the relay log is created when the I/O thread starts, easy: the
master will send the description event and we will queue it. master will send the description event and we will queue it.
But if the relay log is created by new_file(): then the solution is: But if the relay log is created by new_file(): then the solution is:
MYSQL_LOG::open() will write the buffered description event. MYSQL_BIN_LOG::open() will write the buffered description event.
*/ */
if ((ev=Log_event::read_log_event(cur_log,0, if ((ev=Log_event::read_log_event(cur_log,0,
rli->relay_log.description_event_for_exec))) rli->relay_log.description_event_for_exec)))
...@@ -4920,7 +4920,8 @@ event(errno: %d cur_log->error: %d)", ...@@ -4920,7 +4920,8 @@ event(errno: %d cur_log->error: %d)",
Rotate a relay log (this is used only by FLUSH LOGS; the automatic rotation Rotate a relay log (this is used only by FLUSH LOGS; the automatic rotation
because of size is simpler because when we do it we already have all relevant because of size is simpler because when we do it we already have all relevant
locks; here we don't, so this function is mainly taking locks). locks; here we don't, so this function is mainly taking locks).
Returns nothing as we cannot catch any error (MYSQL_LOG::new_file() is void). Returns nothing as we cannot catch any error (MYSQL_BIN_LOG::new_file()
is void).
*/ */
void rotate_relay_log(MASTER_INFO* mi) void rotate_relay_log(MASTER_INFO* mi)
...@@ -4942,7 +4943,7 @@ void rotate_relay_log(MASTER_INFO* mi) ...@@ -4942,7 +4943,7 @@ void rotate_relay_log(MASTER_INFO* mi)
} }
/* If the relay log is closed, new_file() will do nothing. */ /* If the relay log is closed, new_file() will do nothing. */
rli->relay_log.new_file(1); rli->relay_log.new_file();
/* /*
We harvest now, because otherwise BIN_LOG_HEADER_SIZE will not immediately We harvest now, because otherwise BIN_LOG_HEADER_SIZE will not immediately
......
...@@ -73,7 +73,7 @@ ...@@ -73,7 +73,7 @@
run_lock protects all information about the run state: slave_running, and the run_lock protects all information about the run state: slave_running, and the
existence of the I/O thread (to stop/start it, you need this mutex). existence of the I/O thread (to stop/start it, you need this mutex).
data_lock protects some moving members of the struct: counters (log name, data_lock protects some moving members of the struct: counters (log name,
position) and relay log (MYSQL_LOG object). position) and relay log (MYSQL_BIN_LOG object).
In RELAY_LOG_INFO: run_lock, data_lock In RELAY_LOG_INFO: run_lock, data_lock
see MASTER_INFO see MASTER_INFO
...@@ -81,7 +81,7 @@ ...@@ -81,7 +81,7 @@
Order of acquisition: if you want to have LOCK_active_mi and a run_lock, you Order of acquisition: if you want to have LOCK_active_mi and a run_lock, you
must acquire LOCK_active_mi first. must acquire LOCK_active_mi first.
In MYSQL_LOG: LOCK_log, LOCK_index of the binlog and the relay log In MYSQL_BIN_LOG: LOCK_log, LOCK_index of the binlog and the relay log
LOCK_log: when you write to it. LOCK_index: when you create/delete a binlog LOCK_log: when you write to it. LOCK_index: when you create/delete a binlog
(so that you have to update the .index file). (so that you have to update the .index file).
*/ */
......
This diff is collapsed.
...@@ -29,15 +29,12 @@ ...@@ -29,15 +29,12 @@
typedef struct st_tina_share { typedef struct st_tina_share {
char *table_name; char *table_name;
char data_file_name[FN_REFLEN]; char data_file_name[FN_REFLEN];
byte *mapped_file; /* mapped region of file */
uint table_name_length, use_count; uint table_name_length, use_count;
/* /*
Below flag is needed to make log tables work with concurrent insert. Below flag is needed to make log tables work with concurrent insert.
For more details see comment to ha_tina::update_status. For more details see comment to ha_tina::update_status.
*/ */
my_bool is_log_table; my_bool is_log_table;
MY_STAT file_stat; /* Stat information for the data file */
File data_file; /* Current open data file */
/* /*
Here we save the length of the file for readers. This is updated by 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 inserts, updates and deletes. The var is initialized along with the
...@@ -46,7 +43,10 @@ typedef struct st_tina_share { ...@@ -46,7 +43,10 @@ typedef struct st_tina_share {
off_t saved_data_file_length; off_t saved_data_file_length;
pthread_mutex_t mutex; pthread_mutex_t mutex;
THR_LOCK lock; THR_LOCK lock;
bool update_file_opened;
bool tina_write_opened;
File meta_file; /* Meta file we use */ File meta_file; /* Meta file we use */
File tina_write_filedes; /* File handler for readers */
bool crashed; /* Meta file is crashed */ bool crashed; /* Meta file is crashed */
ha_rows rows_recorded; /* Number of rows in tables */ ha_rows rows_recorded; /* Number of rows in tables */
} TINA_SHARE; } TINA_SHARE;
...@@ -56,6 +56,49 @@ struct tina_set { ...@@ -56,6 +56,49 @@ struct tina_set {
off_t end; off_t end;
}; };
class Transparent_file
{
File filedes;
byte *buff; /* in-memory window to the file or mmaped area */
/* current window sizes */
off_t lower_bound;
off_t upper_bound;
uint buff_size;
public:
Transparent_file() : lower_bound(0), buff_size(IO_SIZE)
{ buff= (byte *) my_malloc(buff_size*sizeof(byte), MYF(MY_WME)); }
~Transparent_file()
{ my_free((gptr)buff, MYF(MY_ALLOW_ZERO_PTR)); }
void init_buff(File filedes_arg)
{
filedes= filedes_arg;
/* read the beginning of the file */
lower_bound= 0;
VOID(my_seek(filedes, 0, MY_SEEK_SET, MYF(0)));
if (filedes && buff)
upper_bound= my_read(filedes, buff, buff_size, MYF(0));
}
byte *ptr()
{ return buff; }
off_t start()
{ return lower_bound; }
off_t end()
{ return upper_bound; }
/* get a char from the given position in the file */
char get_value (off_t offset);
/* shift a buffer windows to see the next part of the file */
off_t read_next();
};
class ha_tina: public handler class ha_tina: public handler
{ {
THR_LOCK_DATA lock; /* MySQL lock */ THR_LOCK_DATA lock; /* MySQL lock */
...@@ -64,6 +107,9 @@ class ha_tina: public handler ...@@ -64,6 +107,9 @@ class ha_tina: public handler
off_t next_position; /* Next position in the file scan */ off_t next_position; /* Next position in the file scan */
off_t local_saved_data_file_length; /* save position for reads */ off_t local_saved_data_file_length; /* save position for reads */
byte byte_buffer[IO_SIZE]; byte byte_buffer[IO_SIZE];
Transparent_file *file_buff;
File data_file; /* File handler for readers */
File update_temp_file;
String buffer; String buffer;
/* /*
The chain contains "holes" in the file, occured because of The chain contains "holes" in the file, occured because of
...@@ -77,12 +123,19 @@ class ha_tina: public handler ...@@ -77,12 +123,19 @@ class ha_tina: public handler
uint32 chain_size; uint32 chain_size;
bool records_is_known; 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: public:
ha_tina(TABLE_SHARE *table_arg); ha_tina(TABLE_SHARE *table_arg);
~ha_tina() ~ha_tina()
{ {
if (chain_alloced) if (chain_alloced)
my_free((gptr)chain,0); my_free((gptr)chain, 0);
if (file_buff)
delete file_buff;
} }
const char *table_type() const { return "CSV"; } const char *table_type() const { return "CSV"; }
const char *index_type(uint inx) { return "NONE"; } const char *index_type(uint inx) { return "NONE"; }
......
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