Commit 6bd49441 authored by Sergei Golubchik's avatar Sergei Golubchik

CONNECT engine fixes after 10.0 merge.

Adaptation to new API, small simplifications and bug fixes
parent 337c1b3e
...@@ -176,7 +176,7 @@ static int dbfhead(PGLOBAL g, FILE *file, PSZ fn, DBFHEADER *buf) ...@@ -176,7 +176,7 @@ static int dbfhead(PGLOBAL g, FILE *file, PSZ fn, DBFHEADER *buf)
/* DBFColumns: constructs the result blocks containing the description */ /* DBFColumns: constructs the result blocks containing the description */
/* of all the columns of a DBF file that will be retrieved by #GetData. */ /* of all the columns of a DBF file that will be retrieved by #GetData. */
/****************************************************************************/ /****************************************************************************/
PQRYRES DBFColumns(PGLOBAL g, char *fn, BOOL info) PQRYRES DBFColumns(PGLOBAL g, const char *fn, BOOL info)
{ {
static int dbtype[] = {DB_CHAR, DB_SHORT, DB_CHAR, static int dbtype[] = {DB_CHAR, DB_SHORT, DB_CHAR,
DB_INT, DB_INT, DB_SHORT}; DB_INT, DB_INT, DB_SHORT};
......
...@@ -19,7 +19,7 @@ typedef class DBMFAM *PDBMFAM; ...@@ -19,7 +19,7 @@ typedef class DBMFAM *PDBMFAM;
/****************************************************************************/ /****************************************************************************/
/* Functions used externally. */ /* Functions used externally. */
/****************************************************************************/ /****************************************************************************/
PQRYRES DBFColumns(PGLOBAL g, char *fn, BOOL info); PQRYRES DBFColumns(PGLOBAL g, const char *fn, BOOL info);
/****************************************************************************/ /****************************************************************************/
/* This is the base class for dBASE file access methods. */ /* This is the base class for dBASE file access methods. */
......
...@@ -173,23 +173,18 @@ int xtrace= 0; ...@@ -173,23 +173,18 @@ int xtrace= 0;
ulong ha_connect::num= 0; ulong ha_connect::num= 0;
//int DTVAL::Shift= 0; //int DTVAL::Shift= 0;
static PCONNECT GetUser(THD *thd, PCONNECT xp);
static PGLOBAL GetPlug(THD *thd, PCONNECT lxp);
static handler *connect_create_handler(handlerton *hton, static handler *connect_create_handler(handlerton *hton,
TABLE_SHARE *table, TABLE_SHARE *table,
MEM_ROOT *mem_root); MEM_ROOT *mem_root);
handlerton *connect_hton; static int connect_assisted_discovery(handlerton *hton, THD* thd,
TABLE_SHARE *table_s,
/* Variables for connect share methods */ HA_CREATE_INFO *info);
/*
Hash used to track the number of open tables; variable for connect share
methods
*/
static HASH connect_open_tables;
/* The mutex used to init the hash; variable for example share methods */
mysql_mutex_t connect_mutex;
handlerton *connect_hton;
/** /**
structure for CREATE TABLE options (table options) structure for CREATE TABLE options (table options)
...@@ -212,14 +207,14 @@ struct ha_table_option_struct { ...@@ -212,14 +207,14 @@ struct ha_table_option_struct {
const char *catfunc; const char *catfunc;
const char *oplist; const char *oplist;
const char *data_charset; const char *data_charset;
int lrecl; ulonglong lrecl;
int elements; ulonglong elements;
//int estimate; //ulonglong estimate;
int multiple; ulonglong multiple;
int header; ulonglong header;
int quoted; ulonglong quoted;
int ending; ulonglong ending;
int compressed; ulonglong compressed;
bool mapped; bool mapped;
bool huge; bool huge;
bool split; bool split;
...@@ -227,7 +222,6 @@ struct ha_table_option_struct { ...@@ -227,7 +222,6 @@ struct ha_table_option_struct {
bool sepindex; bool sepindex;
}; };
#if defined(MARIADB)
ha_create_table_option connect_table_option_list[]= ha_create_table_option connect_table_option_list[]=
{ {
// These option are for stand alone Connect tables // These option are for stand alone Connect tables
...@@ -261,7 +255,6 @@ ha_create_table_option connect_table_option_list[]= ...@@ -261,7 +255,6 @@ ha_create_table_option connect_table_option_list[]=
HA_TOPTION_BOOL("SEPINDEX", sepindex, 0), HA_TOPTION_BOOL("SEPINDEX", sepindex, 0),
HA_TOPTION_END HA_TOPTION_END
}; };
#endif // MARIADB
/** /**
...@@ -272,16 +265,15 @@ ha_create_table_option connect_table_option_list[]= ...@@ -272,16 +265,15 @@ ha_create_table_option connect_table_option_list[]=
*/ */
struct ha_field_option_struct struct ha_field_option_struct
{ {
int offset; ulonglong offset;
int freq; // Not used by this version ulonglong freq; // Not used by this version
int opt; // Not used by this version ulonglong opt; // Not used by this version
int fldlen; ulonglong fldlen;
const char *dateformat; const char *dateformat;
const char *fieldformat; const char *fieldformat;
char *special; char *special;
}; };
#if defined(MARIADB)
ha_create_table_option connect_field_option_list[]= ha_create_table_option connect_field_option_list[]=
{ {
HA_FOPTION_NUMBER("FLAG", offset, -1, 0, INT_MAX32, 1), HA_FOPTION_NUMBER("FLAG", offset, -1, 0, INT_MAX32, 1),
...@@ -293,7 +285,6 @@ ha_create_table_option connect_field_option_list[]= ...@@ -293,7 +285,6 @@ ha_create_table_option connect_field_option_list[]=
HA_FOPTION_STRING("SPECIAL", special), HA_FOPTION_STRING("SPECIAL", special),
HA_FOPTION_END HA_FOPTION_END
}; };
#endif // MARIADB
/***********************************************************************/ /***********************************************************************/
/* Push G->Message as a MySQL warning. */ /* Push G->Message as a MySQL warning. */
...@@ -312,23 +303,11 @@ bool PushWarning(PGLOBAL g, PTDBASE tdbp) ...@@ -312,23 +303,11 @@ bool PushWarning(PGLOBAL g, PTDBASE tdbp)
return false; return false;
} // end of PushWarning } // end of PushWarning
/**
@brief
Function we use in the creation of our hash to get key.
*/
static uchar* connect_get_key(CONNECT_SHARE *share, size_t *length,
my_bool not_used __attribute__((unused)))
{
*length=share->table_name_length;
return (uchar*) share->table_name;
}
#ifdef HAVE_PSI_INTERFACE #ifdef HAVE_PSI_INTERFACE
static PSI_mutex_key con_key_mutex_connect, con_key_mutex_CONNECT_SHARE_mutex; static PSI_mutex_key con_key_mutex_CONNECT_SHARE_mutex;
static PSI_mutex_info all_connect_mutexes[]= static PSI_mutex_info all_connect_mutexes[]=
{ {
{ &con_key_mutex_connect, "connect", PSI_FLAG_GLOBAL},
{ &con_key_mutex_CONNECT_SHARE_mutex, "CONNECT_SHARE::mutex", 0} { &con_key_mutex_CONNECT_SHARE_mutex, "CONNECT_SHARE::mutex", 0}
}; };
...@@ -343,9 +322,36 @@ static void init_connect_psi_keys() ...@@ -343,9 +322,36 @@ static void init_connect_psi_keys()
count= array_elements(all_connect_mutexes); count= array_elements(all_connect_mutexes);
PSI_server->register_mutex(category, all_connect_mutexes, count); PSI_server->register_mutex(category, all_connect_mutexes, count);
} }
#else
static void init_connect_psi_keys() {}
#endif #endif
/**
@brief
If frm_error() is called then we will use this to determine
the file extensions that exist for the storage engine. This is also
used by the default rename_table and delete_table method in
handler.cc.
For engines that have two file name extentions (separate meta/index file
and data file), the order of elements is relevant. First element of engine
file name extentions array should be meta/index file extention. Second
element - data file extention. This order is assumed by
prepare_for_repair() when REPAIR TABLE ... USE_FRM is issued.
@see
rename_table method in handler.cc and
delete_table method in handler.cc
*/
static const char *ha_connect_exts[]= {
".tbl", ".dnx", ".fnx", ".bnx", ".vnx", ".dbx", ".dos", ".fix", ".csv",
".fmt", ".dbf", ".xml", ".ini", ".vec", ".odbc", ".mysql", ".dir",
".mac", ".wmi", ".bin", ".oem",
NULL
};
/** /**
@brief @brief
Plugin initialization Plugin initialization
...@@ -376,29 +382,16 @@ static int connect_init_func(void *p) ...@@ -376,29 +382,16 @@ static int connect_init_func(void *p)
} // endif xtrace } // endif xtrace
#ifdef HAVE_PSI_INTERFACE
init_connect_psi_keys(); init_connect_psi_keys();
#endif
connect_hton= (handlerton *)p; connect_hton= (handlerton *)p;
mysql_mutex_init(con_key_mutex_connect, &connect_mutex, MY_MUTEX_INIT_FAST);
//VOID(mysql_mutex_init(&connect_mutex, MY_MUTEX_INIT_FAST));
(void) my_hash_init(&connect_open_tables, system_charset_info, 32, 0, 0,
(my_hash_get_key) connect_get_key, 0, 0);
//connect_hton->name= "CONNECT";
connect_hton->state= SHOW_OPTION_YES; connect_hton->state= SHOW_OPTION_YES;
//connect_hton->comment= "CONNECT handler";
connect_hton->create= connect_create_handler; connect_hton->create= connect_create_handler;
connect_hton->flags= HTON_TEMPORARY_NOT_SUPPORTED | HTON_NO_PARTITION; connect_hton->flags= HTON_TEMPORARY_NOT_SUPPORTED | HTON_NO_PARTITION;
#if defined(MARIADB)
connect_hton->db_type= DB_TYPE_AUTOASSIGN;
connect_hton->table_options= connect_table_option_list; connect_hton->table_options= connect_table_option_list;
connect_hton->field_options= connect_field_option_list; connect_hton->field_options= connect_field_option_list;
#else // !MARIADB connect_hton->tablefile_extensions= ha_connect_exts;
//connect_hton->system_database= connect_system_database; connect_hton->discover_table_structure= connect_assisted_discovery;
//connect_hton->is_supported_system_table= connect_is_supported_system_table;
#endif // !MARIADB
if (xtrace) if (xtrace)
sql_print_information("connect_init: hton=%p", p); sql_print_information("connect_init: hton=%p", p);
...@@ -422,9 +415,6 @@ static int connect_done_func(void *p) ...@@ -422,9 +415,6 @@ static int connect_done_func(void *p)
XmlCleanupParserLib(); XmlCleanupParserLib();
#endif // LIBXML2_SUPPORT #endif // LIBXML2_SUPPORT
if (connect_open_tables.records)
error= 1;
for (pc= user_connect::to_users; pc; pc= pn) { for (pc= user_connect::to_users; pc; pc= pn) {
if (pc->g) if (pc->g)
PlugCleanup(pc->g, true); PlugCleanup(pc->g, true);
...@@ -433,9 +423,6 @@ static int connect_done_func(void *p) ...@@ -433,9 +423,6 @@ static int connect_done_func(void *p)
delete pc; delete pc;
} // endfor pc } // endfor pc
my_hash_free(&connect_open_tables);
mysql_mutex_destroy(&connect_mutex);
DBUG_RETURN(error); DBUG_RETURN(error);
} }
...@@ -454,38 +441,25 @@ static CONNECT_SHARE *get_share(const char *table_name, TABLE *table) ...@@ -454,38 +441,25 @@ static CONNECT_SHARE *get_share(const char *table_name, TABLE *table)
uint length; uint length;
char *tmp_name; char *tmp_name;
mysql_mutex_lock(&connect_mutex);
length=(uint) strlen(table_name); length=(uint) strlen(table_name);
if (!(share=(CONNECT_SHARE*)my_hash_search(&connect_open_tables, if (!(share= (CONNECT_SHARE *)table->s->ha_data)) {
(uchar*) table_name, length))) { if (!(share= (CONNECT_SHARE *)alloc_root(&table->s->mem_root, sizeof(*share) + length + 1)))
if (!(share=(CONNECT_SHARE *)my_multi_malloc(MYF(MY_WME | MY_ZEROFILL),
&share, sizeof(*share), &tmp_name, length+1, NullS))) {
mysql_mutex_unlock(&connect_mutex);
return NULL; return NULL;
} // endif share bzero(share, sizeof(*share));
tmp_name= (char*)(share + 1);
share->use_count=0;
share->table_name_length=length; share->table_name_length=length;
share->table_name=tmp_name; share->table_name=tmp_name;
strmov(share->table_name, table_name); strmov(share->table_name, table_name);
if (my_hash_insert(&connect_open_tables, (uchar*) share))
goto error;
thr_lock_init(&share->lock); thr_lock_init(&share->lock);
mysql_mutex_init(con_key_mutex_CONNECT_SHARE_mutex, mysql_mutex_init(con_key_mutex_CONNECT_SHARE_mutex,
&share->mutex, MY_MUTEX_INIT_FAST); &share->mutex, MY_MUTEX_INIT_FAST);
} // endif share } // endif share
share->use_count++; share->use_count++;
mysql_mutex_unlock(&connect_mutex);
return share; return share;
error:
mysql_mutex_destroy(&share->mutex);
my_free(share);
return NULL;
} }
...@@ -497,20 +471,12 @@ static CONNECT_SHARE *get_share(const char *table_name, TABLE *table) ...@@ -497,20 +471,12 @@ static CONNECT_SHARE *get_share(const char *table_name, TABLE *table)
static int free_share(CONNECT_SHARE *share) static int free_share(CONNECT_SHARE *share)
{ {
mysql_mutex_lock(&connect_mutex);
if (!--share->use_count) { if (!--share->use_count) {
my_hash_delete(&connect_open_tables, (uchar*) share);
thr_lock_delete(&share->lock); thr_lock_delete(&share->lock);
mysql_mutex_destroy(&share->mutex); mysql_mutex_destroy(&share->mutex);
#if !defined(MARIADB) TRASH(share, sizeof(*share));
my_free(share->table_options);
my_free(share->field_options);
#endif // !MARIADB
my_free(share);
} // endif share } // endif share
mysql_mutex_unlock(&connect_mutex);
return 0; return 0;
} }
...@@ -534,8 +500,9 @@ ha_connect::ha_connect(handlerton *hton, TABLE_SHARE *table_arg) ...@@ -534,8 +500,9 @@ ha_connect::ha_connect(handlerton *hton, TABLE_SHARE *table_arg)
:handler(hton, table_arg) :handler(hton, table_arg)
{ {
hnum= ++num; hnum= ++num;
xp= NULL; // Tested in next call xp= (table) ? GetUser(ha_thd(), NULL) : NULL;
xp= (table) ? GetUser(table->in_use) : NULL; if (xp)
xp->SetHandler(this);
tdbp= NULL; tdbp= NULL;
sdvalin= NULL; sdvalin= NULL;
sdvalout= NULL; sdvalout= NULL;
...@@ -554,10 +521,6 @@ ha_connect::ha_connect(handlerton *hton, TABLE_SHARE *table_arg) ...@@ -554,10 +521,6 @@ ha_connect::ha_connect(handlerton *hton, TABLE_SHARE *table_arg)
int_table_flags= (HA_NO_TRANSACTIONS | HA_NO_PREFIX_CHAR_KEYS); int_table_flags= (HA_NO_TRANSACTIONS | HA_NO_PREFIX_CHAR_KEYS);
ref_length= sizeof(int); ref_length= sizeof(int);
share= NULL; share= NULL;
#if !defined(MARIADB)
table_options= NULL;
field_options= NULL;
#endif // !MARIADB
tshp= NULL; tshp= NULL;
} // end of ha_connect constructor } // end of ha_connect constructor
...@@ -594,17 +557,13 @@ ha_connect::~ha_connect(void) ...@@ -594,17 +557,13 @@ ha_connect::~ha_connect(void)
} // endif xp } // endif xp
#if !defined(MARIADB)
my_free(table_options);
my_free(field_options);
#endif // !MARIADB
} // end of ha_connect destructor } // end of ha_connect destructor
/****************************************************************************/ /****************************************************************************/
/* Get a pointer to the user of this handler. */ /* Get a pointer to the user of this handler. */
/****************************************************************************/ /****************************************************************************/
PCONNECT ha_connect::GetUser(THD *thd) static PCONNECT GetUser(THD *thd, PCONNECT xp)
{ {
const char *dbn= NULL; const char *dbn= NULL;
...@@ -621,7 +580,7 @@ PCONNECT ha_connect::GetUser(THD *thd) ...@@ -621,7 +580,7 @@ PCONNECT ha_connect::GetUser(THD *thd)
if (!xp) { if (!xp) {
xp= new user_connect(thd, dbn); xp= new user_connect(thd, dbn);
if (xp->user_init(this)) { if (xp->user_init()) {
delete xp; delete xp;
xp= NULL; xp= NULL;
} // endif user_init } // endif user_init
...@@ -636,9 +595,9 @@ PCONNECT ha_connect::GetUser(THD *thd) ...@@ -636,9 +595,9 @@ PCONNECT ha_connect::GetUser(THD *thd)
/****************************************************************************/ /****************************************************************************/
/* Get the global pointer of the user of this handler. */ /* Get the global pointer of the user of this handler. */
/****************************************************************************/ /****************************************************************************/
PGLOBAL ha_connect::GetPlug(THD *thd) static PGLOBAL GetPlug(THD *thd, PCONNECT lxp)
{ {
PCONNECT lxp= GetUser(thd); lxp= GetUser(thd, lxp);
return (lxp) ? lxp->g : NULL; return (lxp) ? lxp->g : NULL;
} // end of GetPlug } // end of GetPlug
...@@ -646,9 +605,8 @@ PGLOBAL ha_connect::GetPlug(THD *thd) ...@@ -646,9 +605,8 @@ PGLOBAL ha_connect::GetPlug(THD *thd)
/****************************************************************************/ /****************************************************************************/
/* Return the value of an option specified in the option list. */ /* Return the value of an option specified in the option list. */
/****************************************************************************/ /****************************************************************************/
char *ha_connect::GetListOption(const char *opname, static char *GetListOption(PGLOBAL g, const char *opname,
const char *oplist, const char *oplist, const char *def=NULL)
const char *def)
{ {
char key[16], val[256]; char key[16], val[256];
char *pk, *pv, *pn; char *pk, *pv, *pn;
...@@ -684,7 +642,7 @@ char *ha_connect::GetListOption(const char *opname, ...@@ -684,7 +642,7 @@ char *ha_connect::GetListOption(const char *opname,
} // endif pv } // endif pv
if (!stricmp(opname, key)) { if (!stricmp(opname, key)) {
opval= (char*)PlugSubAlloc(xp->g, NULL, strlen(val) + 1); opval= (char*)PlugSubAlloc(g, NULL, strlen(val) + 1);
strcpy(opval, val); strcpy(opval, val);
break; break;
} else if (!pn) } else if (!pn)
...@@ -700,97 +658,7 @@ char *ha_connect::GetListOption(const char *opname, ...@@ -700,97 +658,7 @@ char *ha_connect::GetListOption(const char *opname,
/****************************************************************************/ /****************************************************************************/
PTOS ha_connect::GetTableOptionStruct(TABLE *tab) PTOS ha_connect::GetTableOptionStruct(TABLE *tab)
{ {
#if defined(MARIADB)
return (tshp) ? tshp->option_struct : tab->s->option_struct; return (tshp) ? tshp->option_struct : tab->s->option_struct;
#else // !MARIADB
if (share && share->table_options)
return share->table_options;
else if (table_options)
return table_options;
char *pk, *pv, *pn, *val;
size_t len= sizeof(ha_table_option_struct) + tab->s->comment.length + 1;
PTOS top= (PTOS)my_malloc(len, MYF(MY_FAE | MY_ZEROFILL));
top->quoted= -1; // Default value
top->ending= -1; // Default value
pk= (char *)top + sizeof(ha_table_option_struct);
memcpy(pk, tab->s->comment.str, tab->s->comment.length);
for (; pk; pk= ++pn) {
pn= strchr(pk, ',');
pv= strchr(pk, '=');
if (pn) *pn= 0;
if (pv) *pv= 0;
val= (pv && (!pn || pv < pn)) ? pv + 1 : "";
if (!stricmp(pk, "type") || !stricmp(pk, "Table_Type")) {
top->type= val;
} else if (!stricmp(pk, "fn") || !stricmp(pk, "filename")
|| !stricmp(pk, "File_Name")) {
top->filename= val;
} else if (!stricmp(pk, "optfn") || !stricmp(pk, "optname")
|| !stricmp(pk, "Xfile_Name")) {
top->optname= val;
} else if (!stricmp(pk, "name") || !stricmp(pk, "tabname")) {
top->tabname= val;
} else if (!stricmp(pk, "tablist") || !stricmp(pk, "tablelist")
|| !stricmp(pk, "Table_list")) {
top->tablist= val;
} else if (!stricmp(pk, "sep") || !stricmp(pk, "separator")
|| !stricmp(pk, "Sep_Char")) {
top->separator= val;
} else if (!stricmp(pk, "db") || !stricmp(pk, "DBName")
|| !stricmp(pk, "Database") {
top->dbname= val;
} else if (!stricmp(pk, "qchar")) {
top->qchar= val;
} else if (!stricmp(pk, "module")) {
top->module= val;
} else if (!stricmp(pk, "subtype")) {
top->subtype= val;
} else if (!stricmp(pk, "lrecl")) {
top->lrecl= atoi(val);
} else if (!stricmp(pk, "elements")) {
top->elements= atoi(val);
} else if (!stricmp(pk, "multiple")) {
top->multiple= atoi(val);
} else if (!stricmp(pk, "header")) {
top->header= atoi(val);
} else if (!stricmp(pk, "quoted")) {
top->quoted= atoi(val);
} else if (!stricmp(pk, "ending")) {
top->ending= atoi(val);
} else if (!stricmp(pk, "compressed")) {
top->compressed= atoi(val);
} else if (!stricmp(pk, "mapped")) {
top->mapped= (!*val || *val == 'y' || *val == 'Y' || atoi(val) != 0);
} else if (!stricmp(pk, "huge")) {
top->huge= (!*val || *val == 'y' || *val == 'Y' || atoi(val) != 0);
} else if (!stricmp(pk, "split")) {
top->split= (!*val || *val == 'y' || *val == 'Y' || atoi(val) != 0);
} else if (!stricmp(pk, "readonly") || !stricmp(pk, "protected")) {
top->readonly= (!*val || *val == 'y' || *val == 'Y' || atoi(val) != 0);
} // endif's
if (!pn)
break;
} // endfor pk
// This to get all other options
top->oplist= tab->s->comment.str;
if (share)
share->table_options= top;
else
table_options= top;
return top;
#endif // !MARIADB
} // end of GetTableOptionStruct } // end of GetTableOptionStruct
/****************************************************************************/ /****************************************************************************/
...@@ -833,7 +701,7 @@ char *ha_connect::GetStringOption(char *opname, char *sdef) ...@@ -833,7 +701,7 @@ char *ha_connect::GetStringOption(char *opname, char *sdef)
opval= (char*)options->data_charset; opval= (char*)options->data_charset;
if (!opval && options && options->oplist) if (!opval && options && options->oplist)
opval= GetListOption(opname, options->oplist); opval= GetListOption(xp->g, opname, options->oplist);
if (!opval) { if (!opval) {
if (sdef && !strcmp(sdef, "*")) { if (sdef && !strcmp(sdef, "*")) {
...@@ -875,7 +743,7 @@ bool ha_connect::GetBooleanOption(char *opname, bool bdef) ...@@ -875,7 +743,7 @@ bool ha_connect::GetBooleanOption(char *opname, bool bdef)
else if (!stricmp(opname, "SepIndex")) else if (!stricmp(opname, "SepIndex"))
opval= options->sepindex; opval= options->sepindex;
else if (options->oplist) else if (options->oplist)
if ((pv= GetListOption(opname, options->oplist))) if ((pv= GetListOption(xp->g, opname, options->oplist)))
opval= (!*pv || *pv == 'y' || *pv == 'Y' || atoi(pv) != 0); opval= (!*pv || *pv == 'y' || *pv == 'Y' || atoi(pv) != 0);
return opval; return opval;
...@@ -932,7 +800,7 @@ int ha_connect::GetIntegerOption(char *opname) ...@@ -932,7 +800,7 @@ int ha_connect::GetIntegerOption(char *opname)
opval= (options->compressed); opval= (options->compressed);
if (opval == NO_IVAL && options && options->oplist) if (opval == NO_IVAL && options && options->oplist)
if ((pv= GetListOption(opname, options->oplist))) if ((pv= GetListOption(xp->g, opname, options->oplist)))
opval= atoi(pv); opval= atoi(pv);
return opval; return opval;
...@@ -978,71 +846,7 @@ bool ha_connect::SetIntegerOption(char *opname, int n) ...@@ -978,71 +846,7 @@ bool ha_connect::SetIntegerOption(char *opname, int n)
/****************************************************************************/ /****************************************************************************/
PFOS ha_connect::GetFieldOptionStruct(Field *fdp) PFOS ha_connect::GetFieldOptionStruct(Field *fdp)
{ {
#if defined(MARIADB)
return fdp->option_struct; return fdp->option_struct;
#else // !MARIADB
if (share && share->field_options)
return &share->field_options[fdp->field_index];
else if (field_options)
return &field_options[fdp->field_index];
char *pc, *pk, *pv, *pn, *val;
int i, k, n= table->s->fields;
size_t len= n + n * sizeof(ha_field_option_struct);
PFOS fp, fop;
for (i= 0; i < n; i++)
len+= table->s->field[i]->comment.length;
fop= (PFOS)my_malloc(len, MYF(MY_FAE | MY_ZEROFILL));
pc= (char*)fop + n * sizeof(ha_field_option_struct);
for (i= k= 0; i < n; i++) {
fp= &fop[i];
fp->offset= -1; // Default value
if (!table->s->field[i]->comment.length)
continue;
memcpy(pc, table->s->field[i]->comment.str,
table->s->field[i]->comment.length);
for (pk= pc; pk; pk= ++pn) {
if ((pn= strchr(pk, ','))) *pn= 0;
if ((pv= strchr(pk, '='))) *pv= 0;
val= (pv && (!pn || pv < pn)) ? pv + 1 : "";
if (!stricmp(pk, "datefmt") || !stricmp(pk, "date_format")) {
fp->dateformat= val;
} else if (!stricmp(pk, "fieldfmt") || !stricmp(pk, "field_format")) {
fp->fieldformat= val;
} else if (!stricmp(pk, "special")) {
fp->special= val;
} else if (!stricmp(pk, "offset") || !stricmp(pk, "flag")) {
fp->offset= atoi(val);
} else if (!stricmp(pk, "freq")) {
fp->freq= atoi(val);
} else if (!stricmp(pk, "opt")) {
fp->opt= atoi(val);
} else if (!stricmp(pk, "fldlen") || !stricmp(pk, "field_length")) {
fp->fldlen= atoi(val);
} // endif's
if (!pn)
break;
} // endfor pk
pc+= table->s->field[i]->comment.length + 1;
} // endfor i
if (share)
share->field_options= fop;
else
field_options= fop;
return &fop[fdp->field_index];
#endif // !MARIADB
} // end of GetFildOptionStruct } // end of GetFildOptionStruct
/****************************************************************************/ /****************************************************************************/
...@@ -1144,7 +948,7 @@ void *ha_connect::GetColumnOption(void *field, PCOLINFO pcf) ...@@ -1144,7 +948,7 @@ void *ha_connect::GetColumnOption(void *field, PCOLINFO pcf)
if (pcf->Datefmt) { if (pcf->Datefmt) {
// Find the (max) length produced by the date format // Find the (max) length produced by the date format
char buf[256]; char buf[256];
PGLOBAL g= GetPlug(table->in_use); PGLOBAL g= GetPlug(table->in_use, xp);
#if defined(WIN32) #if defined(WIN32)
struct tm datm= {0,0,0,12,11,112,0,0,0}; struct tm datm= {0,0,0,12,11,112,0,0,0};
#else // !WIN32 #else // !WIN32
...@@ -1172,11 +976,9 @@ void *ha_connect::GetColumnOption(void *field, PCOLINFO pcf) ...@@ -1172,11 +976,9 @@ void *ha_connect::GetColumnOption(void *field, PCOLINFO pcf)
if (fp->real_maybe_null()) if (fp->real_maybe_null())
pcf->Flags |= U_NULLS; pcf->Flags |= U_NULLS;
#if defined(MARIADB)
// Mark virtual columns as such // Mark virtual columns as such
if (fp->vcol_info && !fp->stored_in_db) if (fp->vcol_info && !fp->stored_in_db)
pcf->Flags |= U_VIRTUAL; pcf->Flags |= U_VIRTUAL;
#endif // MARIADB
pcf->Key= 0; // Not used when called from MySQL pcf->Key= 0; // Not used when called from MySQL
pcf->Remark= fp->comment.str; pcf->Remark= fp->comment.str;
...@@ -1477,16 +1279,10 @@ int ha_connect::MakeRecord(char *buf) ...@@ -1477,16 +1279,10 @@ int ha_connect::MakeRecord(char *buf)
DBUG_ENTER("ha_connect::MakeRecord"); DBUG_ENTER("ha_connect::MakeRecord");
if (xtrace > 1) if (xtrace > 1)
#if defined(MARIADB)
printf("Maps: read=%08X write=%08X vcol=%08X defr=%08X defw=%08X\n", printf("Maps: read=%08X write=%08X vcol=%08X defr=%08X defw=%08X\n",
*table->read_set->bitmap, *table->write_set->bitmap, *table->read_set->bitmap, *table->write_set->bitmap,
*table->vcol_set->bitmap, *table->vcol_set->bitmap,
*table->def_read_set.bitmap, *table->def_write_set.bitmap); *table->def_read_set.bitmap, *table->def_write_set.bitmap);
#else // !MARIADB
printf("Maps: read=%p write=%p defr=%p defw=%p\n",
*table->read_set->bitmap, *table->write_set->bitmap,
*table->def_read_set.bitmap, *table->def_write_set.bitmap);
#endif // !MARIADB
// Avoid asserts in field::store() for columns that are not updated // Avoid asserts in field::store() for columns that are not updated
org_bitmap= dbug_tmp_use_all_columns(table, table->write_set); org_bitmap= dbug_tmp_use_all_columns(table, table->write_set);
...@@ -1501,10 +1297,8 @@ int ha_connect::MakeRecord(char *buf) ...@@ -1501,10 +1297,8 @@ int ha_connect::MakeRecord(char *buf)
for (field= table->field; *field && !rc; field++) { for (field= table->field; *field && !rc; field++) {
fp= *field; fp= *field;
#if defined(MARIADB)
if (fp->vcol_info && !fp->stored_in_db) if (fp->vcol_info && !fp->stored_in_db)
continue; // This is a virtual column continue; // This is a virtual column
#endif // MARIADB
if (bitmap_is_set(map, fp->field_index)) { if (bitmap_is_set(map, fp->field_index)) {
// This is a used field, fill the buffer with value // This is a used field, fill the buffer with value
...@@ -1603,11 +1397,9 @@ int ha_connect::ScanRecord(PGLOBAL g, uchar *buf) ...@@ -1603,11 +1397,9 @@ int ha_connect::ScanRecord(PGLOBAL g, uchar *buf)
for (Field **field=table->field ; *field ; field++) { for (Field **field=table->field ; *field ; field++) {
fp= *field; fp= *field;
#if defined(MARIADB)
if ((fp->vcol_info && !fp->stored_in_db) || if ((fp->vcol_info && !fp->stored_in_db) ||
fp->option_struct->special) fp->option_struct->special)
continue; // Is a virtual column possible here ??? continue; // Is a virtual column possible here ???
#endif // MARIADB
if (xmod == MODE_INSERT || if (xmod == MODE_INSERT ||
bitmap_is_set(table->write_set, fp->field_index)) { bitmap_is_set(table->write_set, fp->field_index)) {
...@@ -2048,39 +1840,6 @@ bool ha_connect::get_error_message(int error, String* buf) ...@@ -2048,39 +1840,6 @@ bool ha_connect::get_error_message(int error, String* buf)
} // end of get_error_message } // end of get_error_message
/**
@brief
If frm_error() is called then we will use this to determine
the file extensions that exist for the storage engine. This is also
used by the default rename_table and delete_table method in
handler.cc.
For engines that have two file name extentions (separate meta/index file
and data file), the order of elements is relevant. First element of engine
file name extentions array should be meta/index file extention. Second
element - data file extention. This order is assumed by
prepare_for_repair() when REPAIR TABLE ... USE_FRM is issued.
@note: PlugDB will handle all file creation/deletion. When dropping
a CONNECT table, we don't want the PlugDB table to be dropped or erased.
Therefore we provide a void list of extensions.
@see
rename_table method in handler.cc and
delete_table method in handler.cc
*/
static const char *ha_connect_null_exts[]= {
NullS
};
static const char* *ha_connect_exts= ha_connect_null_exts;
const char **ha_connect::bas_ext() const
{
return ha_connect_exts; // a null list, see @note above
} // end of bas_ext
/** /**
@brief @brief
Used for opening tables. The name will be the name of the file. Used for opening tables. The name will be the name of the file.
...@@ -2115,14 +1874,12 @@ int ha_connect::open(const char *name, int mode, uint test_if_locked) ...@@ -2115,14 +1874,12 @@ int ha_connect::open(const char *name, int mode, uint test_if_locked)
thr_lock_data_init(&share->lock,&lock,NULL); thr_lock_data_init(&share->lock,&lock,NULL);
// Try to get the user if possible // Try to get the user if possible
if (table && table->in_use) { xp= GetUser(ha_thd(), xp);
PGLOBAL g= GetPlug(table->in_use); PGLOBAL g= xp->g;
// Try to set the database environment
if (g)
rc= (CntCheckDB(g, this, name)) ? (-2) : 0;
} // endif table // Try to set the database environment
if (g)
rc= (CntCheckDB(g, this, name)) ? (-2) : 0;
DBUG_RETURN(rc); DBUG_RETURN(rc);
} // end of open } // end of open
...@@ -2589,7 +2346,7 @@ int ha_connect::index_next_same(uchar *buf, const uchar *key, uint keylen) ...@@ -2589,7 +2346,7 @@ int ha_connect::index_next_same(uchar *buf, const uchar *key, uint keylen)
*/ */
int ha_connect::rnd_init(bool scan) int ha_connect::rnd_init(bool scan)
{ {
PGLOBAL g= ((table && table->in_use) ? GetPlug(table->in_use) : PGLOBAL g= ((table && table->in_use) ? GetPlug(table->in_use, xp) :
(xp) ? xp->g : NULL); (xp) ? xp->g : NULL);
DBUG_ENTER("ha_connect::rnd_init"); DBUG_ENTER("ha_connect::rnd_init");
...@@ -2603,11 +2360,7 @@ int ha_connect::rnd_init(bool scan) ...@@ -2603,11 +2360,7 @@ int ha_connect::rnd_init(bool scan)
DBUG_RETURN(HA_ERR_INITIALIZATION); DBUG_RETURN(HA_ERR_INITIALIZATION);
if (OpenTable(g, xmod == MODE_DELETE)) if (OpenTable(g, xmod == MODE_DELETE))
#if defined(MARIADB)
DBUG_RETURN(HA_ERR_INITIALIZATION); DBUG_RETURN(HA_ERR_INITIALIZATION);
#else // !MARIADB
DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
#endif // !MARIADB
} else } else
void(CntRewindTable(g, tdbp)); // Read from beginning void(CntRewindTable(g, tdbp)); // Read from beginning
...@@ -2663,11 +2416,6 @@ int ha_connect::rnd_next(uchar *buf) ...@@ -2663,11 +2416,6 @@ int ha_connect::rnd_next(uchar *buf)
DBUG_ENTER("ha_connect::rnd_next"); DBUG_ENTER("ha_connect::rnd_next");
//statistic_increment(ha_read_rnd_next_count, &LOCK_status); //statistic_increment(ha_read_rnd_next_count, &LOCK_status);
#if !defined(MARIADB)
if (!tdbp) // MySQL ignores error from rnd_init
DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
#endif // !MARIADB
if (tdbp->GetMode() == MODE_ANY) { if (tdbp->GetMode() == MODE_ANY) {
// We will stop on next read // We will stop on next read
if (!stop) { if (!stop) {
...@@ -2813,7 +2561,7 @@ int ha_connect::rnd_pos(uchar *buf, uchar *pos) ...@@ -2813,7 +2561,7 @@ int ha_connect::rnd_pos(uchar *buf, uchar *pos)
int ha_connect::info(uint flag) int ha_connect::info(uint flag)
{ {
bool pure= false; bool pure= false;
PGLOBAL g= GetPlug((table) ? table->in_use : NULL); PGLOBAL g= GetPlug((table) ? table->in_use : NULL, xp);
DBUG_ENTER("ha_connect::info"); DBUG_ENTER("ha_connect::info");
...@@ -2847,8 +2595,8 @@ int ha_connect::info(uint flag) ...@@ -2847,8 +2595,8 @@ int ha_connect::info(uint flag)
if (flag & HA_STATUS_CONST) { if (flag & HA_STATUS_CONST) {
// This is imported from the previous handler and must be reconsidered // This is imported from the previous handler and must be reconsidered
stats.max_data_file_length= LL(4294967295); stats.max_data_file_length= 4294967295;
stats.max_index_file_length= LL(4398046510080); stats.max_index_file_length= 4398046510080;
stats.create_time= 0; stats.create_time= 0;
data_file_name= xinfo.data_file_name; data_file_name= xinfo.data_file_name;
index_file_name= NULL; index_file_name= NULL;
...@@ -2941,8 +2689,8 @@ int ha_connect::delete_all_rows() ...@@ -2941,8 +2689,8 @@ int ha_connect::delete_all_rows()
bool ha_connect::check_privileges(THD *thd, PTOS options) bool ha_connect::check_privileges(THD *thd, PTOS options)
{ {
if (!options || !options->type) if (!options->type)
goto err; options->type= "DOS";
switch (GetTypeID(options->type)) switch (GetTypeID(options->type))
{ {
...@@ -2953,7 +2701,9 @@ bool ha_connect::check_privileges(THD *thd, PTOS options) ...@@ -2953,7 +2701,9 @@ bool ha_connect::check_privileges(THD *thd, PTOS options)
case TAB_DMY: case TAB_DMY:
case TAB_NIY: case TAB_NIY:
case TAB_PIVOT: case TAB_PIVOT:
goto err; my_printf_error(ER_UNKNOWN_ERROR,
"Unsupported table type %s", MYF(0), options->type);
return true;
case TAB_DOS: case TAB_DOS:
case TAB_FIX: case TAB_FIX:
...@@ -2988,9 +2738,8 @@ bool ha_connect::check_privileges(THD *thd, PTOS options) ...@@ -2988,9 +2738,8 @@ bool ha_connect::check_privileges(THD *thd, PTOS options)
return false; return false;
} }
err: my_printf_error(ER_UNKNOWN_ERROR, "check_privileges failed", MYF(0));
my_printf_error(ER_UNKNOWN_ERROR, "check_privileges failed", MYF(0)); return true;
return true;
} }
// Check that two indexes are equivalent // Check that two indexes are equivalent
...@@ -3046,7 +2795,7 @@ int ha_connect::external_lock(THD *thd, int lock_type) ...@@ -3046,7 +2795,7 @@ int ha_connect::external_lock(THD *thd, int lock_type)
bool del= false, xcheck=false, cras= false; bool del= false, xcheck=false, cras= false;
MODE newmode; MODE newmode;
PTOS options= GetTableOptionStruct(table); PTOS options= GetTableOptionStruct(table);
PGLOBAL g= GetPlug(thd); PGLOBAL g= GetPlug(thd, xp);
DBUG_ENTER("ha_connect::external_lock"); DBUG_ENTER("ha_connect::external_lock");
if (xtrace) if (xtrace)
...@@ -3387,8 +3136,7 @@ int ha_connect::delete_or_rename_table(const char *name, const char *to) ...@@ -3387,8 +3136,7 @@ int ha_connect::delete_or_rename_table(const char *name, const char *to)
#endif // !WIN32 #endif // !WIN32
char key[MAX_DBKEY_LENGTH], db[128], tabname[128]; char key[MAX_DBKEY_LENGTH], db[128], tabname[128];
int rc; int rc;
uint key_length, db_flags= 0; uint key_length;
TABLE_LIST table_list;
TABLE_SHARE *share; TABLE_SHARE *share;
THD *thd= current_thd; THD *thd= current_thd;
...@@ -3399,16 +3147,14 @@ int ha_connect::delete_or_rename_table(const char *name, const char *to) ...@@ -3399,16 +3147,14 @@ int ha_connect::delete_or_rename_table(const char *name, const char *to)
if (sscanf(name, fmt, db, tabname) != 2 || *tabname == '#') if (sscanf(name, fmt, db, tabname) != 2 || *tabname == '#')
goto fin; goto fin;
table_list.db= (char*) db; key_length= create_table_def_key(key, db, tabname);
table_list.table_name= (char*) tabname;
key_length= create_table_def_key(thd, key, &table_list, 0);
// share contains the option struct that we need // share contains the option struct that we need
if (!(share= alloc_table_share(&table_list, key, key_length))) if (!(share= alloc_table_share(db, tabname, key, key_length)))
goto fin; goto fin;
// Get the share info from the .frm file // Get the share info from the .frm file
if (open_table_def(thd, share, db_flags)) if (open_table_def(thd, share))
goto err; goto err;
// Now we can work // Now we can work
...@@ -3421,54 +3167,11 @@ int ha_connect::delete_or_rename_table(const char *name, const char *to) ...@@ -3421,54 +3167,11 @@ int ha_connect::delete_or_rename_table(const char *name, const char *to)
} }
if (IsFileType(GetTypeID(pos->type)) && !pos->filename) { if (IsFileType(GetTypeID(pos->type)) && !pos->filename) {
// This is a table whose files must be erased or renamed */
// char ftype[8], *new_exts[2];
char ftype[12], *xtype, *new_exts[3];
int n= 0;
if (share->keynames.count) {
switch (GetTypeID(pos->type)) {
case TAB_CSV:
case TAB_FMT:
case TAB_DOS: xtype= ".dnx"; break;
case TAB_FIX: xtype= ".fnx"; break;
case TAB_BIN: xtype= ".bnx"; break;
case TAB_VEC: xtype= ".vnx"; break;
case TAB_DBF: xtype= ".dbx"; break;
default:
xtype= NULL;
// return true;
} // endswitch Ftype
if (xtype)
new_exts[n++]= xtype;
} // endif keynames
// Fold type to lower case
ftype[0]= '.';
for (int i= 0; i < 12; i++)
if (!pos->type[i]) {
ftype[i+1]= 0;
break;
} else
ftype[i+1]= tolower(pos->type[i]);
new_exts[n++]= ftype;
new_exts[n]= NULL;
// This will be answered by bas_ext()
ha_connect_exts= (const char**)new_exts;
// Let the base handler do the job // Let the base handler do the job
if (to) if (to)
rc= handler::rename_table(name, to); rc= handler::rename_table(name, to);
else else
rc= handler::delete_table(name); rc= handler::delete_table(name);
// Reset the ext list to null.
ha_connect_exts= ha_connect_null_exts;
} // endif filename } // endif filename
// Done no more need for this // Done no more need for this
...@@ -3542,11 +3245,10 @@ ha_rows ha_connect::records_in_range(uint inx, key_range *min_key, ...@@ -3542,11 +3245,10 @@ ha_rows ha_connect::records_in_range(uint inx, key_range *min_key,
DBUG_RETURN(rows); DBUG_RETURN(rows);
} // end of records_in_range } // end of records_in_range
#if defined(MARIADB)
/** /**
Convert an ISO-8859-1 column name to UTF-8 Convert an ISO-8859-1 column name to UTF-8
*/ */
char *ha_connect::encode(PGLOBAL g, char *cnm) static char *encode(PGLOBAL g, char *cnm)
{ {
char *buf= (char*)PlugSubAlloc(g, NULL, strlen(cnm) * 3); char *buf= (char*)PlugSubAlloc(g, NULL, strlen(cnm) * 3);
uint dummy_errors; uint dummy_errors;
...@@ -3566,191 +3268,105 @@ char *ha_connect::encode(PGLOBAL g, char *cnm) ...@@ -3566,191 +3268,105 @@ char *ha_connect::encode(PGLOBAL g, char *cnm)
Return 0 if ok Return 0 if ok
*/ */
bool ha_connect::add_fields(THD *thd, void *alt_info, bool add_field(String *sql, const char *field_name, const char *type,
LEX_STRING *field_name, int len, int dec, uint tm, const char *rem)
enum_field_types type,
char *length, char *decimals,
uint type_modifier,
// Item *default_value, Item *on_update_value,
LEX_STRING *comment,
// char *change,
// List<String> *interval_list,
CHARSET_INFO *cs,
// uint uint_geom_type,
void *vcolinfo,
engine_option_value *create_options)
{ {
register Create_field *new_field; bool error= false;
Alter_info *alter_info= (Alter_info*)alt_info;
Virtual_column_info *vcol_info= (Virtual_column_info *)vcolinfo;
DBUG_ENTER("ha_connect::add_fields");
if (check_string_char_length(field_name, "", NAME_CHAR_LEN, error|= sql->append(field_name);
system_charset_info, 1)) error|= sql->append(' ');
{ error|= sql->append(type);
my_error(ER_TOO_LONG_IDENT, MYF(0), field_name->str); /* purecov: inspected */ if (len) {
DBUG_RETURN(1); /* purecov: inspected */ error|= sql->append('(');
} error|= sql->append_ulonglong(len);
#if 0 if (dec) {
if (type_modifier & PRI_KEY_FLAG) error|= sql->append(',');
{ error|= sql->append_ulonglong(dec);
Key *key;
lex->col_list.push_back(new Key_part_spec(*field_name, 0));
key= new Key(Key::PRIMARY, null_lex_str,
&default_key_create_info,
0, lex->col_list, NULL);
alter_info->key_list.push_back(key);
lex->col_list.empty();
}
if (type_modifier & (UNIQUE_FLAG | UNIQUE_KEY_FLAG))
{
Key *key;
lex->col_list.push_back(new Key_part_spec(*field_name, 0));
key= new Key(Key::UNIQUE, null_lex_str,
&default_key_create_info, 0,
lex->col_list, NULL);
alter_info->key_list.push_back(key);
lex->col_list.empty();
}
if (default_value)
{
/*
Default value should be literal => basic constants =>
no need fix_fields()
We allow only one function as part of default value -
NOW() as default for TIMESTAMP type.
*/
if (default_value->type() == Item::FUNC_ITEM &&
!(((Item_func*)default_value)->functype() == Item_func::NOW_FUNC &&
type == MYSQL_TYPE_TIMESTAMP))
{
my_error(ER_INVALID_DEFAULT, MYF(0), field_name->str);
DBUG_RETURN(1);
}
else if (default_value->type() == Item::NULL_ITEM)
{
default_value= 0;
if ((type_modifier & (NOT_NULL_FLAG | AUTO_INCREMENT_FLAG)) ==
NOT_NULL_FLAG)
{
my_error(ER_INVALID_DEFAULT, MYF(0), field_name->str);
DBUG_RETURN(1);
} }
error|= sql->append(')');
} }
else if (type_modifier & AUTO_INCREMENT_FLAG)
{ if (tm)
my_error(ER_INVALID_DEFAULT, MYF(0), field_name->str); error|= sql->append(STRING_WITH_LEN(" NOT NULL"), system_charset_info);
DBUG_RETURN(1);
}
}
if (on_update_value && type != MYSQL_TYPE_TIMESTAMP) if (rem && *rem) {
{ error|= sql->append(" COMMENT='");
my_error(ER_INVALID_ON_UPDATE, MYF(0), field_name->str); error|= sql->append_for_single_quote(rem, strlen(rem));
DBUG_RETURN(1); error|= sql->append("'");
} }
#endif // 0
if (!(new_field= new Create_field()) || sql->append(',');
new_field->init(thd, field_name->str, type, length, decimals, type_modifier,
NULL, NULL, comment, NULL,
NULL, cs, 0, vcol_info,
create_options))
DBUG_RETURN(1);
alter_info->create_list.push_back(new_field); return error;
//lex->last_field=new_field; } // end of add_field
DBUG_RETURN(0);
} // end of add_fields
/** /**
@brief @brief
pre_create() is called when creating a table with no columns. connect_assisted_discovery() is called when creating a table with no columns.
@details @details
When pre_create() is called the .frm file have not already been When assisted discovery is used the .frm file have not already been
created. You can overwrite some definitions at this point but the created. You can overwrite some definitions at this point but the
main purpose of it is to define the columns for some table types. main purpose of it is to define the columns for some table types.
@note
Not really implemented yet.
*/ */
bool ha_connect::pre_create(THD *thd, HA_CREATE_INFO *create_info, static int connect_assisted_discovery(handlerton *hton, THD* thd,
void *alt_info) TABLE_SHARE *table_s,
HA_CREATE_INFO *create_info)
{ {
char spc= ',', qch= 0; char spc= ',', qch= 0;
const char *typn= "?";
const char *fncn= "?"; const char *fncn= "?";
const char *user; const char *user, *fn, *tab, *db, *host, *pwd, *prt, *sep; // *csn;
char *fn, *dsn, *tab, *db, *host, *pwd, *prt, *sep; // *csn; char *dsn;
#if defined(WIN32) #if defined(WIN32)
char *nsp= NULL, *cls= NULL; char *nsp= NULL, *cls= NULL;
#endif // WIN32 #endif // WIN32
int port= MYSQL_PORT, hdr= 0, mxr= 0; int port= MYSQL_PORT, hdr= 0, mxr= 0, b= 0;
uint tm, fnc= FNC_NO, supfnc= (FNC_NO | FNC_COL); uint tm, fnc= FNC_NO, supfnc= (FNC_NO | FNC_COL);
bool b= false, ok= false, dbf= false; bool ok= false, dbf= false;
TABTYPE ttp= TAB_UNDEF; TABTYPE ttp= TAB_UNDEF;
LEX_STRING *comment, *name, *val;
MEM_ROOT *mem= thd->mem_root; MEM_ROOT *mem= thd->mem_root;
CHARSET_INFO *cs; CHARSET_INFO *cs;
Alter_info *alter_info= (Alter_info*)alt_info;
engine_option_value *pov, **start= &create_info->option_list, *end= NULL;
PQRYRES qrp; PQRYRES qrp;
PCOLRES crp; PCOLRES crp;
PGLOBAL g= GetPlug(thd); PGLOBAL g= GetPlug(thd, NULL);
PTOS topt= table_s->option_struct;
char buf[1024];
String sql(buf, sizeof(buf), system_charset_info);
if (!g) if (!g)
return true; return HA_ERR_INTERNAL_ERROR;
fn= dsn= tab= db= host= pwd= prt= sep= NULL; sql.copy(STRING_WITH_LEN("CREATE TABLE whatever ("), system_charset_info);
user= NULL;
user= host= pwd= prt= dsn= NULL;
// Get the useful create options // Get the useful create options
for (pov= *start; pov; pov= pov->next) { ttp= GetTypeID(topt->type);
if (!stricmp(pov->name.str, "table_type")) { fn= topt->filename;
typn= pov->value.str; tab= topt->tabname;
ttp= GetTypeID(typn); db= topt->dbname;
} else if (!stricmp(pov->name.str, "file_name")) { fncn= topt->catfunc;
fn= pov->value.str; fnc= GetFuncID(fncn);
} else if (!stricmp(pov->name.str, "tabname")) { sep= topt->separator;
tab= pov->value.str; spc= (!sep || !strcmp(sep, "\\t")) ? '\t' : *sep;
} else if (!stricmp(pov->name.str, "dbname")) { qch= topt->qchar ? *topt->qchar : topt->quoted >= 0 ? '"' : 0;
db= pov->value.str; hdr= topt->header;
} else if (!stricmp(pov->name.str, "catfunc")) { if (topt->oplist) {
fncn= pov->value.str; host= GetListOption(g,"host", topt->oplist, "localhost");
fnc= GetFuncID(fncn); user= GetListOption(g,"user", topt->oplist, "root");
} else if (!stricmp(pov->name.str, "sep_char")) {
sep= pov->value.str;
spc= (!strcmp(sep, "\\t")) ? '\t' : *sep;
} else if (!stricmp(pov->name.str, "qchar")) {
qch= *pov->value.str;
} else if (!stricmp(pov->name.str, "quoted")) {
if (!qch)
qch= '"';
} else if (!stricmp(pov->name.str, "header")) {
hdr= atoi(pov->value.str);
} else if (!stricmp(pov->name.str, "option_list")) {
host= GetListOption("host", pov->value.str, "localhost");
user= GetListOption("user", pov->value.str, "root");
// Default value db can come from the DBNAME=xxx option. // Default value db can come from the DBNAME=xxx option.
db= GetListOption("database", pov->value.str, db); db= GetListOption(g,"database", topt->oplist, db);
pwd= GetListOption("password", pov->value.str); pwd= GetListOption(g,"password", topt->oplist);
prt= GetListOption("port", pov->value.str); prt= GetListOption(g,"port", topt->oplist);
port= (prt) ? atoi(prt) : MYSQL_PORT; port= (prt) ? atoi(prt) : MYSQL_PORT;
#if defined(WIN32) #if defined(WIN32)
nsp= GetListOption("namespace", pov->value.str); nsp= GetListOption(g,"namespace", topt->oplist);
cls= GetListOption("class", pov->value.str); cls= GetListOption(g,"class", topt->oplist);
#endif // WIN32 #endif // WIN32
mxr= atoi(GetListOption("maxerr", pov->value.str, "0")); mxr= atoi(GetListOption(g,"maxerr", topt->oplist, "0"));
} // endelse option_list } // endelse option_list
end= pov;
} // endfor pov
if (!db) if (!db)
db= thd->db; // Default value db= thd->db; // Default value
...@@ -3759,14 +3375,11 @@ bool ha_connect::pre_create(THD *thd, HA_CREATE_INFO *create_info, ...@@ -3759,14 +3375,11 @@ bool ha_connect::pre_create(THD *thd, HA_CREATE_INFO *create_info,
strcpy(g->Message, "No table_type. Was set to DOS"); strcpy(g->Message, "No table_type. Was set to DOS");
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0, g->Message); push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0, g->Message);
ttp= TAB_DOS; ttp= TAB_DOS;
typn= "DOS"; topt->type= "DOS";
name= thd->make_lex_string(NULL, "table_type", 10, true);
val= thd->make_lex_string(NULL, typn, strlen(typn), true);
pov= new(mem) engine_option_value(*name, *val, false, start, &end);
} else if (ttp == TAB_NIY) { } else if (ttp == TAB_NIY) {
sprintf(g->Message, "Unsupported table type %s", typn); sprintf(g->Message, "Unsupported table type %s", topt->type);
my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0)); my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
return true; return HA_ERR_INTERNAL_ERROR;
} // endif ttp } // endif ttp
if (!tab && !(fnc & (FNC_TABLE | FNC_COL))) if (!tab && !(fnc & (FNC_TABLE | FNC_COL)))
...@@ -3777,7 +3390,7 @@ bool ha_connect::pre_create(THD *thd, HA_CREATE_INFO *create_info, ...@@ -3777,7 +3390,7 @@ bool ha_connect::pre_create(THD *thd, HA_CREATE_INFO *create_info,
case TAB_ODBC: case TAB_ODBC:
if (!(dsn= create_info->connect_string.str) if (!(dsn= create_info->connect_string.str)
&& !(fnc & (FNC_DSN | FNC_DRIVER))) && !(fnc & (FNC_DSN | FNC_DRIVER)))
sprintf(g->Message, "Missing %s connection string", typn); sprintf(g->Message, "Missing %s connection string", topt->type);
else else
ok= true; ok= true;
...@@ -3789,7 +3402,7 @@ bool ha_connect::pre_create(THD *thd, HA_CREATE_INFO *create_info, ...@@ -3789,7 +3402,7 @@ bool ha_connect::pre_create(THD *thd, HA_CREATE_INFO *create_info,
// Passthru // Passthru
case TAB_CSV: case TAB_CSV:
if (!fn && fnc != FNC_NO) if (!fn && fnc != FNC_NO)
sprintf(g->Message, "Missing %s file name", typn); sprintf(g->Message, "Missing %s file name", topt->type);
else else
ok= true; ok= true;
...@@ -3807,16 +3420,16 @@ bool ha_connect::pre_create(THD *thd, HA_CREATE_INFO *create_info, ...@@ -3807,16 +3420,16 @@ bool ha_connect::pre_create(THD *thd, HA_CREATE_INFO *create_info,
strncpy(dsn, create_info->connect_string.str, strncpy(dsn, create_info->connect_string.str,
create_info->connect_string.length); create_info->connect_string.length);
dsn[create_info->connect_string.length] = 0; dsn[create_info->connect_string.length] = 0;
mydef->Name= (char*)create_info->alias; mydef->SetName(create_info->alias);
mydef->Cat= cat; mydef->SetCat(cat);
if (!mydef->ParseURL(g, dsn)) { if (!mydef->ParseURL(g, dsn)) {
host= mydef->Hostname; host= mydef->GetHostname();
user= mydef->Username; user= mydef->GetUsername();
pwd= mydef->Password; pwd= mydef->GetPassword();
db= mydef->Database; db= mydef->GetDatabase();
tab= mydef->Tabname; tab= mydef->GetTabname();
port= mydef->Portnumber; port= mydef->GetPortnumber();
} else } else
ok= false; ok= false;
...@@ -3831,55 +3444,27 @@ bool ha_connect::pre_create(THD *thd, HA_CREATE_INFO *create_info, ...@@ -3831,55 +3444,27 @@ bool ha_connect::pre_create(THD *thd, HA_CREATE_INFO *create_info,
break; break;
#endif // WIN32 #endif // WIN32
default: default:
sprintf(g->Message, "Cannot get column info for table type %s", typn); sprintf(g->Message, "Cannot get column info for table type %s", topt->type);
} // endif ttp } // endif ttp
// Check for supported catalog function // Check for supported catalog function
if (ok && !(supfnc & fnc)) { if (ok && !(supfnc & fnc)) {
sprintf(g->Message, "Unsupported catalog function %s for table type %s", sprintf(g->Message, "Unsupported catalog function %s for table type %s",
fncn, typn); fncn, topt->type);
ok= false; ok= false;
} // endif supfnc } // endif supfnc
// Test whether columns must be specified
if (alter_info->create_list.elements) {
if (g->Createas) {
// This table is created AS SELECT
// The sourcetable FLAG values have been passed to the created
// table columns but they must be removed to get default offsets.
List_iterator<Create_field> it(alter_info->create_list);
Create_field *field;
engine_option_value *vop, *pop;
while ((field= it++))
for (pop= NULL, vop= field->option_list; vop; vop= vop->next)
if (!stricmp(vop->name.str, "FLAG")) {
if (pop)
pop->next= vop->next;
else
field->option_list= vop->next;
break;
} else
pop= vop;
g->Createas= 0;
} // endif Createas
return false;
} // endif elements
if (ok) { if (ok) {
char *length, *decimals, *cnm, *rem; char *cnm, *rem;
int i, len, dec, typ; int i, len, dec, typ;
enum_field_types type; const char *type;
PDBUSER dup= PlgGetUser(g); PDBUSER dup= PlgGetUser(g);
PCATLG cat= (dup) ? dup->Catalog : NULL; PCATLG cat= (dup) ? dup->Catalog : NULL;
if (cat) if (cat)
cat->SetDataPath(g, thd->db); cat->SetDataPath(g, thd->db);
else else
return true; // Should never happen return HA_ERR_INTERNAL_ERROR; // Should never happen
switch (ttp) { switch (ttp) {
case TAB_DBF: case TAB_DBF:
...@@ -3922,38 +3507,31 @@ bool ha_connect::pre_create(THD *thd, HA_CREATE_INFO *create_info, ...@@ -3922,38 +3507,31 @@ bool ha_connect::pre_create(THD *thd, HA_CREATE_INFO *create_info,
break; break;
#endif // WIN32 #endif // WIN32
default: default:
strcpy(g->Message, "System error in pre_create"); strcpy(g->Message, "System error during assisted discovery");
break; break;
} // endswitch ttp } // endswitch ttp
if (!qrp) { if (!qrp) {
my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0)); my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
return true; return HA_ERR_INTERNAL_ERROR;
} // endif qrp } // endif qrp
if (fnc != FNC_NO) { if (fnc != FNC_NO) {
// Catalog table // Catalog table
for (crp=qrp->Colresp; !b && crp; crp= crp->Next) { for (crp=qrp->Colresp; !b && crp; crp= crp->Next) {
cnm= encode(g, crp->Name); cnm= encode(g, crp->Name);
name= thd->make_lex_string(NULL, cnm, strlen(cnm), true); type= PLGtoMYSQLtype(crp->Type, dbf);
type= PLGtoMYSQL(crp->Type, dbf);
len= crp->Length; len= crp->Length;
length= (char*)PlugSubAlloc(g, NULL, 8);
sprintf(length, "%d", len);
decimals= NULL;
comment= thd->make_lex_string(NULL, "", 0, true);
// Now add the field // Now add the field
b= add_fields(thd, alt_info, name, type, length, decimals, if (add_field(&sql, cnm, type, len, 0, NOT_NULL_FLAG, 0))
NOT_NULL_FLAG, comment, NULL, NULL, NULL); b= HA_ERR_OUT_OF_MEM;
} // endfor crp } // endfor crp
} else // Not a catalog table } else // Not a catalog table
for (i= 0; !b && i < qrp->Nblin; i++) { for (i= 0; !b && i < qrp->Nblin; i++) {
rem= ""; rem= NULL;
typ= len= dec= 0; typ= len= dec= 0;
length= "";
decimals= NULL;
tm= NOT_NULL_FLAG; tm= NOT_NULL_FLAG;
cs= NULL; cs= NULL;
...@@ -3961,7 +3539,6 @@ bool ha_connect::pre_create(THD *thd, HA_CREATE_INFO *create_info, ...@@ -3961,7 +3539,6 @@ bool ha_connect::pre_create(THD *thd, HA_CREATE_INFO *create_info,
switch (crp->Fld) { switch (crp->Fld) {
case FLD_NAME: case FLD_NAME:
cnm= encode(g, crp->Kdata->GetCharValue(i)); cnm= encode(g, crp->Kdata->GetCharValue(i));
name= thd->make_lex_string(NULL, cnm, strlen(cnm), true);
break; break;
case FLD_TYPE: case FLD_TYPE:
typ= crp->Kdata->GetIntValue(i); typ= crp->Kdata->GetIntValue(i);
...@@ -3970,12 +3547,7 @@ bool ha_connect::pre_create(THD *thd, HA_CREATE_INFO *create_info, ...@@ -3970,12 +3547,7 @@ bool ha_connect::pre_create(THD *thd, HA_CREATE_INFO *create_info,
len= crp->Kdata->GetIntValue(i); len= crp->Kdata->GetIntValue(i);
break; break;
case FLD_SCALE: case FLD_SCALE:
if ((dec= crp->Kdata->GetIntValue(i))) { dec= crp->Kdata->GetIntValue(i);
decimals= (char*)PlugSubAlloc(g, NULL, 8);
sprintf(decimals, "%d", dec);
} else
decimals= NULL;
break; break;
case FLD_NULL: case FLD_NULL:
if (crp->Kdata->GetIntValue(i)) if (crp->Kdata->GetIntValue(i))
...@@ -4003,7 +3575,7 @@ bool ha_connect::pre_create(THD *thd, HA_CREATE_INFO *create_info, ...@@ -4003,7 +3575,7 @@ bool ha_connect::pre_create(THD *thd, HA_CREATE_INFO *create_info,
if (!(plgtyp= TranslateSQLType(typ, dec, len))) { if (!(plgtyp= TranslateSQLType(typ, dec, len))) {
sprintf(g->Message, "Unsupported SQL type %d", typ); sprintf(g->Message, "Unsupported SQL type %d", typ);
my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0)); my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
return true; return HA_ERR_INTERNAL_ERROR;
} else } else
typ= plgtyp; typ= plgtyp;
...@@ -4014,24 +3586,66 @@ bool ha_connect::pre_create(THD *thd, HA_CREATE_INFO *create_info, ...@@ -4014,24 +3586,66 @@ bool ha_connect::pre_create(THD *thd, HA_CREATE_INFO *create_info,
} // endif ttp } // endif ttp
#endif // ODBC_SUPPORT #endif // ODBC_SUPPORT
// Make the arguments as required by add_fields type= PLGtoMYSQLtype(typ, true);
type= PLGtoMYSQL(typ, true); if (typ == TYPE_DATE)
length= (char*)PlugSubAlloc(g, NULL, 8); len= 0;
sprintf(length, "%d", len); if (add_field(&sql, cnm, type, len, dec, tm, rem))
comment= thd->make_lex_string(NULL, rem, strlen(rem), true); b= HA_ERR_OUT_OF_MEM;
// Now add the field
b= add_fields(thd, alt_info, name, type, length, decimals,
tm, comment, cs, NULL, NULL);
} // endfor i } // endfor i
sql.length(sql.length()-1); // remove the trailing comma
sql.append(')');
for (ha_create_table_option *opt= connect_table_option_list;
opt->name; opt++) {
ulonglong vull;
const char *vstr;
bool oom= false;
switch (opt->type) {
case HA_OPTION_TYPE_ULL:
vull= *(ulonglong*)(((char*)topt) + opt->offset);
if (vull != opt->def_value) {
oom|= sql.append(' ');
oom|= sql.append(opt->name);
oom|= sql.append('=');
oom|= sql.append_ulonglong(vull);
}
break;
case HA_OPTION_TYPE_STRING:
vstr= *(char**)(((char*)topt) + opt->offset);
if (vstr) {
oom|= sql.append(' ');
oom|= sql.append(opt->name);
oom|= sql.append("='");
oom|= sql.append_for_single_quote(vstr, strlen(vstr));
oom|= sql.append('\'');
}
break;
case HA_OPTION_TYPE_BOOL:
vull= *(bool*)(((char*)topt) + opt->offset);
if (vull != opt->def_value) {
oom|= sql.append(' ');
oom|= sql.append(opt->name);
oom|= sql.append('=');
oom|= sql.append(vull ? "ON" : "OFF");
}
break;
default: // no enums here, good :)
break;
}
if (oom)
b= HA_ERR_OUT_OF_MEM;
}
if (!b)
b= table_s->init_from_sql_statement_string(thd, true,
sql.ptr(), sql.length());
return b; return b;
} // endif ok } // endif ok
my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0)); my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
return true; return HA_ERR_INTERNAL_ERROR;
} // end of pre_create } // end of pre_create
#endif // MARIADB
/** /**
@brief @brief
...@@ -4067,7 +3681,8 @@ int ha_connect::create(const char *name, TABLE *table_arg, ...@@ -4067,7 +3681,8 @@ int ha_connect::create(const char *name, TABLE *table_arg,
Field *fp; Field *fp;
TABTYPE type; TABTYPE type;
TABLE *st= table; // Probably unuseful TABLE *st= table; // Probably unuseful
PGLOBAL g= GetPlug(table_arg->in_use); xp= GetUser(ha_thd(), xp);
PGLOBAL g= xp->g;
DBUG_ENTER("ha_connect::create"); DBUG_ENTER("ha_connect::create");
PTOS options= GetTableOptionStruct(table_arg); PTOS options= GetTableOptionStruct(table_arg);
...@@ -4076,7 +3691,7 @@ int ha_connect::create(const char *name, TABLE *table_arg, ...@@ -4076,7 +3691,7 @@ int ha_connect::create(const char *name, TABLE *table_arg,
DBUG_ASSERT(options); DBUG_ASSERT(options);
type= GetTypeID(options->type); type= GetTypeID(options->type);
if (check_privileges(current_thd, options)) if (check_privileges(ha_thd(), options))
DBUG_RETURN(HA_ERR_INTERNAL_ERROR); DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
if (options->data_charset) { if (options->data_charset) {
...@@ -4105,7 +3720,7 @@ int ha_connect::create(const char *name, TABLE *table_arg, ...@@ -4105,7 +3720,7 @@ int ha_connect::create(const char *name, TABLE *table_arg,
if (type == TAB_XML) { if (type == TAB_XML) {
bool dom; // True: MS-DOM, False libxml2 bool dom; // True: MS-DOM, False libxml2
char *xsup= GetListOption("Xmlsup", options->oplist, "*"); char *xsup= GetListOption(g, "Xmlsup", options->oplist, "*");
// Note that if no support is specified, the default is MS-DOM // Note that if no support is specified, the default is MS-DOM
// on Windows and libxml2 otherwise // on Windows and libxml2 otherwise
...@@ -4151,10 +3766,8 @@ int ha_connect::create(const char *name, TABLE *table_arg, ...@@ -4151,10 +3766,8 @@ int ha_connect::create(const char *name, TABLE *table_arg,
for (field= table_arg->field; *field; field++) { for (field= table_arg->field; *field; field++) {
fp= *field; fp= *field;
#if defined(MARIADB)
if (fp->vcol_info && !fp->stored_in_db) if (fp->vcol_info && !fp->stored_in_db)
continue; // This is a virtual column continue; // This is a virtual column
#endif // MARIADB
if (fp->flags & AUTO_INCREMENT_FLAG) { if (fp->flags & AUTO_INCREMENT_FLAG) {
strcpy(g->Message, "Auto_increment is not supported yet"); strcpy(g->Message, "Auto_increment is not supported yet");
...@@ -4378,6 +3991,9 @@ bool ha_connect::check_if_incompatible_data(HA_CREATE_INFO *info, ...@@ -4378,6 +3991,9 @@ bool ha_connect::check_if_incompatible_data(HA_CREATE_INFO *info,
} // endif sepindex } // endif sepindex
#endif // 0 #endif // 0
if (oldopt->type != newopt->type)
DBUG_RETURN(COMPATIBLE_DATA_NO);
if (newopt->filename) if (newopt->filename)
DBUG_RETURN(COMPATIBLE_DATA_NO); DBUG_RETURN(COMPATIBLE_DATA_NO);
...@@ -4390,28 +4006,6 @@ bool ha_connect::check_if_incompatible_data(HA_CREATE_INFO *info, ...@@ -4390,28 +4006,6 @@ bool ha_connect::check_if_incompatible_data(HA_CREATE_INFO *info,
struct st_mysql_storage_engine connect_storage_engine= struct st_mysql_storage_engine connect_storage_engine=
{ MYSQL_HANDLERTON_INTERFACE_VERSION }; { MYSQL_HANDLERTON_INTERFACE_VERSION };
struct st_mysql_daemon unusable_connect=
{ MYSQL_DAEMON_INTERFACE_VERSION };
mysql_declare_plugin(connect)
{
MYSQL_STORAGE_ENGINE_PLUGIN,
&connect_storage_engine,
"CONNECT",
"Olivier Bertrand",
"Direct access to external data, including many file formats",
PLUGIN_LICENSE_GPL,
connect_init_func, /* Plugin Init */
connect_done_func, /* Plugin Deinit */
0x0001 /* 0.1 */,
NULL, /* status variables */
NULL, /* system variables */
NULL, /* config options */
0, /* flags */
}
mysql_declare_plugin_end;
#if defined(MARIADB)
maria_declare_plugin(connect) maria_declare_plugin(connect)
{ {
MYSQL_STORAGE_ENGINE_PLUGIN, MYSQL_STORAGE_ENGINE_PLUGIN,
...@@ -4427,21 +4021,5 @@ maria_declare_plugin(connect) ...@@ -4427,21 +4021,5 @@ maria_declare_plugin(connect)
NULL, /* system variables */ NULL, /* system variables */
"0.1", /* string version */ "0.1", /* string version */
MariaDB_PLUGIN_MATURITY_EXPERIMENTAL /* maturity */ MariaDB_PLUGIN_MATURITY_EXPERIMENTAL /* maturity */
},
{
MYSQL_DAEMON_PLUGIN,
&unusable_connect,
"UNUSABLE",
"Olivier Bertrand",
"Unusable Daemon",
PLUGIN_LICENSE_PROPRIETARY,
NULL, /* Plugin Init */
NULL, /* Plugin Deinit */
0x0101, /* version number (1.1) */
NULL, /* status variables */
NULL, /* system variables */
"1.01.00.000" , /* version, as a string */
MariaDB_PLUGIN_MATURITY_EXPERIMENTAL /* maturity */
} }
maria_declare_plugin_end; maria_declare_plugin_end;
#endif // MARIADB
...@@ -62,6 +62,8 @@ typedef class user_connect *PCONNECT; ...@@ -62,6 +62,8 @@ typedef class user_connect *PCONNECT;
typedef struct ha_table_option_struct TOS, *PTOS; typedef struct ha_table_option_struct TOS, *PTOS;
typedef struct ha_field_option_struct FOS, *PFOS; typedef struct ha_field_option_struct FOS, *PFOS;
extern handlerton *connect_hton;
/** @brief /** @brief
CONNECT_SHARE is a structure that will be shared among all open handlers. CONNECT_SHARE is a structure that will be shared among all open handlers.
This example implements the minimum of what you will probably need. This example implements the minimum of what you will probably need.
...@@ -71,10 +73,6 @@ typedef struct st_connect_share { ...@@ -71,10 +73,6 @@ typedef struct st_connect_share {
uint table_name_length, use_count; uint table_name_length, use_count;
mysql_mutex_t mutex; mysql_mutex_t mutex;
THR_LOCK lock; THR_LOCK lock;
#if !defined(MARIADB)
PTOS table_options;
PFOS field_options;
#endif // !MARIADB
} CONNECT_SHARE; } CONNECT_SHARE;
typedef class ha_connect *PHC; typedef class ha_connect *PHC;
...@@ -111,8 +109,6 @@ class ha_connect: public handler ...@@ -111,8 +109,6 @@ class ha_connect: public handler
TABLE *GetTable(void) {return table;} TABLE *GetTable(void) {return table;}
bool IsSameIndex(PIXDEF xp1, PIXDEF xp2); bool IsSameIndex(PIXDEF xp1, PIXDEF xp2);
PCONNECT GetUser(THD *thd);
PGLOBAL GetPlug(THD *thd);
PTDB GetTDB(PGLOBAL g); PTDB GetTDB(PGLOBAL g);
bool OpenTable(PGLOBAL g, bool del= false); bool OpenTable(PGLOBAL g, bool del= false);
bool IsOpened(void); bool IsOpened(void);
...@@ -148,9 +144,7 @@ class ha_connect: public handler ...@@ -148,9 +144,7 @@ class ha_connect: public handler
return (HA_NO_TRANSACTIONS | HA_REC_NOT_IN_SEQ | HA_HAS_RECORDS | return (HA_NO_TRANSACTIONS | HA_REC_NOT_IN_SEQ | HA_HAS_RECORDS |
HA_NO_AUTO_INCREMENT | HA_NO_PREFIX_CHAR_KEYS | HA_NO_AUTO_INCREMENT | HA_NO_PREFIX_CHAR_KEYS |
HA_NO_COPY_ON_ALTER | HA_NO_COPY_ON_ALTER |
#if defined(MARIADB)
HA_CAN_VIRTUAL_COLUMNS | HA_CAN_VIRTUAL_COLUMNS |
#endif // MARIADB
HA_NULL_IN_KEY | HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE); HA_NULL_IN_KEY | HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE);
} }
...@@ -361,9 +355,6 @@ const char *GetValStr(OPVAL vop, bool neg); ...@@ -361,9 +355,6 @@ const char *GetValStr(OPVAL vop, bool neg);
Called by delete_table and rename_table Called by delete_table and rename_table
*/ */
int delete_or_rename_table(const char *from, const char *to); int delete_or_rename_table(const char *from, const char *to);
#if defined(MARIADB)
bool pre_create(THD *thd, HA_CREATE_INFO *crt_info, void *alt_info);
#endif // MARIADB
int create(const char *name, TABLE *form, int create(const char *name, TABLE *form,
HA_CREATE_INFO *create_info); ///< required HA_CREATE_INFO *create_info); ///< required
bool check_if_incompatible_data(HA_CREATE_INFO *info, bool check_if_incompatible_data(HA_CREATE_INFO *info,
...@@ -375,23 +366,6 @@ const char *GetValStr(OPVAL vop, bool neg); ...@@ -375,23 +366,6 @@ const char *GetValStr(OPVAL vop, bool neg);
protected: protected:
bool check_privileges(THD *thd, PTOS options); bool check_privileges(THD *thd, PTOS options);
char *GetListOption(const char *opname, const char *oplist, const char *def= NULL);
#if defined(MARIADB)
char *encode(PGLOBAL g, char *cnm);
bool add_fields(THD *thd, void *alter_info,
LEX_STRING *field_name,
enum_field_types type,
char *length, char *decimals,
uint type_modifier,
// Item *default_value, Item *on_update_value,
LEX_STRING *comment,
// char *change,
// List<String> *interval_list,
CHARSET_INFO *cs,
// uint uint_geom_type,
void *vcol_info,
engine_option_value *create_options);
#endif // MARIADB
// Members // Members
static ulong num; // Tracable handler number static ulong num; // Tracable handler number
...@@ -409,10 +383,6 @@ const char *GetValStr(OPVAL vop, bool neg); ...@@ -409,10 +383,6 @@ const char *GetValStr(OPVAL vop, bool neg);
bool valid_info; // True if xinfo is valid bool valid_info; // True if xinfo is valid
bool stop; // Used when creating index bool stop; // Used when creating index
int indexing; // Type of indexing for CONNECT int indexing; // Type of indexing for CONNECT
#if !defined(MARIADB)
PTOS table_options;
PFOS field_options;
#endif // !MARIADB
THR_LOCK_DATA lock_data; THR_LOCK_DATA lock_data;
public: public:
......
...@@ -111,6 +111,7 @@ ERROR HY000: Cannot open DATADIR/test/t1.dbf ...@@ -111,6 +111,7 @@ ERROR HY000: Cannot open DATADIR/test/t1.dbf
SHOW WARNINGS; SHOW WARNINGS;
Level Code Message Level Code Message
Error 1105 Cannot open DATADIR/test/t1.dbf Error 1105 Cannot open DATADIR/test/t1.dbf
Error 1030 Got error 122 "Internal (unspecified) error in handler" from storage engine CONNECT
CREATE PROCEDURE test.dbf_field(in fieldno INT, in content BLOB) DETERMINISTIC CREATE PROCEDURE test.dbf_field(in fieldno INT, in content BLOB) DETERMINISTIC
BEGIN BEGIN
SELECT '---'; SELECT '---';
......
...@@ -24,7 +24,7 @@ size DOUBLE(12,0) NOT NULL flag=5 ...@@ -24,7 +24,7 @@ size DOUBLE(12,0) NOT NULL flag=5
) ENGINE=CONNECT TABLE_TYPE=DIR FILE_NAME='*.*'; ) ENGINE=CONNECT TABLE_TYPE=DIR FILE_NAME='*.*';
SELECT fname, ftype, size FROM t1 WHERE size>0; SELECT fname, ftype, size FROM t1 WHERE size>0;
fname ftype size fname ftype size
t1 .frm 8654 t1 .frm 1081
SELECT user(); SELECT user();
user() user()
user@localhost user@localhost
......
...@@ -106,7 +106,7 @@ Table Create Table ...@@ -106,7 +106,7 @@ Table Create Table
t2 CREATE TABLE `t2` ( t2 CREATE TABLE `t2` (
`a` int(11) DEFAULT NULL, `a` int(11) DEFAULT NULL,
`b` varchar(10) DEFAULT NULL `b` varchar(10) DEFAULT NULL
) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`=MYSQL `TABNAME`='t1' `OPTION_LIST`='host=localhost,user=root,port=PORT' ) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`='MYSQL' `TABNAME`='t1' `OPTION_LIST`='host=localhost,user=root,port=PORT'
SELECT * FROM t2; SELECT * FROM t2;
a b a b
NULL NULL NULL NULL
...@@ -175,7 +175,7 @@ SHOW CREATE TABLE t2; ...@@ -175,7 +175,7 @@ SHOW CREATE TABLE t2;
Table Create Table Table Create Table
t2 CREATE TABLE `t2` ( t2 CREATE TABLE `t2` (
`a` smallint(6) DEFAULT NULL `a` smallint(6) DEFAULT NULL
) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`=MYSQL `TABNAME`='t1' `OPTION_LIST`='host=localhost,user=root,port=PORT' ) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`='MYSQL' `TABNAME`='t1' `OPTION_LIST`='host=localhost,user=root,port=PORT'
SELECT * FROM t2; SELECT * FROM t2;
a a
DROP TABLE t2, t1; DROP TABLE t2, t1;
...@@ -190,7 +190,7 @@ SHOW CREATE TABLE t2; ...@@ -190,7 +190,7 @@ SHOW CREATE TABLE t2;
Table Create Table Table Create Table
t2 CREATE TABLE `t2` ( t2 CREATE TABLE `t2` (
`a` int(9) DEFAULT NULL `a` int(9) DEFAULT NULL
) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`=MYSQL `TABNAME`='t1' `OPTION_LIST`='host=localhost,user=root,port=PORT' ) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`='MYSQL' `TABNAME`='t1' `OPTION_LIST`='host=localhost,user=root,port=PORT'
SELECT * FROM t2; SELECT * FROM t2;
a a
DROP TABLE t2, t1; DROP TABLE t2, t1;
...@@ -205,7 +205,7 @@ SHOW CREATE TABLE t2; ...@@ -205,7 +205,7 @@ SHOW CREATE TABLE t2;
Table Create Table Table Create Table
t2 CREATE TABLE `t2` ( t2 CREATE TABLE `t2` (
`a` int(11) DEFAULT NULL `a` int(11) DEFAULT NULL
) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`=MYSQL `TABNAME`='t1' `OPTION_LIST`='host=localhost,user=root,port=PORT' ) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`='MYSQL' `TABNAME`='t1' `OPTION_LIST`='host=localhost,user=root,port=PORT'
SELECT * FROM t2; SELECT * FROM t2;
a a
DROP TABLE t2, t1; DROP TABLE t2, t1;
...@@ -220,7 +220,7 @@ SHOW CREATE TABLE t2; ...@@ -220,7 +220,7 @@ SHOW CREATE TABLE t2;
Table Create Table Table Create Table
t2 CREATE TABLE `t2` ( t2 CREATE TABLE `t2` (
`a` bigint(20) DEFAULT NULL `a` bigint(20) DEFAULT NULL
) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`=MYSQL `TABNAME`='t1' `OPTION_LIST`='host=localhost,user=root,port=PORT' ) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`='MYSQL' `TABNAME`='t1' `OPTION_LIST`='host=localhost,user=root,port=PORT'
SELECT * FROM t2; SELECT * FROM t2;
a a
DROP TABLE t2, t1; DROP TABLE t2, t1;
...@@ -238,7 +238,7 @@ SHOW CREATE TABLE t2; ...@@ -238,7 +238,7 @@ SHOW CREATE TABLE t2;
Table Create Table Table Create Table
t2 CREATE TABLE `t2` ( t2 CREATE TABLE `t2` (
`a` varchar(10) DEFAULT NULL `a` varchar(10) DEFAULT NULL
) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`=MYSQL `TABNAME`='t1' `OPTION_LIST`='host=localhost,user=root,port=PORT' ) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`='MYSQL' `TABNAME`='t1' `OPTION_LIST`='host=localhost,user=root,port=PORT'
SELECT * FROM t2; SELECT * FROM t2;
a a
DROP TABLE t2, t1; DROP TABLE t2, t1;
...@@ -253,7 +253,7 @@ SHOW CREATE TABLE t2; ...@@ -253,7 +253,7 @@ SHOW CREATE TABLE t2;
Table Create Table Table Create Table
t2 CREATE TABLE `t2` ( t2 CREATE TABLE `t2` (
`a` varchar(10) DEFAULT NULL `a` varchar(10) DEFAULT NULL
) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`=MYSQL `TABNAME`='t1' `OPTION_LIST`='host=localhost,user=root,port=PORT' ) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`='MYSQL' `TABNAME`='t1' `OPTION_LIST`='host=localhost,user=root,port=PORT'
SELECT * FROM t2; SELECT * FROM t2;
a a
DROP TABLE t2, t1; DROP TABLE t2, t1;
...@@ -274,7 +274,7 @@ SHOW CREATE TABLE t2; ...@@ -274,7 +274,7 @@ SHOW CREATE TABLE t2;
Table Create Table Table Create Table
t2 CREATE TABLE `t2` ( t2 CREATE TABLE `t2` (
`a` date DEFAULT NULL `a` date DEFAULT NULL
) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`=MYSQL `TABNAME`='t1' `OPTION_LIST`='host=localhost,user=root,port=PORT' ) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`='MYSQL' `TABNAME`='t1' `OPTION_LIST`='host=localhost,user=root,port=PORT'
SELECT * FROM t2; SELECT * FROM t2;
a a
DROP TABLE t2, t1; DROP TABLE t2, t1;
...@@ -4,9 +4,6 @@ ...@@ -4,9 +4,6 @@
CREATE TABLE t1 ( CREATE TABLE t1 (
a INT NOT NULL, a INT NOT NULL,
message CHAR(10)) ENGINE=connect; message CHAR(10)) ENGINE=connect;
Warnings:
Warning 1105 No table_type. Was set to DOS
Warning 1105 No file name. Table will use t1.dos
INSERT INTO t1 VALUES (1,'Testing'),(2,'dos table'),(3,'t1'); INSERT INTO t1 VALUES (1,'Testing'),(2,'dos table'),(3,'t1');
SELECT * FROM t1; SELECT * FROM t1;
a message a message
......
...@@ -59,9 +59,6 @@ END// ...@@ -59,9 +59,6 @@ END//
# Testing DOS table changes # Testing DOS table changes
# #
CREATE TABLE t1 ENGINE=connect AS SELECT * FROM employee; CREATE TABLE t1 ENGINE=connect AS SELECT * FROM employee;
Warnings:
Warning 1105 No table_type. Was set to DOS
Warning 1105 No file name. Table will use t1.dos
CALL test.tst_up(); CALL test.tst_up();
serialno name sex title manager department secretary salary serialno name sex title manager department secretary salary
74200 BANCROFT 2 SALESMAN 70012 0318 24888 9600.00 74200 BANCROFT 2 SALESMAN 70012 0318 24888 9600.00
...@@ -157,9 +154,6 @@ serialno name sex title manager department secretary salary ...@@ -157,9 +154,6 @@ serialno name sex title manager department secretary salary
# Testing DOS table changes # Testing DOS table changes
# #
CREATE TABLE t1 ENGINE=connect mapped=yes AS SELECT * FROM employee; CREATE TABLE t1 ENGINE=connect mapped=yes AS SELECT * FROM employee;
Warnings:
Warning 1105 No table_type. Was set to DOS
Warning 1105 No file name. Table will use t1.dos
CALL test.tst_up(); CALL test.tst_up();
serialno name sex title manager department secretary salary serialno name sex title manager department secretary salary
74200 BANCROFT 2 SALESMAN 70012 0318 24888 9600.00 74200 BANCROFT 2 SALESMAN 70012 0318 24888 9600.00
......
...@@ -94,6 +94,25 @@ enum enum_field_types PLGtoMYSQL(int type, bool dbf) ...@@ -94,6 +94,25 @@ enum enum_field_types PLGtoMYSQL(int type, bool dbf)
return mytype; return mytype;
} // end of PLGtoMYSQL } // end of PLGtoMYSQL
/************************************************************************/
/* Convert from PlugDB type to MySQL type name */
/************************************************************************/
const char *PLGtoMYSQLtype(int type, bool dbf)
{
switch (type) {
case TYPE_INT: return "INT";
case TYPE_SHORT: return "SMALLINT";
case TYPE_FLOAT: return "DOUBLE";
case TYPE_DATE: return dbf ? "DATE" : "DATETIME";
case TYPE_STRING: return "VARCHAR";
case TYPE_BIGINT: return "BIGINT";
case TYPE_TINY: return "TINYINT";
default: return "CHAR(0)";
} // endswitch mytype
return "CHAR(0)";
} // end of PLGtoMYSQL
/************************************************************************/ /************************************************************************/
/* Convert from MySQL type to PlugDB type number */ /* Convert from MySQL type to PlugDB type number */
/************************************************************************/ /************************************************************************/
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
/* Prototypes of Functions used externally. */ /* Prototypes of Functions used externally. */
/***********************************************************************/ /***********************************************************************/
enum enum_field_types PLGtoMYSQL(int type, bool dbf); enum enum_field_types PLGtoMYSQL(int type, bool dbf);
const char *PLGtoMYSQLtype(int type, bool dbf);
int MYSQLtoPLG(char *typname); int MYSQLtoPLG(char *typname);
int MYSQLtoPLG(int mytype); int MYSQLtoPLG(int mytype);
char *MyDateFmt(int mytype); char *MyDateFmt(int mytype);
......
...@@ -34,6 +34,8 @@ class DllExport RELDEF : public BLOCK { // Relation definition block ...@@ -34,6 +34,8 @@ class DllExport RELDEF : public BLOCK { // Relation definition block
PCATLG GetCat(void) {return Cat;} PCATLG GetCat(void) {return Cat;}
virtual const char *GetType(void) = 0; virtual const char *GetType(void) = 0;
virtual AMT GetDefType(void) = 0; virtual AMT GetDefType(void) = 0;
void SetName(const char *str) { Name=(char*)str; }
void SetCat(PCATLG cat) { Cat=cat; }
// Methods // Methods
virtual bool DeleteTableFile(PGLOBAL g) {return true;} virtual bool DeleteTableFile(PGLOBAL g) {return true;}
......
...@@ -75,7 +75,7 @@ extern "C" int trace; ...@@ -75,7 +75,7 @@ extern "C" int trace;
/* of types (TYPE_STRING < TYPE_FLOAT < TYPE_INT) (1 < 2 < 7). */ /* of types (TYPE_STRING < TYPE_FLOAT < TYPE_INT) (1 < 2 < 7). */
/* If these values are changed, this will have to be revisited. */ /* If these values are changed, this will have to be revisited. */
/***********************************************************************/ /***********************************************************************/
PQRYRES CSVColumns(PGLOBAL g, char *fn, char sep, char q, PQRYRES CSVColumns(PGLOBAL g, const char *fn, char sep, char q,
int hdr, int mxr, bool info) int hdr, int mxr, bool info)
{ {
static int dbtype[] = {DB_CHAR, DB_SHORT, DB_CHAR, static int dbtype[] = {DB_CHAR, DB_SHORT, DB_CHAR,
......
...@@ -14,7 +14,7 @@ typedef class TDBFMT *PTDBFMT; ...@@ -14,7 +14,7 @@ typedef class TDBFMT *PTDBFMT;
/***********************************************************************/ /***********************************************************************/
/* Functions used externally. */ /* Functions used externally. */
/***********************************************************************/ /***********************************************************************/
PQRYRES CSVColumns(PGLOBAL g, char *fn, char sep, char q, PQRYRES CSVColumns(PGLOBAL g, const char *fn, char sep, char q,
int hdr, int mxr, bool info); int hdr, int mxr, bool info);
/***********************************************************************/ /***********************************************************************/
......
...@@ -79,8 +79,6 @@ ...@@ -79,8 +79,6 @@
extern "C" int trace; extern "C" int trace;
int open_table_def(THD *thd, TABLE_SHARE *share, uint db_flags);
/* ---------------------------- Class TBLDEF ---------------------------- */ /* ---------------------------- Class TBLDEF ---------------------------- */
/**************************************************************************/ /**************************************************************************/
...@@ -220,9 +218,8 @@ PCOL TDBTBL::InsertSpecialColumn(PGLOBAL g, PCOL scp) ...@@ -220,9 +218,8 @@ PCOL TDBTBL::InsertSpecialColumn(PGLOBAL g, PCOL scp)
PTDB TDBTBL::GetSubTable(PGLOBAL g, PTBL tblp, PTABLE tabp) PTDB TDBTBL::GetSubTable(PGLOBAL g, PTBL tblp, PTABLE tabp)
{ {
char *db, key[256]; char *db, key[256];
uint k, flags; uint k;
PTDB tdbp = NULL; PTDB tdbp = NULL;
TABLE_LIST table_list;
TABLE_SHARE *s; TABLE_SHARE *s;
PCATLG cat = To_Def->GetCat(); PCATLG cat = To_Def->GetCat();
PHC hc = ((MYCAT*)cat)->GetHandler(); PHC hc = ((MYCAT*)cat)->GetHandler();
...@@ -236,29 +233,17 @@ PTDB TDBTBL::GetSubTable(PGLOBAL g, PTBL tblp, PTABLE tabp) ...@@ -236,29 +233,17 @@ PTDB TDBTBL::GetSubTable(PGLOBAL g, PTBL tblp, PTABLE tabp)
else else
db = (char*)hc->GetDBName(NULL); db = (char*)hc->GetDBName(NULL);
table_list.init_one_table(db, strlen(db), k = sprintf(key, "%s", db) + 1;
tblp->Name, strlen(tblp->Name), k += sprintf(key + k, "%s", tblp->Name);
NULL, TL_IGNORE);
k = sprintf(key, "%s", db);
k += sprintf(key + ++k, "%s", tblp->Name);
key[++k] = 0; key[++k] = 0;
if (!(s = alloc_table_share(&table_list, key, ++k))) { if (!(s = alloc_table_share(db, tblp->Name, key, ++k))) {
strcpy(g->Message, "Error allocating share\n"); strcpy(g->Message, "Error allocating share\n");
return NULL; return NULL;
} // endif s } // endif s
// 1 8 16 if (!open_table_def(thd, s)) {
//flags = READ_ALL | DONT_OPEN_TABLES | DONT_OPEN_MASTER_REG; if (plugin_data(s->db_plugin, handlerton*) != connect_hton) {
//flags = 25;
flags = 24;
if (!open_table_def(thd, s, flags)) {
#ifdef DBUG_OFF
if (stricmp(s->db_plugin->name.str, "connect")) {
#else
if (stricmp((*s->db_plugin)->name.str, "connect")) {
#endif
#if defined(MYSQL_SUPPORT) #if defined(MYSQL_SUPPORT)
// Access sub-table via MySQL API // Access sub-table via MySQL API
if (!(tdbp= cat->GetTable(g, tabp, MODE_READ, "MYSQL"))) { if (!(tdbp= cat->GetTable(g, tabp, MODE_READ, "MYSQL"))) {
......
...@@ -92,7 +92,7 @@ user_connect::~user_connect() ...@@ -92,7 +92,7 @@ user_connect::~user_connect()
/****************************************************************************/ /****************************************************************************/
/* Initialization. */ /* Initialization. */
/****************************************************************************/ /****************************************************************************/
bool user_connect::user_init(PHC hc) bool user_connect::user_init()
{ {
// Initialize Plug-like environment // Initialize Plug-like environment
PACTIVITY ap= NULL; PACTIVITY ap= NULL;
...@@ -113,7 +113,7 @@ bool user_connect::user_init(PHC hc) ...@@ -113,7 +113,7 @@ bool user_connect::user_init(PHC hc)
return true; return true;
} // endif g-> } // endif g->
dup->Catalog= new MYCAT(hc); dup->Catalog= new MYCAT(NULL);
ap= new ACTIVITY; ap= new ACTIVITY;
memset(ap, 0, sizeof(ACTIVITY)); memset(ap, 0, sizeof(ACTIVITY));
...@@ -132,6 +132,13 @@ bool user_connect::user_init(PHC hc) ...@@ -132,6 +132,13 @@ bool user_connect::user_init(PHC hc)
} // end of user_init } // end of user_init
void user_connect::SetHandler(ha_connect *hc)
{
PDBUSER dup= (PDBUSER)g->Activityp->Aptr;
MYCAT *mc= (MYCAT*)dup->Catalog;
mc->SetHandler(hc);
}
/****************************************************************************/ /****************************************************************************/
/* Check whether we begin a new query and if so cleanup the previous one. */ /* Check whether we begin a new query and if so cleanup the previous one. */
/****************************************************************************/ /****************************************************************************/
......
...@@ -57,15 +57,15 @@ class user_connect ...@@ -57,15 +57,15 @@ class user_connect
virtual ~user_connect(); virtual ~user_connect();
// Implementation // Implementation
bool user_init(ha_connect *hc); bool user_init();
void SetHandler(ha_connect *hc);
bool CheckCleanup(void); bool CheckCleanup(void);
bool CheckQueryID(void) {return thdp->query_id > last_query_id;} bool CheckQueryID(void) {return thdp->query_id > last_query_id;}
bool CheckQuery(query_id_t vid) {return last_query_id > vid;} bool CheckQuery(query_id_t vid) {return last_query_id > vid;}
protected:
// Members // Members
static PCONNECT to_users; // To the chain of users
THD *thdp; // To the user thread THD *thdp; // To the user thread
static PCONNECT to_users; // To the chain of users
PCONNECT next; // Next user in chain PCONNECT next; // Next user in chain
PCONNECT previous; // Previous user in chain PCONNECT previous; // Previous user in chain
PGLOBAL g; // The common handle to CONNECT PGLOBAL g; // The common handle to CONNECT
......
...@@ -675,7 +675,7 @@ void *CHRBLK::GetValPtrEx(int n) ...@@ -675,7 +675,7 @@ void *CHRBLK::GetValPtrEx(int n)
memcpy(Valp, Chrp + n * Long, Long); memcpy(Valp, Chrp + n * Long, Long);
if (IsNull(n)) if (IsNull(n))
return ""; return const_cast<char *>("");
if (Blanks) { if (Blanks) {
// The (fast) way this is done works only for blocks such // The (fast) way this is done works only for blocks such
...@@ -857,7 +857,7 @@ void *STRBLK::GetValPtr(int n) ...@@ -857,7 +857,7 @@ void *STRBLK::GetValPtr(int n)
void *STRBLK::GetValPtrEx(int n) void *STRBLK::GetValPtrEx(int n)
{ {
ChkIndx(n); ChkIndx(n);
return (Strp[n]) ? Strp[n] : ""; return (Strp[n]) ? Strp[n] : const_cast<char*>("");
} // end of GetValPtrEx } // end of GetValPtrEx
/***********************************************************************/ /***********************************************************************/
......
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