Commit 174fc2a8 authored by Andrew McDonnell's avatar Andrew McDonnell

Fix remaining build problems caused by merge from lp:maria/10.0

parent 6d1d8847
...@@ -202,6 +202,14 @@ DROP TABLE IF EXISTS oqtable; ...@@ -202,6 +202,14 @@ DROP TABLE IF EXISTS oqtable;
CREATE TABLE oqtable ( latch varchar(32) NULL NULL, origid BIGINT UNSIGNED NULL, destid BIGINT UNSIGNED NULL, weight DOUBLE NULL, seq BIGINT UNSIGNED NULL, linkid BIGINT UNSIGNED NULL, KEY (latch, origid, destid) USING HASH, KEY (latch, destid, origid) USING HASH ) ENGINE=OQGRAPH, DATA_TABLE='backing',ORIGID='id',DESTID='id2',WEIGHT='weight'; CREATE TABLE oqtable ( latch varchar(32) NULL NULL, origid BIGINT UNSIGNED NULL, destid BIGINT UNSIGNED NULL, weight DOUBLE NULL, seq BIGINT UNSIGNED NULL, linkid BIGINT UNSIGNED NULL, KEY (latch, origid, destid) USING HASH, KEY (latch, destid, origid) USING HASH ) ENGINE=OQGRAPH, DATA_TABLE='backing',ORIGID='id',DESTID='id2',WEIGHT='weight';
DESCRIBE oqtable; DESCRIBE oqtable;
#-- Expect an error if we attempt to use a view as the backing store
#-- 'VIEWs are not supported for an OQGRAPH backing store.'
#-- TODO
#-- TODO - what happens if we make two tables with the same backing store?
#-- TODO - what happens if data_table is a TEMPORARY table?
# cleanup # cleanup
--disable_warnings --disable_warnings
DROP TABLE IF EXISTS oqtable; DROP TABLE IF EXISTS oqtable;
......
...@@ -53,7 +53,7 @@ ...@@ -53,7 +53,7 @@
#include "my_dbug.h" #include "my_dbug.h"
// Uncomment this for extra debug, but expect a performance hit in large queries // Uncomment this for extra debug, but expect a performance hit in large queries
//#define VERBOSE_DEBUG #define VERBOSE_DEBUG
#ifdef VERBOSE_DEBUG #ifdef VERBOSE_DEBUG
#else #else
#undef DBUG_PRINT #undef DBUG_PRINT
...@@ -426,6 +426,10 @@ int ha_oqgraph::oqgraph_check_table_structure (TABLE *table_arg) ...@@ -426,6 +426,10 @@ int ha_oqgraph::oqgraph_check_table_structure (TABLE *table_arg)
ha_oqgraph::ha_oqgraph(handlerton *hton, TABLE_SHARE *table_arg) ha_oqgraph::ha_oqgraph(handlerton *hton, TABLE_SHARE *table_arg)
: handler(hton, table_arg) : handler(hton, table_arg)
, have_table_share(false)
, origid(NULL)
, destid(NULL)
, weight(NULL)
, graph_share(0) , graph_share(0)
, graph(0) , graph(0)
, error_message("", 0, &my_charset_latin1) , error_message("", 0, &my_charset_latin1)
...@@ -478,10 +482,23 @@ void ha_oqgraph::fprint_error(const char* fmt, ...) ...@@ -478,10 +482,23 @@ void ha_oqgraph::fprint_error(const char* fmt, ...)
va_end(ap); va_end(ap);
} }
/**
* Open the OQGRAPH engine 'table'.
*
* An OQGRAPH table is effectively similar to a view over the underlying backing table,
* attribute 'data_table', but where the result returned by a query depends on the
* value of the 'latch' column specified to the query. Therefore,
* when mysqld opens us, we need to open the corresponding backing table 'data_table'
*
*/
int ha_oqgraph::open(const char *name, int mode, uint test_if_locked) int ha_oqgraph::open(const char *name, int mode, uint test_if_locked)
{ {
DBUG_PRINT( "oq-debug", ("open(name=%s,mode=%d)", name, mode)); DBUG_ENTER("ha_oqgraph::open");
DBUG_PRINT( "oq-debug", ("open(name=%s,mode=%d,test_if_locked=%u)", name, mode, test_if_locked));
assert(!have_table_share);
assert(graph == NULL);
THD* thd = current_thd; THD* thd = current_thd;
oqgraph_table_option_struct *options= oqgraph_table_option_struct *options=
...@@ -490,80 +507,102 @@ int ha_oqgraph::open(const char *name, int mode, uint test_if_locked) ...@@ -490,80 +507,102 @@ int ha_oqgraph::open(const char *name, int mode, uint test_if_locked)
// Catch cases where table was not constructed properly // Catch cases where table was not constructed properly
if (!options) { if (!options) {
fprint_error("Invalid OQGRAPH backing store (null attributes)"); fprint_error("Invalid OQGRAPH backing store (null attributes)");
return -1; DBUG_RETURN(HA_WRONG_CREATE_OPTION);
} }
if (!options->table_name || !*options->table_name) { if (!options->table_name || !*options->table_name) {
fprint_error("Invalid OQGRAPH backing store (unspecified or empty data_table attribute)"); fprint_error("Invalid OQGRAPH backing store (unspecified or empty data_table attribute)");
// if table_name if present but doesnt actually exist, we will fail out below // if table_name if present but doesnt actually exist, we will fail out below
// when we call open_table_def(). same probably applies for the id fields // when we call open_table_def(). same probably applies for the id fields
return -1; DBUG_RETURN(HA_WRONG_CREATE_OPTION);
} }
if (!options->origid || !*options->origid) { if (!options->origid || !*options->origid) {
fprint_error("Invalid OQGRAPH backing store (unspecified or empty origid attribute)"); fprint_error("Invalid OQGRAPH backing store (unspecified or empty origid attribute)");
return -1; DBUG_RETURN(HA_WRONG_CREATE_OPTION);
} }
if (!options->destid || !*options->destid) { if (!options->destid || !*options->destid) {
fprint_error("Invalid OQGRAPH backing store (unspecified or empty destid attribute)"); fprint_error("Invalid OQGRAPH backing store (unspecified or empty destid attribute)");
return -1; DBUG_RETURN(HA_WRONG_CREATE_OPTION);
} }
// weight is optional // weight is optional
error_message.length(0); error_message.length(0);
origid= destid= weight= 0;
init_tmp_table_share( thd, share, table->s->db.str, table->s->db.length, options->table_name, "");
// What I think this code is doing:
// * Our OQGRAPH table is `database_blah/name`
// * We point p --> /name (or if table happened to be simply `name`, to `name`, dont know if this is possible)
// * plen seems to be then set to length of `database_blah/options_data_table_name`
// * then we set share->normalized_path.str and share->path.str to `database_blah/options_data_table_name`
// * I assume that this verbiage is needed so the memory used by share->path.str is set in the share mem root
// * because otherwise one could simply build the string more simply using malloc and pass it instead of "" above
const char* p= strend(name)-1; const char* p= strend(name)-1;
while (p > name && *p != '\\' && *p != '/') while (p > name && *p != '\\' && *p != '/')
--p; --p;
init_tmp_table_share(
thd, share, table->s->db.str, table->s->db.length,
options->table_name, "");
size_t tlen= strlen(options->table_name); size_t tlen= strlen(options->table_name);
size_t plen= (int)(p - name) + tlen + 1; size_t plen= (int)(p - name) + tlen + 1;
share->path.str= (char*) share->path.str= (char*)alloc_root(&share->mem_root, plen);
alloc_root(&share->mem_root, plen);
strmov(strnmov(share->path.str, name, (int)(p - name) + 1), options->table_name); strmov(strnmov(share->path.str, name, (int)(p - name) + 1), options->table_name);
share->normalized_path.str= share->path.str; share->normalized_path.str= share->path.str;
share->path.length= share->normalized_path.length= plen; share->path.length= share->normalized_path.length= plen;
origid= destid= weight= 0;
DBUG_PRINT( "oq-debug", ("share:(normalized_path=%s,path.length=%zu)", DBUG_PRINT( "oq-debug", ("share:(normalized_path=%s,path.length=%zu)",
share->normalized_path.str, share->path.length)); share->normalized_path.str, share->path.length));
while (open_table_def(thd, share, 0))
int open_def_flags = 0;
#if MYSQL_VERSION_ID >= 100002
open_def_flags = GTS_TABLE;
#endif
// We want to open the definition for the given backing table
// Once can assume this loop exists because sometimes open_table_def() fails for a reason other than not exist
// and not 'exist' is valid, because we use ha_create_table_from_engine() to force it to 'exist'
// But, ha_create_table_from_engine() is removed in MariaDB 10.0.4 (?)
// Looking inside most recent ha_create_table_from_engine(), it also calls open_table_def() so maybe this whole thing is redundant...
// Or perhaps it is needed if the backing store is a temporary table or maybe if has no records as yet...?
// Lets try without this, and see if all the tests pass...
while (open_table_def(thd, share, open_def_flags))
{ {
if (thd->is_error() && thd->get_stmt_da()->sql_errno() != ER_NO_SUCH_TABLE) if (thd->is_error() && thd->get_stmt_da()->sql_errno() != ER_NO_SUCH_TABLE)
{ {
free_table_share(share); free_table_share(share);
return thd->get_stmt_da()->sql_errno(); DBUG_RETURN(thd->get_stmt_da()->sql_errno());
} }
#if MYSQL_VERSION_ID < 100002
if (ha_create_table_from_engine(thd, table->s->db.str, options->table_name)) if (ha_create_table_from_engine(thd, table->s->db.str, options->table_name))
{ {
free_table_share(share); free_table_share(share);
return thd->get_stmt_da()->sql_errno(); DBUG_RETURN(thd->get_stmt_da()->sql_errno());
} }
/*mysql_reset_errors(thd, 1);*/ /*mysql_reset_errors(thd, 1);*/
thd->clear_error(); thd->clear_error();
continue; continue;
#else
open_table_error(share, OPEN_FRM_OPEN_ERROR, EMFILE);
free_table_share(share);
fprint_error("Problem opening OQGRPAPH backing store, maybe introduced by MariaDB v10.0.2.");
DBUG_RETURN(-1);
#endif
} }
if (int err= share->error) if (int err= share->error)
{ {
open_table_error(share, share->error, share->open_errno); open_table_error(share, share->error, share->open_errno);
free_table_share(share); free_table_share(share);
return err; DBUG_RETURN(err);
} }
if (share->is_view) if (share->is_view)
{ {
open_table_error(share, OPEN_FRM_OPEN_ERROR, EMFILE); open_table_error(share, OPEN_FRM_OPEN_ERROR, EMFILE);
free_table_share(share); free_table_share(share);
fprint_error("VIEWs are not supported for an OQGRAPH backing store"); fprint_error("VIEWs are not supported for an OQGRAPH backing store.");
return -1; DBUG_RETURN(-1);
} }
if (enum open_frm_error err= open_table_from_share(thd, share, "", if (enum open_frm_error err= open_table_from_share(thd, share, "",
...@@ -574,7 +613,7 @@ int ha_oqgraph::open(const char *name, int mode, uint test_if_locked) ...@@ -574,7 +613,7 @@ int ha_oqgraph::open(const char *name, int mode, uint test_if_locked)
{ {
open_table_error(share, err, EMFILE); open_table_error(share, err, EMFILE);
free_table_share(share); free_table_share(share);
return -1; DBUG_RETURN(-1);
} }
edges->reginfo.lock_type= TL_READ; edges->reginfo.lock_type= TL_READ;
...@@ -595,7 +634,7 @@ int ha_oqgraph::open(const char *name, int mode, uint test_if_locked) ...@@ -595,7 +634,7 @@ int ha_oqgraph::open(const char *name, int mode, uint test_if_locked)
{ {
fprint_error("Some error occurred opening table '%s'", options->table_name); fprint_error("Some error occurred opening table '%s'", options->table_name);
free_table_share(share); free_table_share(share);
return -1; DBUG_RETURN(-1);
} }
for (Field **field= edges->field; *field; ++field) for (Field **field= edges->field; *field; ++field)
...@@ -609,17 +648,17 @@ int ha_oqgraph::open(const char *name, int mode, uint test_if_locked) ...@@ -609,17 +648,17 @@ int ha_oqgraph::open(const char *name, int mode, uint test_if_locked)
options->table_name, options->origid); options->table_name, options->origid);
closefrm(edges, 0); closefrm(edges, 0);
free_table_share(share); free_table_share(share);
return -1; DBUG_RETURN(-1);
} }
origid = *field; origid = *field;
break; break;
} }
if (!origid) { if (!origid) {
fprint_error("Invalid OQGRAPH backing store ('%s'.origid attribute not set to a valid column of '%s')", p, options->table_name); fprint_error("Invalid OQGRAPH backing store ('%s.origid' attribute not set to a valid column of '%s')", p+1, options->table_name);
closefrm(edges, 0); closefrm(edges, 0);
free_table_share(share); free_table_share(share);
return -1; DBUG_RETURN(-1);
} }
...@@ -634,25 +673,25 @@ int ha_oqgraph::open(const char *name, int mode, uint test_if_locked) ...@@ -634,25 +673,25 @@ int ha_oqgraph::open(const char *name, int mode, uint test_if_locked)
options->table_name, options->destid); options->table_name, options->destid);
closefrm(edges, 0); closefrm(edges, 0);
free_table_share(share); free_table_share(share);
return -1; DBUG_RETURN(-1);
} }
destid = *field; destid = *field;
break; break;
} }
if (!destid) { if (!destid) {
fprint_error("Invalid OQGRAPH backing store ('%s'.destid attribute not set to a valid column of '%s')", p, options->table_name); fprint_error("Invalid OQGRAPH backing store ('%s.destid' attribute not set to a valid column of '%s')", p+1, options->table_name);
closefrm(edges, 0); closefrm(edges, 0);
free_table_share(share); free_table_share(share);
return -1; DBUG_RETURN(-1);
} }
// Make sure origid column != destid column // Make sure origid column != destid column
if (strcmp( origid->field_name, destid->field_name)==0) { if (strcmp( origid->field_name, destid->field_name)==0) {
fprint_error("Invalid OQGRAPH backing store ('%s'.destid attribute set to same column as origid attribute)", p, options->table_name); fprint_error("Invalid OQGRAPH backing store ('%s.destid' attribute set to same column as origid attribute)", p+1, options->table_name);
closefrm(edges, 0); closefrm(edges, 0);
free_table_share(share); free_table_share(share);
return -1; DBUG_RETURN(-1);
} }
for (Field **field= edges->field; options->weight && *field; ++field) for (Field **field= edges->field; options->weight && *field; ++field)
...@@ -666,17 +705,17 @@ int ha_oqgraph::open(const char *name, int mode, uint test_if_locked) ...@@ -666,17 +705,17 @@ int ha_oqgraph::open(const char *name, int mode, uint test_if_locked)
options->table_name, options->weight); options->table_name, options->weight);
closefrm(edges, 0); closefrm(edges, 0);
free_table_share(share); free_table_share(share);
return -1; DBUG_RETURN(-1);
} }
weight = *field; weight = *field;
break; break;
} }
if (!weight && options->weight) { if (!weight && options->weight) {
fprint_error("Invalid OQGRAPH backing store ('%s'.weight attribute not set to a valid column of '%s')", p, options->table_name); fprint_error("Invalid OQGRAPH backing store ('%s.weight' attribute not set to a valid column of '%s')", p, options->table_name);
closefrm(edges, 0); closefrm(edges, 0);
free_table_share(share); free_table_share(share);
return -1; DBUG_RETURN(-1);
} }
if (!(graph_share = oqgraph::create(edges, origid, destid, weight))) if (!(graph_share = oqgraph::create(edges, origid, destid, weight)))
...@@ -684,13 +723,14 @@ int ha_oqgraph::open(const char *name, int mode, uint test_if_locked) ...@@ -684,13 +723,14 @@ int ha_oqgraph::open(const char *name, int mode, uint test_if_locked)
fprint_error("Unable to create graph instance."); fprint_error("Unable to create graph instance.");
closefrm(edges, 0); closefrm(edges, 0);
free_table_share(share); free_table_share(share);
return -1; DBUG_RETURN(-1);
} }
ref_length= oqgraph::sizeof_ref; ref_length= oqgraph::sizeof_ref;
graph = oqgraph::create(graph_share); graph = oqgraph::create(graph_share);
have_table_share = true;
return 0; DBUG_RETURN(0);
} }
int ha_oqgraph::close(void) int ha_oqgraph::close(void)
...@@ -698,11 +738,12 @@ int ha_oqgraph::close(void) ...@@ -698,11 +738,12 @@ int ha_oqgraph::close(void)
oqgraph::free(graph); graph= 0; oqgraph::free(graph); graph= 0;
oqgraph::free(graph_share); graph_share= 0; oqgraph::free(graph_share); graph_share= 0;
if (share) if (have_table_share)
{ {
if (edges->file) if (edges->file)
closefrm(edges, 0); closefrm(edges, 0);
free_table_share(share); free_table_share(share);
have_table_share = false;
} }
return 0; return 0;
} }
......
...@@ -44,6 +44,7 @@ namespace open_query ...@@ -44,6 +44,7 @@ namespace open_query
class ha_oqgraph: public handler class ha_oqgraph: public handler
{ {
TABLE_SHARE share[1]; TABLE_SHARE share[1];
bool have_table_share;
TABLE edges[1]; TABLE edges[1];
Field *origid; Field *origid;
Field *destid; Field *destid;
...@@ -62,7 +63,7 @@ public: ...@@ -62,7 +63,7 @@ public:
ha_oqgraph(TABLE *table); ha_oqgraph(TABLE *table);
Table_flags table_flags() const; Table_flags table_flags() const;
#endif #endif
~ha_oqgraph(); virtual ~ha_oqgraph();
const char *index_type(uint inx) const char *index_type(uint inx)
{ {
return "HASH"; return "HASH";
......
...@@ -179,7 +179,7 @@ int oqgraph3::cursor::restore_position() ...@@ -179,7 +179,7 @@ int oqgraph3::cursor::restore_position()
if (int rc= table.file->ha_index_read_map( if (int rc= table.file->ha_index_read_map(
table.record[0], (const uchar*) _key.data(), table.record[0], (const uchar*) _key.data(),
(key_part_map)(1 << _parts) - 1, (key_part_map)(1 << _parts) - 1,
table.s->key_info[_index].key_parts == _parts ? table.s->key_info[_index].user_defined_key_parts == _parts ?
HA_READ_KEY_EXACT : HA_READ_KEY_OR_NEXT)) HA_READ_KEY_EXACT : HA_READ_KEY_OR_NEXT))
{ {
table.file->ha_index_end(); table.file->ha_index_end();
...@@ -439,7 +439,7 @@ int oqgraph3::cursor::seek_to( ...@@ -439,7 +439,7 @@ int oqgraph3::cursor::seek_to(
*key_end= key_info + table.s->keys; *key_end= key_info + table.s->keys;
key_info < key_end; ++key_info, ++i) key_info < key_end; ++key_info, ++i)
{ {
if (key_info->key_parts < 2) if (key_info->user_defined_key_parts < 2)
continue; continue;
if (!((key_info->key_part[0].offset == target_fieldpos && if (!((key_info->key_part[0].offset == target_fieldpos &&
key_info->key_part[1].offset == source_fieldpos) || key_info->key_part[1].offset == source_fieldpos) ||
...@@ -490,7 +490,7 @@ int oqgraph3::cursor::seek_to( ...@@ -490,7 +490,7 @@ int oqgraph3::cursor::seek_to(
if (int rc= table.file->ha_index_read_map( if (int rc= table.file->ha_index_read_map(
table.record[0], (uchar*) _key.data(), table.record[0], (uchar*) _key.data(),
(key_part_map) ((1U << _parts) - 1), (key_part_map) ((1U << _parts) - 1),
table.s->key_info[_index].key_parts == _parts ? table.s->key_info[_index].user_defined_key_parts == _parts ?
HA_READ_KEY_EXACT : HA_READ_KEY_OR_NEXT)) HA_READ_KEY_EXACT : HA_READ_KEY_OR_NEXT))
{ {
table.file->ha_index_end(); table.file->ha_index_end();
......
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