summaryrefslogtreecommitdiff
path: root/storage
diff options
context:
space:
mode:
authorSergei Golubchik <sergii@pisem.net>2014-05-08 11:33:51 +0200
committerSergei Golubchik <sergii@pisem.net>2014-05-08 11:33:51 +0200
commit229dad1f9b12f8e9f64b6a605bdf8e31c339d018 (patch)
treeb7d0e0a22007e1c4dd24c52ab9ddd67cabaa0110 /storage
parent60dd52e3a36a700669e127bf39af0f0ac5ac2e0b (diff)
parent3743e1e0f626833d6941a8b04d90f7c836d12dcf (diff)
downloadmariadb-git-229dad1f9b12f8e9f64b6a605bdf8e31c339d018.tar.gz
merge with 10.0-connect
Diffstat (limited to 'storage')
-rw-r--r--storage/connect/connect.cc4
-rw-r--r--storage/connect/domdoc.cpp24
-rw-r--r--storage/connect/ha_connect.cc126
-rw-r--r--storage/connect/ha_connect.h10
-rw-r--r--storage/connect/maputil.cpp11
-rw-r--r--storage/connect/myconn.cpp71
-rw-r--r--storage/connect/myconn.h1
-rw-r--r--storage/connect/mysql-test/connect/r/xml_mult.result102
-rw-r--r--storage/connect/mysql-test/connect/std_data/bookstore.xml31
-rw-r--r--storage/connect/mysql-test/connect/t/xml_mult.test64
-rw-r--r--storage/connect/odbconn.cpp12
-rw-r--r--storage/connect/tabdos.h3
-rw-r--r--storage/connect/table.cpp15
-rw-r--r--storage/connect/tabmysql.cpp51
-rw-r--r--storage/connect/tabmysql.h5
-rw-r--r--storage/connect/tabxml.cpp125
-rw-r--r--storage/connect/tabxml.h1
-rwxr-xr-xstorage/connect/xindex.cpp91
-rw-r--r--storage/connect/xindex.h7
-rw-r--r--storage/connect/xtable.h3
20 files changed, 568 insertions, 189 deletions
diff --git a/storage/connect/connect.cc b/storage/connect/connect.cc
index 77f23edb79c..32997f53068 100644
--- a/storage/connect/connect.cc
+++ b/storage/connect/connect.cc
@@ -442,7 +442,7 @@ RCODE CntReadNext(PGLOBAL g, PTDB tdbp)
for (PCOL colp= tdbp->GetColumns(); colp; colp= colp->GetNext())
colp->SetKcol(NULL);
- ((PTDBASE)tdbp)->SetKindex(NULL);
+ ((PTDBASE)tdbp)->ResetKindex(g, NULL);
} // endif index
// Save stack and allocation environment and prepare error return
@@ -585,7 +585,7 @@ int CntCloseTable(PGLOBAL g, PTDB tdbp)
// Make all the eventual indexes
tbxp= (TDBDOX*)tdbp;
- tbxp->SetKindex(NULL);
+ tbxp->ResetKindex(g, NULL);
tbxp->To_Key_Col= NULL;
rc= tbxp->ResetTableOpt(g, ((PTDBASE)tdbp)->GetDef()->Indexable() == 1);
diff --git a/storage/connect/domdoc.cpp b/storage/connect/domdoc.cpp
index 251b4f17982..518c806c653 100644
--- a/storage/connect/domdoc.cpp
+++ b/storage/connect/domdoc.cpp
@@ -416,18 +416,24 @@ PXLIST DOMNODE::SelectNodes(PGLOBAL g, char *xp, PXLIST lp)
/******************************************************************/
PXNODE DOMNODE::SelectSingleNode(PGLOBAL g, char *xp, PXNODE np)
{
- MSXML2::IXMLDOMNodePtr dnp = Nodep->selectSingleNode(xp);
+ try {
+ MSXML2::IXMLDOMNodePtr dnp = Nodep->selectSingleNode(xp);
- if (dnp) {
- if (np) {
- ((PDOMNODE)np)->Nodep = dnp;
- return np;
- } else
- return new(g) DOMNODE(Doc, dnp);
+ if (dnp) {
+ if (np) {
+ ((PDOMNODE)np)->Nodep = dnp;
+ return np;
+ } else
+ return new(g) DOMNODE(Doc, dnp);
- } else
- return NULL;
+ } // endif dnp
+
+ } catch(_com_error e) {
+ sprintf(g->Message, "%s: %s", MSG(COM_ERROR),
+ _com_util::ConvertBSTRToString(e.Description()));
+ } catch(...) {}
+ return NULL;
} // end of SelectSingleNode
/******************************************************************/
diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc
index 4788b669cbe..974906d6ed5 100644
--- a/storage/connect/ha_connect.cc
+++ b/storage/connect/ha_connect.cc
@@ -413,9 +413,9 @@ static int connect_init_func(void *p)
init_connect_psi_keys();
connect_hton= (handlerton *)p;
- connect_hton->state= SHOW_OPTION_YES;
- connect_hton->create= connect_create_handler;
- connect_hton->flags= HTON_TEMPORARY_NOT_SUPPORTED | HTON_NO_PARTITION;
+ connect_hton->state= SHOW_OPTION_YES;
+ connect_hton->create= connect_create_handler;
+ connect_hton->flags= HTON_TEMPORARY_NOT_SUPPORTED | HTON_NO_PARTITION;
connect_hton->table_options= connect_table_option_list;
connect_hton->field_options= connect_field_option_list;
connect_hton->tablefile_extensions= ha_connect_exts;
@@ -621,7 +621,7 @@ TABTYPE ha_connect::GetRealType(PTOS pos)
{
TABTYPE type;
- if (pos || (pos= GetTableOptionStruct(table))) {
+ if (pos || (pos= GetTableOptionStruct())) {
type= GetTypeID(pos->type);
if (type == TAB_UNDEF)
@@ -634,6 +634,50 @@ TABTYPE ha_connect::GetRealType(PTOS pos)
} // end of GetRealType
/** @brief
+ The name of the index type that will be used for display.
+ Don't implement this method unless you really have indexes.
+ */
+const char *ha_connect::index_type(uint inx)
+{
+ switch (GetIndexType(GetRealType())) {
+ case 1: return "XPLUG";
+ case 2: return "REMOTE";
+ } // endswitch
+
+ return "Unknown";
+} // end of index_type
+
+/** @brief
+ This is a bitmap of flags that indicates how the storage engine
+ implements indexes. The current index flags are documented in
+ handler.h. If you do not implement indexes, just return zero here.
+
+ @details
+ part is the key part to check. First key part is 0.
+ If all_parts is set, MySQL wants to know the flags for the combined
+ index, up to and including 'part'.
+*/
+ulong ha_connect::index_flags(uint inx, uint part, bool all_parts) const
+{
+ ulong flags= HA_READ_NEXT | HA_READ_RANGE |
+ HA_KEYREAD_ONLY | HA_KEY_SCAN_NOT_ROR;
+ ha_connect *hp= (ha_connect*)this;
+ PTOS pos= hp->GetTableOptionStruct();
+
+ if (pos) {
+ TABTYPE type= hp->GetRealType(pos);
+
+ switch (GetIndexType(type)) {
+ case 1: flags|= (HA_READ_ORDER | HA_READ_PREV); break;
+ case 2: flags|= HA_READ_AFTER_KEY; break;
+ } // endswitch
+
+ } // endif pos
+
+ return flags;
+} // end of index_flags
+
+/** @brief
This is a list of flags that indicate what functionality the storage
engine implements. The current table flags are documented in handler.h
*/
@@ -641,14 +685,14 @@ ulonglong ha_connect::table_flags() const
{
ulonglong flags= HA_CAN_VIRTUAL_COLUMNS | HA_REC_NOT_IN_SEQ |
HA_NO_AUTO_INCREMENT | HA_NO_PREFIX_CHAR_KEYS |
-// HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE |
+ HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE |
HA_PARTIAL_COLUMN_READ | HA_FILE_BASED |
// HA_NULL_IN_KEY | not implemented yet
// HA_FAST_KEY_READ | causes error when sorting (???)
HA_NO_TRANSACTIONS | HA_DUPLICATE_KEY_NOT_IN_ORDER |
HA_NO_BLOBS | HA_MUST_USE_TABLE_CONDITION_PUSHDOWN;
ha_connect *hp= (ha_connect*)this;
- PTOS pos= hp->GetTableOptionStruct(table);
+ PTOS pos= hp->GetTableOptionStruct();
if (pos) {
TABTYPE type= hp->GetRealType(pos);
@@ -719,10 +763,11 @@ char *GetListOption(PGLOBAL g, const char *opname,
/****************************************************************************/
/* Return the table option structure. */
/****************************************************************************/
-PTOS ha_connect::GetTableOptionStruct(TABLE *tab)
+PTOS ha_connect::GetTableOptionStruct(TABLE_SHARE *s)
{
- return (tshp) ? tshp->option_struct :
- (tab) ? tab->s->option_struct : NULL;
+ TABLE_SHARE *tsp= (tshp) ? tshp : (s) ? s : table_share;
+
+ return (tsp) ? tsp->option_struct : NULL;
} // end of GetTableOptionStruct
/****************************************************************************/
@@ -731,7 +776,7 @@ PTOS ha_connect::GetTableOptionStruct(TABLE *tab)
char *ha_connect::GetStringOption(char *opname, char *sdef)
{
char *opval= NULL;
- PTOS options= GetTableOptionStruct(table);
+ PTOS options= GetTableOptionStruct();
if (!options)
;
@@ -803,10 +848,10 @@ bool ha_connect::GetBooleanOption(char *opname, bool bdef)
{
bool opval= bdef;
char *pv;
- PTOS options= GetTableOptionStruct(table);
+ PTOS options= GetTableOptionStruct();
if (!stricmp(opname, "View"))
- opval= (tshp) ? tshp->is_view : table->s->is_view;
+ opval= (tshp) ? tshp->is_view : table_share->is_view;
else if (!options)
;
else if (!stricmp(opname, "Mapped"))
@@ -834,7 +879,7 @@ bool ha_connect::GetBooleanOption(char *opname, bool bdef)
/****************************************************************************/
bool ha_connect::SetBooleanOption(char *opname, bool b)
{
- PTOS options= GetTableOptionStruct(table);
+ PTOS options= GetTableOptionStruct();
if (!options)
return true;
@@ -854,7 +899,7 @@ int ha_connect::GetIntegerOption(char *opname)
{
ulonglong opval= NO_IVAL;
char *pv;
- PTOS options= GetTableOptionStruct(table);
+ PTOS options= GetTableOptionStruct();
if (!options)
;
@@ -891,7 +936,7 @@ int ha_connect::GetIntegerOption(char *opname)
/****************************************************************************/
bool ha_connect::SetIntegerOption(char *opname, int n)
{
- PTOS options= GetTableOptionStruct(table);
+ PTOS options= GetTableOptionStruct();
if (!options)
return true;
@@ -1153,7 +1198,7 @@ const char *ha_connect::GetDBName(const char* name)
const char *ha_connect::GetTableName(void)
{
- return (tshp) ? tshp->table_name.str : table->s->table_name.str;
+ return (tshp) ? tshp->table_name.str : table_share->table_name.str;
} // end of GetTableName
#if 0
@@ -2404,7 +2449,7 @@ int ha_connect::index_init(uint idx, bool sorted)
} // endif index type
if ((rc= rnd_init(0)))
- return rc;
+ DBUG_RETURN(rc);
if (locked == 2) {
// Indexes are not updated in lock write mode
@@ -3310,7 +3355,7 @@ int ha_connect::external_lock(THD *thd, int lock_type)
int rc= 0;
bool xcheck=false, cras= false;
MODE newmode;
- PTOS options= GetTableOptionStruct(table);
+ PTOS options= GetTableOptionStruct();
PGLOBAL g= GetPlug(thd, xp);
DBUG_ENTER("ha_connect::external_lock");
@@ -3771,7 +3816,8 @@ ha_rows ha_connect::records_in_range(uint inx, key_range *min_key,
DBUG_ENTER("ha_connect::records_in_range");
if (indexing < 0 || inx != active_index)
- index_init(inx, false);
+ if (index_init(inx, false))
+ DBUG_RETURN(HA_POS_ERROR);
if (xtrace)
htrc("records_in_range: inx=%d indexing=%d\n", inx, indexing);
@@ -4362,7 +4408,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
if (!qrp) {
my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
return HA_ERR_INTERNAL_ERROR;
- } // endif qrp
+ } // endif !qrp
if (fnc != FNC_NO || src || ttp == TAB_PIVOT) {
// Catalog like table
@@ -4384,7 +4430,18 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
} // endfor crp
- } else // Not a catalog table
+ } else {
+ // Not a catalog table
+ if (!qrp->Nblin) {
+ if (tab)
+ sprintf(g->Message, "Cannot get columns from %s", tab);
+ else
+ strcpy(g->Message, "Fail to retrieve columns");
+
+ my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
+ return HA_ERR_INTERNAL_ERROR;
+ } // endif !nblin
+
for (i= 0; !rc && i < qrp->Nblin; i++) {
typ= len= prec= dec= 0;
tm= NOT_NULL_FLAG;
@@ -4477,6 +4534,8 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
rc= HA_ERR_OUT_OF_MEM;
} // endfor i
+ } // endif fnc
+
if (!rc)
rc= init_table_share(thd, table_s, create_info, &sql);
// rc= init_table_share(thd, table_s, create_info, dsn, &sql);
@@ -4550,7 +4609,7 @@ int ha_connect::create(const char *name, TABLE *table_arg,
DBUG_ENTER("ha_connect::create");
int sqlcom= thd_sql_command(table_arg->in_use);
- PTOS options= GetTableOptionStruct(table_arg);
+ PTOS options= GetTableOptionStruct(table_arg->s);
table= table_arg; // Used by called functions
@@ -4885,7 +4944,7 @@ int ha_connect::create(const char *name, TABLE *table_arg,
} else
::close(h);
- if (type == TAB_FMT || options->readonly)
+ if ((type == TAB_FMT || options->readonly) && sqlcom == SQLCOM_CREATE_TABLE)
push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0,
"Congratulation, you just created a read-only void table!");
@@ -4915,7 +4974,15 @@ int ha_connect::create(const char *name, TABLE *table_arg,
// Get the index definitions
if (xdp= GetIndexInfo()) {
- if (GetIndexType(type) == 1) {
+ if (options->multiple) {
+ strcpy(g->Message, "Multiple tables are not indexable");
+ my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
+ rc= HA_ERR_UNSUPPORTED;
+ } else if (options->compressed) {
+ strcpy(g->Message, "Compressed tables are not indexable");
+ my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
+ rc= HA_ERR_UNSUPPORTED;
+ } else if (GetIndexType(type) == 1) {
PDBUSER dup= PlgGetUser(g);
PCATLG cat= (dup) ? dup->Catalog : NULL;
@@ -5123,7 +5190,6 @@ ha_connect::check_if_supported_inplace_alter(TABLE *altered_table,
int sqlcom= thd_sql_command(thd);
TABTYPE newtyp, type= TAB_UNDEF;
HA_CREATE_INFO *create_info= ha_alter_info->create_info;
-//PTOS pos= GetTableOptionStruct(table);
PTOS newopt, oldopt;
xp= GetUser(thd, xp);
PGLOBAL g= xp->g;
@@ -5169,7 +5235,15 @@ ha_connect::check_if_supported_inplace_alter(TABLE *altered_table,
if (ha_alter_info->handler_flags & index_operations ||
!SameString(altered_table, "optname") ||
!SameBool(altered_table, "sepindex")) {
- if (GetIndexType(type) == 1) {
+ if (newopt->multiple) {
+ strcpy(g->Message, "Multiple tables are not indexable");
+ my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
+ DBUG_RETURN(HA_ALTER_ERROR);
+ } else if (newopt->compressed) {
+ strcpy(g->Message, "Compressed tables are not indexable");
+ my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
+ DBUG_RETURN(HA_ALTER_ERROR);
+ } else if (GetIndexType(type) == 1) {
g->Xchk= new(g) XCHK;
PCHK xcp= (PCHK)g->Xchk;
diff --git a/storage/connect/ha_connect.h b/storage/connect/ha_connect.h
index ae7ae010c7d..a8d0be4c03e 100644
--- a/storage/connect/ha_connect.h
+++ b/storage/connect/ha_connect.h
@@ -167,7 +167,7 @@ public:
static bool connect_end(void);
TABTYPE GetRealType(PTOS pos= NULL);
char *GetStringOption(char *opname, char *sdef= NULL);
- PTOS GetTableOptionStruct(TABLE *table_arg);
+ PTOS GetTableOptionStruct(TABLE_SHARE *s= NULL);
bool GetBooleanOption(char *opname, bool bdef);
bool SetBooleanOption(char *opname, bool b);
int GetIntegerOption(char *opname);
@@ -210,7 +210,7 @@ public:
The name of the index type that will be used for display.
Don't implement this method unless you really have indexes.
*/
- const char *index_type(uint inx) { return "XPLUG"; }
+ const char *index_type(uint inx);
/** @brief
The file extensions.
@@ -241,11 +241,7 @@ public:
If all_parts is set, MySQL wants to know the flags for the combined
index, up to and including 'part'.
*/
- ulong index_flags(uint inx, uint part, bool all_parts) const
- {
- return HA_READ_NEXT | HA_READ_RANGE | HA_READ_ORDER |
- HA_READ_PREV | HA_KEYREAD_ONLY | HA_KEY_SCAN_NOT_ROR;
- } // end of index_flags
+ ulong index_flags(uint inx, uint part, bool all_parts) const;
/** @brief
unireg.cc will call max_supported_record_length(), max_supported_keys(),
diff --git a/storage/connect/maputil.cpp b/storage/connect/maputil.cpp
index b7032f10d2b..7104259ebad 100644
--- a/storage/connect/maputil.cpp
+++ b/storage/connect/maputil.cpp
@@ -80,7 +80,16 @@ HANDLE CreateFileMap(PGLOBAL g, LPCSTR filename,
} // endif hFileMap
access = (mode == MODE_READ) ? FILE_MAP_READ : FILE_MAP_WRITE;
- mm->memory = MapViewOfFile(hFileMap, access, 0, 0, 0);
+
+ if (!(mm->memory = MapViewOfFile(hFileMap, access, 0, 0, 0))) {
+ DWORD ler = GetLastError();
+
+ sprintf(g->Message, "Error %ld in MapViewOfFile %s",
+ ler, filename);
+ CloseHandle(hFile);
+ return INVALID_HANDLE_VALUE;
+ } // endif memory
+
// lenH is the high-order word of the file size
mm->lenL = GetFileSize(hFile, &mm->lenH);
CloseHandle(hFileMap); // Not used anymore
diff --git a/storage/connect/myconn.cpp b/storage/connect/myconn.cpp
index 2e563dbaf1e..8700a24ac96 100644
--- a/storage/connect/myconn.cpp
+++ b/storage/connect/myconn.cpp
@@ -31,6 +31,10 @@
/* */
/************************************************************************/
#include "my_global.h"
+#if !defined(MYSQL_PREPARED_STATEMENTS)
+#include "my_sys.h"
+#include "mysqld_error.h"
+#endif // !MYSQL_PREPARED_STATEMENTS
#if defined(WIN32)
//#include <windows.h>
#else // !WIN32
@@ -59,6 +63,59 @@ uint GetDefaultPort(void)
return mysqld_port;
} // end of GetDefaultPort
+#if !defined(MYSQL_PREPARED_STATEMENTS)
+/**************************************************************************
+ Alloc struct for use with unbuffered reads. Data is fetched by domand
+ when calling to mysql_fetch_row.
+ mysql_data_seek is a noop.
+
+ No other queries may be specified with the same MYSQL handle.
+ There shouldn't be much processing per row because mysql server shouldn't
+ have to wait for the client (and will not wait more than 30 sec/packet).
+ NOTE: copied from client.c cli_use_result
+**************************************************************************/
+static MYSQL_RES *connect_use_result(MYSQL *mysql)
+{
+ MYSQL_RES *result;
+ DBUG_ENTER("connect_use_result");
+
+ if (!mysql->fields)
+ DBUG_RETURN(NULL);
+
+ if (mysql->status != MYSQL_STATUS_GET_RESULT) {
+ my_message(ER_UNKNOWN_ERROR, "Command out of sync", MYF(0));
+ DBUG_RETURN(NULL);
+ } // endif status
+
+ if (!(result = (MYSQL_RES*) my_malloc(sizeof(*result) +
+ sizeof(ulong) * mysql->field_count,
+ MYF(MY_WME | MY_ZEROFILL))))
+ DBUG_RETURN(NULL);
+
+ result->lengths = (ulong*)(result+1);
+ result->methods = mysql->methods;
+
+ /* Ptrs: to one row */
+ if (!(result->row = (MYSQL_ROW)my_malloc(sizeof(result->row[0]) *
+ (mysql->field_count+1), MYF(MY_WME)))) {
+ my_free(result);
+ DBUG_RETURN(NULL);
+ } // endif row
+
+ result->fields = mysql->fields;
+ result->field_alloc = mysql->field_alloc;
+ result->field_count = mysql->field_count;
+ result->current_field = 0;
+ result->handle = mysql;
+ result->current_row = 0;
+ mysql->fields = 0; /* fields is now in result */
+ clear_alloc_root(&mysql->field_alloc);
+ mysql->status = MYSQL_STATUS_USE_RESULT;
+ mysql->unbuffered_fetch_owner = &result->unbuffered_fetch_cancelled;
+ DBUG_RETURN(result); /* Data is ready to be fetched */
+} // end of connect_use_result
+#endif // !MYSQL_PREPARED_STATEMENTS
+
/************************************************************************/
/* MyColumns: constructs the result blocks containing all columns */
/* of a MySQL table or view. */
@@ -339,6 +396,7 @@ MYSQLC::MYSQLC(void)
m_Row = NULL;
m_Fields = -1;
N = 0;
+ m_Use = false;
} // end of MYSQLC constructor
/***********************************************************************/
@@ -600,7 +658,16 @@ int MYSQLC::ExecSQL(PGLOBAL g, const char *query, int *w)
rc = RC_FX;
//} else if (mysql_field_count(m_DB) > 0) {
} else if (m_DB->field_count > 0) {
- if (!(m_Res = mysql_store_result(m_DB))) {
+ if (m_Use)
+#if defined(MYSQL_PREPARED_STATEMENTS)
+ m_Res = mysql_use_result(m_DB);
+#else // !MYSQL_PREPARED_STATEMENTS)
+ m_Res = connect_use_result(m_DB);
+#endif // !MYSQL_PREPARED_STATEMENTS
+ else
+ m_Res = mysql_store_result(m_DB);
+
+ if (!m_Res) {
char *msg = (char*)PlugSubAlloc(g, NULL, 512 + strlen(query));
sprintf(msg, "mysql_store_result failed: %s", mysql_error(m_DB));
@@ -609,7 +676,7 @@ int MYSQLC::ExecSQL(PGLOBAL g, const char *query, int *w)
rc = RC_FX;
} else {
m_Fields = mysql_num_fields(m_Res);
- m_Rows = (int)mysql_num_rows(m_Res);
+ m_Rows = (!m_Use) ? (int)mysql_num_rows(m_Res) : 0;
} // endif m_Res
} else {
diff --git a/storage/connect/myconn.h b/storage/connect/myconn.h
index 5bfa58ffb0c..7e892eece34 100644
--- a/storage/connect/myconn.h
+++ b/storage/connect/myconn.h
@@ -96,5 +96,6 @@ class DllItem MYSQLC {
int N;
int m_Fields; // The number of result fields
int m_Afrw; // The number of affected rows
+ bool m_Use; // Use or store result set
}; // end of class MYSQLC
diff --git a/storage/connect/mysql-test/connect/r/xml_mult.result b/storage/connect/mysql-test/connect/r/xml_mult.result
new file mode 100644
index 00000000000..a9592e986c0
--- /dev/null
+++ b/storage/connect/mysql-test/connect/r/xml_mult.result
@@ -0,0 +1,102 @@
+Warnings:
+Warning 1105 No file name. Table will use t1.xml
+SET NAMES utf8;
+#
+# Testing expanded values
+#
+CREATE TABLE `bookstore` (
+`category` CHAR(16) NOT NULL FIELD_FORMAT='@',
+`title` VARCHAR(50) NOT NULL,
+`lang` char(2) NOT NULL FIELD_FORMAT='title/@',
+`author` VARCHAR(24) NOT NULL,
+`year` INT(4) NOT NULL,
+`price` DOUBLE(8,2) NOT NULL)
+ENGINE=CONNECT TABLE_TYPE=XML FILE_NAME='bookstore.xml' OPTION_LIST='expand=1,mulnode=author,limit=6,xmlsup=libxml2';
+SELECT * FROM bookstore;
+category title lang author year price
+COOKING Everyday Italian en Giada De Laurentiis 2005 30.00
+CHILDREN Harry Potter en J K. Rowling 2005 29.99
+WEB XQuery Kick Start en James McGovern 2003 49.99
+WEB XQuery Kick Start en Per Bothner 2003 49.99
+WEB XQuery Kick Start en Kurt Cagle 2003 49.99
+WEB XQuery Kick Start en James Linn 2003 49.99
+WEB XQuery Kick Start en Vaidyanathan Nagarajan 2003 49.99
+WEB Learning XML en Erik T. Ray 2003 39.95
+SELECT category, title, price FROM bookstore;
+category title price
+COOKING Everyday Italian 30.00
+CHILDREN Harry Potter 29.99
+WEB XQuery Kick Start 49.99
+WEB Learning XML 39.95
+SELECT category, title, author, price FROM bookstore WHERE author LIKE '%K%';
+category title author price
+CHILDREN Harry Potter J K. Rowling 29.99
+WEB XQuery Kick Start Kurt Cagle 49.99
+WEB Learning XML Erik T. Ray 39.95
+SELECT category, title, price FROM bookstore WHERE author LIKE 'J%';
+category title price
+CHILDREN Harry Potter 29.99
+WEB XQuery Kick Start 49.99
+WEB XQuery Kick Start 49.99
+#
+# Limiting expanded values
+#
+ALTER TABLE bookstore OPTION_LIST='expand=1,mulnode=author,limit=3,xmlsup=libxml2';
+SELECT * FROM bookstore;
+category title lang author year price
+COOKING Everyday Italian en Giada De Laurentiis 2005 30.00
+CHILDREN Harry Potter en J K. Rowling 2005 29.99
+WEB XQuery Kick Start en James McGovern 2003 49.99
+WEB XQuery Kick Start en Per Bothner 2003 49.99
+WEB XQuery Kick Start en Kurt Cagle 2003 49.99
+WEB Learning XML en Erik T. Ray 2003 39.95
+Warnings:
+Warning 1105 Mutiple values limited to 3
+# One line lost because the where clause is applied only on the first 3 rows
+SELECT category, title, author, price FROM bookstore WHERE author LIKE 'J%';
+category title author price
+CHILDREN Harry Potter J K. Rowling 29.99
+WEB XQuery Kick Start James McGovern 49.99
+Warnings:
+Warning 1105 Mutiple values limited to 3
+#
+# Testing concatenated values
+#
+ALTER TABLE bookstore OPTION_LIST='mulnode=author,limit=6,xmlsup=libxml2';
+# truncated
+SELECT * FROM bookstore;
+category title lang author year price
+COOKING Everyday Italian en Giada De Laurentiis 2005 30.00
+CHILDREN Harry Potter en J K. Rowling 2005 29.99
+WEB XQuery Kick Start en James McGovern, Per Both 2003 49.99
+WEB Learning XML en Erik T. Ray 2003 39.95
+Warnings:
+Warning 1105 Truncated author content
+# increase author size
+ALTER TABLE bookstore MODIFY `author` VARCHAR(128) NOT NULL;
+SELECT * FROM bookstore;
+category title lang author year price
+COOKING Everyday Italian en Giada De Laurentiis 2005 30.00
+CHILDREN Harry Potter en J K. Rowling 2005 29.99
+WEB XQuery Kick Start en James McGovern, Per Bothner, Kurt Cagle, James Linn, Vaidyanathan Nagarajan 2003 49.99
+WEB Learning XML en Erik T. Ray 2003 39.95
+#
+# Limiting concatenated values
+#
+ALTER TABLE bookstore OPTION_LIST='mulnode=author,limit=4,xmlsup=libxml2';
+SELECT * FROM bookstore;
+category title lang author year price
+COOKING Everyday Italian en Giada De Laurentiis 2005 30.00
+CHILDREN Harry Potter en J K. Rowling 2005 29.99
+WEB XQuery Kick Start en James McGovern, Per Bothner, Kurt Cagle, James Linn 2003 49.99
+WEB Learning XML en Erik T. Ray 2003 39.95
+Warnings:
+Warning 1105 Mutiple values limited to 4
+# The where clause is applied on the concatenated column result
+SELECT category, title, author, price FROM bookstore WHERE author LIKE 'J%';
+category title author price
+CHILDREN Harry Potter J K. Rowling 29.99
+WEB XQuery Kick Start James McGovern, Per Bothner, Kurt Cagle, James Linn 49.99
+Warnings:
+Warning 1105 Mutiple values limited to 4
+DROP TABLE bookstore;
diff --git a/storage/connect/mysql-test/connect/std_data/bookstore.xml b/storage/connect/mysql-test/connect/std_data/bookstore.xml
new file mode 100644
index 00000000000..0aebbcd243e
--- /dev/null
+++ b/storage/connect/mysql-test/connect/std_data/bookstore.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<bookstore>
+ <book category="COOKING">
+ <title lang="en">Everyday Italian</title>
+ <author>Giada De Laurentiis</author>
+ <year>2005</year>
+ <price>30.00</price>
+ </book>
+ <book category="CHILDREN">
+ <title lang="en">Harry Potter</title>
+ <author>J K. Rowling</author>
+ <year>2005</year>
+ <price>29.99</price>
+ </book>
+ <book category="WEB">
+ <title lang="en">XQuery Kick Start</title>
+ <author>James McGovern</author>
+ <author>Per Bothner</author>
+ <author>Kurt Cagle</author>
+ <author>James Linn</author>
+ <author>Vaidyanathan Nagarajan</author>
+ <year>2003</year>
+ <price>49.99</price>
+ </book>
+ <book category="WEB">
+ <title lang="en">Learning XML</title>
+ <author>Erik T. Ray</author>
+ <year>2003</year>
+ <price>39.95</price>
+ </book>
+</bookstore>
diff --git a/storage/connect/mysql-test/connect/t/xml_mult.test b/storage/connect/mysql-test/connect/t/xml_mult.test
new file mode 100644
index 00000000000..cd83827fe34
--- /dev/null
+++ b/storage/connect/mysql-test/connect/t/xml_mult.test
@@ -0,0 +1,64 @@
+--source have_libxml2.inc
+
+let $MYSQLD_DATADIR= `select @@datadir`;
+
+SET NAMES utf8;
+
+--copy_file $MTR_SUITE_DIR/std_data/bookstore.xml $MYSQLD_DATADIR/test/bookstore.xml
+
+#--echo $MYSQL_TEST_DIR
+#--exec pwd
+#SELECT LOAD_FILE('test/bookstore.xml');
+
+
+--echo #
+--echo # Testing expanded values
+--echo #
+CREATE TABLE `bookstore` (
+ `category` CHAR(16) NOT NULL FIELD_FORMAT='@',
+ `title` VARCHAR(50) NOT NULL,
+ `lang` char(2) NOT NULL FIELD_FORMAT='title/@',
+ `author` VARCHAR(24) NOT NULL,
+ `year` INT(4) NOT NULL,
+ `price` DOUBLE(8,2) NOT NULL)
+ENGINE=CONNECT TABLE_TYPE=XML FILE_NAME='bookstore.xml' OPTION_LIST='expand=1,mulnode=author,limit=6,xmlsup=libxml2';
+SELECT * FROM bookstore;
+SELECT category, title, price FROM bookstore;
+SELECT category, title, author, price FROM bookstore WHERE author LIKE '%K%';
+SELECT category, title, price FROM bookstore WHERE author LIKE 'J%';
+
+
+--echo #
+--echo # Limiting expanded values
+--echo #
+ALTER TABLE bookstore OPTION_LIST='expand=1,mulnode=author,limit=3,xmlsup=libxml2';
+SELECT * FROM bookstore;
+--echo # One line lost because the where clause is applied only on the first 3 rows
+SELECT category, title, author, price FROM bookstore WHERE author LIKE 'J%';
+
+
+--echo #
+--echo # Testing concatenated values
+--echo #
+ALTER TABLE bookstore OPTION_LIST='mulnode=author,limit=6,xmlsup=libxml2';
+--echo # truncated
+SELECT * FROM bookstore;
+--echo # increase author size
+ALTER TABLE bookstore MODIFY `author` VARCHAR(128) NOT NULL;
+SELECT * FROM bookstore;
+
+
+--echo #
+--echo # Limiting concatenated values
+--echo #
+ALTER TABLE bookstore OPTION_LIST='mulnode=author,limit=4,xmlsup=libxml2';
+SELECT * FROM bookstore;
+--echo # The where clause is applied on the concatenated column result
+SELECT category, title, author, price FROM bookstore WHERE author LIKE 'J%';
+DROP TABLE bookstore;
+
+
+#
+# Clean up
+#
+--remove_file $MYSQLD_DATADIR/test/bookstore.xml
diff --git a/storage/connect/odbconn.cpp b/storage/connect/odbconn.cpp
index a857a1bc918..679e8dc703c 100644
--- a/storage/connect/odbconn.cpp
+++ b/storage/connect/odbconn.cpp
@@ -2135,7 +2135,7 @@ int ODBConn::GetCatInfo(CATPARM *cap)
PSZ fnc = "Unknown";
UWORD n;
SWORD ncol, len, tp;
- SQLULEN crow;
+ SQLULEN crow = 0;
PQRYRES qrp = cap->Qrp;
PCOLRES crp;
RETCODE rc = 0;
@@ -2287,6 +2287,7 @@ int ODBConn::GetCatInfo(CATPARM *cap)
} // endfor i
+#if 0
if ((crow = i) && (rc == SQL_NO_DATA || rc == SQL_SUCCESS_WITH_INFO))
rc = SQL_SUCCESS;
@@ -2303,6 +2304,15 @@ int ODBConn::GetCatInfo(CATPARM *cap)
} else
ThrowDBX(rc, fnc, hstmt);
+#endif // 0
+
+ if (!rc || rc == SQL_NO_DATA || rc == SQL_SUCCESS_WITH_INFO) {
+ if ((rc = SQLFetch(hstmt)) != SQL_NO_DATA_FOUND)
+ qrp->Truncated = true;
+
+ crow = i;
+ } else
+ ThrowDBX(rc, fnc, hstmt);
irc = (int)crow;
} catch(DBX *x) {
diff --git a/storage/connect/tabdos.h b/storage/connect/tabdos.h
index 5ea7847d2c9..d6cbc8f8d92 100644
--- a/storage/connect/tabdos.h
+++ b/storage/connect/tabdos.h
@@ -49,7 +49,8 @@ class DllExport DOSDEF : public TABDEF { /* Logical table description */
int GetEnding(void) {return Ending;}
// Methods
- virtual int Indexable(void) {return (Compressed != 1) ? 1 : 0;}
+ virtual int Indexable(void)
+ {return (!Multiple && Compressed != 1) ? 1 : 0;}
virtual bool DeleteIndexFile(PGLOBAL g, PIXDEF pxdf);
virtual bool DefineAM(PGLOBAL g, LPCSTR am, int poff);
virtual PTDB GetTable(PGLOBAL g, MODE mode);
diff --git a/storage/connect/table.cpp b/storage/connect/table.cpp
index 9749673ad71..325e80945f7 100644
--- a/storage/connect/table.cpp
+++ b/storage/connect/table.cpp
@@ -304,15 +304,22 @@ int TDBASE::ResetTableOpt(PGLOBAL g, bool dox)
} // end of ResetTableOpt
/***********************************************************************/
-/* SetKindex: set or reset the index pointer. */
+/* ResetKindex: set or reset the index pointer. */
/***********************************************************************/
-void TDBASE::SetKindex(PKXBASE kxp)
+void TDBASE::ResetKindex(PGLOBAL g, PKXBASE kxp)
{
- if (To_Kindex)
+ if (To_Kindex) {
+ int pos = GetRecpos(); // To be reset in Txfp
+
+ for (PCOL colp= Columns; colp; colp= colp->GetNext())
+ colp->SetKcol(NULL);
+
To_Kindex->Close(); // Discard old index
+ SetRecpos(g, pos); // Ignore return value
+ } // endif To_Kindex
To_Kindex = kxp;
- } // end of SetKindex
+ } // end of ResetKindex
/***********************************************************************/
/* SetRecpos: Replace the table at the specified position. */
diff --git a/storage/connect/tabmysql.cpp b/storage/connect/tabmysql.cpp
index a57c7b21c94..dea6978f73e 100644
--- a/storage/connect/tabmysql.cpp
+++ b/storage/connect/tabmysql.cpp
@@ -84,10 +84,11 @@ MYSQLDEF::MYSQLDEF(void)
Username = NULL;
Password = NULL;
Portnumber = 0;
- Isview = FALSE;
- Bind = FALSE;
- Delayed = FALSE;
- Xsrc = FALSE;
+ Isview = false;
+ Bind = false;
+ Delayed = false;
+ Xsrc = false;
+ Huge = false;
} // end of MYSQLDEF constructor
/***********************************************************************/
@@ -329,7 +330,7 @@ bool MYSQLDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
} else {
// MYSQL access from a PROXY table
Database = GetStringCatInfo(g, "Database", "*");
- Isview = GetBoolCatInfo("View", FALSE);
+ Isview = GetBoolCatInfo("View", false);
// We must get other connection parms from the calling table
Remove_tshp(Cat);
@@ -363,7 +364,8 @@ bool MYSQLDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
// Specific for command executing tables
Xsrc = GetBoolCatInfo("Execsrc", false);
Mxr = GetIntCatInfo("Maxerr", 0);
- return FALSE;
+ Huge = GetBoolCatInfo("Huge", false);
+ return false;
} // end of DefineAM
/***********************************************************************/
@@ -401,6 +403,7 @@ TDBMYSQL::TDBMYSQL(PMYDEF tdp) : TDBASE(tdp)
Isview = tdp->Isview;
Prep = tdp->Bind;
Delayed = tdp->Delayed;
+ Myc.m_Use = tdp->Huge;
} else {
Host = NULL;
Database = NULL;
@@ -412,15 +415,15 @@ TDBMYSQL::TDBMYSQL(PMYDEF tdp) : TDBASE(tdp)
Qrystr = NULL;
Quoted = 0;
Port = 0;
- Isview = FALSE;
- Prep = FALSE;
- Delayed = FALSE;
+ Isview = false;
+ Prep = false;
+ Delayed = false;
} // endif tdp
Bind = NULL;
Query = NULL;
Qbuf = NULL;
- Fetched = FALSE;
+ Fetched = false;
m_Rc = RC_FX;
AftRows = 0;
N = -1;
@@ -555,17 +558,17 @@ bool TDBMYSQL::MakeInsert(PGLOBAL g)
char *colist, *valist = NULL;
char *tk = "`";
int len = 0, qlen = 0;
- bool b = FALSE;
+ bool b = false;
PCOL colp;
if (Query)
- return FALSE; // already done
+ return false; // already done
for (colp = Columns; colp; colp = colp->GetNext())
if (!colp->IsSpecial()) {
// if (colp->IsSpecial()) {
// strcpy(g->Message, MSG(NO_SPEC_COL));
-// return TRUE;
+// return true;
// } else {
len += (strlen(colp->GetName()) + 4);
((PMYCOL)colp)->Rank = Nparm++;
@@ -581,7 +584,7 @@ bool TDBMYSQL::MakeInsert(PGLOBAL g)
#else // !MYSQL_PREPARED_STATEMENTS
strcpy(g->Message, "Prepared statements not used (not supported)");
PushWarning(g, this);
- Prep = FALSE;
+ Prep = false;
#endif // !MYSQL_PREPARED_STATEMENTS
} // endif Prep
@@ -590,7 +593,7 @@ bool TDBMYSQL::MakeInsert(PGLOBAL g)
strcat(colist, ", ");
if (Prep) strcat(valist, ",");
} else
- b = TRUE;
+ b = true;
strcat(strcat(strcat(colist, tk), colp->GetName()), tk);
@@ -628,7 +631,7 @@ bool TDBMYSQL::MakeInsert(PGLOBAL g)
Qbuf = (char *)PlugSubAlloc(g, NULL, qlen);
} // endelse Prep
- return FALSE;
+ return false;
} // end of MakeInsert
/***********************************************************************/
@@ -906,9 +909,9 @@ bool TDBMYSQL::SetColumnRanks(PGLOBAL g)
{
for (PCOL colp = Columns; colp; colp = colp->GetNext())
if (((PMYCOL)colp)->FindRank(g))
- return TRUE;
+ return true;
- return FALSE;
+ return false;
} // end of SetColumnRanks
/***********************************************************************/
@@ -1233,7 +1236,7 @@ bool MYSQLCOL::SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check)
{
if (!(To_Val = value)) {
sprintf(g->Message, MSG(VALUE_ERROR), Name);
- return TRUE;
+ return true;
} else if (Buf_Type == value->GetType()) {
// Values are of the (good) column type
if (Buf_Type == TYPE_DATE) {
@@ -1253,12 +1256,12 @@ bool MYSQLCOL::SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check)
if (check) {
sprintf(g->Message, MSG(TYPE_VALUE_ERR), Name,
GetTypeName(Buf_Type), GetTypeName(value->GetType()));
- return TRUE;
+ return true;
} // endif check
newval:
if (InitValue(g)) // Allocate the matching value block
- return TRUE;
+ return true;
} // endif's Value, Buf_Type
@@ -1269,7 +1272,7 @@ bool MYSQLCOL::SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check)
// Set the Column
Status = (ok) ? BUF_EMPTY : BUF_NO;
- return FALSE;
+ return false;
} // end of SetBuffer
/***********************************************************************/
@@ -1317,7 +1320,7 @@ void MYSQLCOL::ReadColumn(PGLOBAL g)
longjmp(g->jumper[g->jump_level], 11);
} else
- tdbp->Fetched = TRUE;
+ tdbp->Fetched = true;
if ((buf = ((PTDBMY)To_Tdb)->Myc.GetCharField(Rank))) {
if (trace > 1)
@@ -1354,7 +1357,7 @@ void MYSQLCOL::WriteColumn(PGLOBAL g)
/* Do convert the column value if necessary. */
/*********************************************************************/
if (Value != To_Val)
- Value->SetValue_pval(To_Val, FALSE); // Convert the inserted value
+ Value->SetValue_pval(To_Val, false); // Convert the inserted value
#if defined(MYSQL_PREPARED_STATEMENTS)
if (((PTDBMY)To_Tdb)->Prep) {
diff --git a/storage/connect/tabmysql.h b/storage/connect/tabmysql.h
index 0387fcc7da9..96991fb14c1 100644
--- a/storage/connect/tabmysql.h
+++ b/storage/connect/tabmysql.h
@@ -58,10 +58,11 @@ class MYSQLDEF : public TABDEF {/* Logical table description */
int Portnumber; /* MySQL port number (0 = default) */
int Mxr; /* Maxerr for an Exec table */
int Quoted; /* Identifier quoting level */
- bool Isview; /* TRUE if this table is a MySQL view */
+ bool Isview; /* true if this table is a MySQL view */
bool Bind; /* Use prepared statement on insert */
bool Delayed; /* Delayed insert */
bool Xsrc; /* Execution type */
+ bool Huge; /* True for big table */
}; // end of MYSQLDEF
/***********************************************************************/
@@ -84,7 +85,7 @@ class TDBMYSQL : public TDBASE {
virtual int GetRecpos(void) {return N;}
virtual int GetProgMax(PGLOBAL g);
virtual void ResetDB(void) {N = 0;}
- virtual int RowNumber(PGLOBAL g, bool b = FALSE);
+ virtual int RowNumber(PGLOBAL g, bool b = false);
virtual bool IsView(void) {return Isview;}
virtual PSZ GetServer(void) {return Server;}
void SetDatabase(LPCSTR db) {Database = (char*)db;}
diff --git a/storage/connect/tabxml.cpp b/storage/connect/tabxml.cpp
index c7c61f0dcbb..1e9c172cdb3 100644
--- a/storage/connect/tabxml.cpp
+++ b/storage/connect/tabxml.cpp
@@ -145,7 +145,7 @@ bool XMLDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
XmlDB = GetStringCatInfo(g, "XmlDB", "");
Nslist = GetStringCatInfo(g, "Nslist", "");
DefNs = GetStringCatInfo(g, "DefNs", "");
- Limit = GetIntCatInfo("Limit", 2);
+ Limit = GetIntCatInfo("Limit", 10);
Xpand = (GetIntCatInfo("Expand", 0) != 0);
Header = GetIntCatInfo("Header", 0);
GetCharCatInfo("Xmlsup", "*", buf, sizeof(buf));
@@ -1038,12 +1038,13 @@ XMLCOL::XMLCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am)
Type = Tdbp->Coltype;
Nx = -1;
Sx = -1;
+ N = 0;
Valbuf = NULL;
To_Val = NULL;
} // end of XMLCOL constructor
/***********************************************************************/
-/* XMLCOL constructor used for copying columns. */
+/* XMLCOL constructor used for copying columns. */
/* tdbp is the pointer to the new table descriptor. */
/***********************************************************************/
XMLCOL::XMLCOL(XMLCOL *col1, PTDB tdbp) : COLBLK(col1, tdbp)
@@ -1068,6 +1069,7 @@ XMLCOL::XMLCOL(XMLCOL *col1, PTDB tdbp) : COLBLK(col1, tdbp)
Rank = col1->Rank;
Nx = col1->Nx;
Sx = col1->Sx;
+ N = col1->N;
Type = col1->Type;
To_Val = col1->To_Val;
} // end of XMLCOL copy constructor
@@ -1080,8 +1082,8 @@ bool XMLCOL::AllocBuf(PGLOBAL g, bool mode)
if (Valbuf)
return false; // Already done
- Valbuf = (char*)PlugSubAlloc(g, NULL, Long + 1);
- Valbuf[Long] = '\0';
+//Valbuf = (char*)PlugSubAlloc(g, NULL, Long + 1);
+//Valbuf[Long] = '\0';
return ParseXpath(g, mode);
} // end of AllocBuf
@@ -1095,7 +1097,7 @@ bool XMLCOL::AllocBuf(PGLOBAL g, bool mode)
bool XMLCOL::ParseXpath(PGLOBAL g, bool mode)
{
char *p, *p2, *pbuf = NULL;
- int i, len = strlen(Name);
+ int i, n = 1, len = strlen(Name);
len += ((Tdbp->Colname) ? strlen(Tdbp->Colname) : 0);
len += ((Xname) ? strlen(Xname) : 0);
@@ -1122,7 +1124,7 @@ bool XMLCOL::ParseXpath(PGLOBAL g, bool mode)
// For Update or Insert the Xpath must be analyzed
if (mode) {
for (i = 0, p = pbuf; (p = strchr(p, '/')); i++, p++)
- Nod++; // One path node found
+ Nod++; // One path node found
if (Nod)
Nodes = (char**)PlugSubAlloc(g, NULL, Nod * sizeof(char*));
@@ -1136,7 +1138,7 @@ bool XMLCOL::ParseXpath(PGLOBAL g, bool mode)
strcpy(g->Message, MSG(CONCAT_SUBNODE));
return true;
} else
- Inod = i; // Index of multiple node
+ Inod = i; // Index of multiple node
if (mode) {
// For Update or Insert the Xpath must be explicit
@@ -1171,7 +1173,7 @@ bool XMLCOL::ParseXpath(PGLOBAL g, bool mode)
} else if (Type == 2) {
// HTML like table, columns are retrieved by position
- new(this) XPOSCOL(Value); // Change the class of this column
+ new(this) XPOSCOL(Value); // Change the class of this column
Tdbp->Hasnod = true;
return false;
} else if (Type == 0 && !mode) {
@@ -1185,9 +1187,18 @@ bool XMLCOL::ParseXpath(PGLOBAL g, bool mode)
if (Inod >= 0) {
Tdbp->Colp = this; // To force expand
- new(this) XMULCOL(Value); // Change the class of this column
+
+ if (Tdbp->Xpand)
+ n = Tdbp->Limit;
+
+ new(this) XMULCOL(Value); // Change the class of this column
} // endif Inod
+ Valbuf = (char*)PlugSubAlloc(g, NULL, n * (Long + 1));
+
+ for (i = 0; i < n; i++)
+ Valbuf[Long + (i * (Long + 1))] = '\0';
+
if (Type || Nod)
Tdbp->Hasnod = true;
@@ -1470,60 +1481,72 @@ void XMLCOL::WriteColumn(PGLOBAL g)
void XMULCOL::ReadColumn(PGLOBAL g)
{
char *p;
- int i, n, len;
+ int i, len;
+ bool b = Tdbp->Xpand;
- if (Nx != Tdbp->Irow) // New row
+ if (Nx != Tdbp->Irow) { // New row
Nl = Tdbp->RowNode->SelectNodes(g, Xname, Nl);
- else if (Sx == Tdbp->Nsub)
- return; // Same row
- if ((n = Nl->GetLength())) {
- *(p = Valbuf) = '\0';
- len = Long;
+ if ((N = Nl->GetLength())) {
+ *(p = Valbuf) = '\0';
+ len = Long;
- for (i = Tdbp->Nsub; i < n; i++) {
- ValNode = Nl->GetItem(g, i, Vxnp);
+ if (N > Tdbp->Limit) {
+ N = Tdbp->Limit;
+ sprintf(g->Message, "Mutiple values limited to %d", Tdbp->Limit);
+ PushWarning(g, Tdbp);
+ } // endif N
- if (ValNode->GetType() != XML_ELEMENT_NODE &&
- ValNode->GetType() != XML_ATTRIBUTE_NODE) {
- sprintf(g->Message, MSG(BAD_VALNODE), ValNode->GetType(), Name);
- longjmp(g->jumper[g->jump_level], TYPE_AM_XML);
- } // endif type
+ for (i = 0; i < N; i++) {
+ ValNode = Nl->GetItem(g, i, Vxnp);
- // Get the Xname value from the XML file
- switch (ValNode->GetContent(g, p, len + 1)) {
- case RC_OK:
- break;
- case RC_INFO:
- PushWarning(g, Tdbp);
- break;
- default:
+ if (ValNode->GetType() != XML_ELEMENT_NODE &&
+ ValNode->GetType() != XML_ATTRIBUTE_NODE) {
+ sprintf(g->Message, MSG(BAD_VALNODE), ValNode->GetType(), Name);
longjmp(g->jumper[g->jump_level], TYPE_AM_XML);
- } // endswitch
-
- if (!Tdbp->Xpand) {
- // Concatenate all values
- if (n - i > 1)
- strncat(Valbuf, ", ", Long + 1);
-
- len -= strlen(p);
- p += strlen(p);
- } else
- break;
-
- } // endfor i
+ } // endif type
+
+ // Get the Xname value from the XML file
+ switch (ValNode->GetContent(g, p, (b ? Long : len))) {
+ case RC_OK:
+ break;
+ case RC_INFO:
+ PushWarning(g, Tdbp);
+ break;
+ default:
+ longjmp(g->jumper[g->jump_level], TYPE_AM_XML);
+ } // endswitch
+
+ if (!b) {
+ // Concatenate all values
+ if (N - i > 1)
+ strncat(Valbuf, ", ", len - strlen(p));
+
+ if ((len -= strlen(p)) <= 0)
+ break;
+
+ p += strlen(p);
+ } else // Xpand
+ p += (Long + 1);
+
+ } // endfor i
+
+ Value->SetValue_psz(Valbuf);
+ } else {
+ if (Nullable)
+ Value->SetNull(true);
- Value->SetValue_psz(Valbuf);
- } else {
- if (Nullable)
- Value->SetNull(true);
+ Value->Reset(); // Null value
+ } // endif ValNode
- Value->Reset(); // Null value
- } // endif ValNode
+ } else if (Sx == Tdbp->Nsub)
+ return; // Same row
+ else // Expanded value
+ Value->SetValue_psz(Valbuf + (Tdbp->Nsub * (Long + 1)));
Nx = Tdbp->Irow;
Sx = Tdbp->Nsub;
- Tdbp->NextSame = (Tdbp->Xpand && Nl->GetLength() - Sx > 1);
+ Tdbp->NextSame = (Tdbp->Xpand && N - Sx > 1);
} // end of ReadColumn
/***********************************************************************/
diff --git a/storage/connect/tabxml.h b/storage/connect/tabxml.h
index 1284cf6197f..23c46c03a8b 100644
--- a/storage/connect/tabxml.h
+++ b/storage/connect/tabxml.h
@@ -190,6 +190,7 @@ class XMLCOL : public COLBLK {
int Long; // Buffer length
int Nx; // The last read row
int Sx; // The last read sub-row
+ int N; // The number of (multiple) values
PVAL To_Val; // To value used for Update/Insert
}; // end of class XMLCOL
diff --git a/storage/connect/xindex.cpp b/storage/connect/xindex.cpp
index ac4329d8683..fad7495fa82 100755
--- a/storage/connect/xindex.cpp
+++ b/storage/connect/xindex.cpp
@@ -2131,9 +2131,6 @@ int XINDXS::FastFind(int nk)
XLOAD::XLOAD(void)
{
Hfile = INVALID_HANDLE_VALUE;
-#if defined(WIN32) && defined(XMAP)
- ViewBase = NULL;
-#endif // WIN32 && XMAP
NewOff.Val = 0LL;
} // end of XLOAD constructor
@@ -2147,15 +2144,6 @@ void XLOAD::Close(void)
Hfile = INVALID_HANDLE_VALUE;
} // endif Hfile
-#if defined(WIN32) && defined(XMAP)
- if (ViewBase) {
- if (!UnmapViewOfFile(ViewBase))
- printf("Error %d closing Viewmap\n", GetLastError());
-
- ViewBase = NULL;
- } // endif ViewBase
-#endif // WIN32 && XMAP
-
} // end of Close
/* --------------------------- XFILE Class --------------------------- */
@@ -2166,9 +2154,9 @@ void XLOAD::Close(void)
XFILE::XFILE(void) : XLOAD()
{
Xfile = NULL;
-#if defined(XMAP) && !defined(WIN32)
+#if defined(XMAP)
Mmp = NULL;
-#endif // XMAP && !WIN32
+#endif // XMAP
} // end of XFILE constructor
/***********************************************************************/
@@ -2193,9 +2181,9 @@ bool XFILE::Open(PGLOBAL g, char *filename, int id, MODE mode)
} // endswitch mode
if (!(Xfile= global_fopen(g, MSGID_OPEN_ERROR_AND_STRERROR, filename, pmod))) {
-#if defined(TRACE)
- printf("Open: %s\n", g->Message);
-#endif // TRACE
+ if (trace)
+ htrc("Open: %s\n", g->Message);
+
return true;
} // endif Xfile
@@ -2311,11 +2299,9 @@ void XFILE::Close(void)
Xfile = NULL;
} // endif Xfile
-#if defined(XMAP) && !defined(WIN32)
- if (Mmp) {
- CloseMemMap(Mmp->memory, Mmp->lenL);
- Mmp = NULL;
- } // endif Mmp
+#if defined(XMAP)
+ if (Mmp && CloseMemMap(Mmp->memory, Mmp->lenL))
+ printf("Error closing mapped index\n");
#endif // XMAP
} // end of Close
@@ -2357,9 +2343,8 @@ bool XHUGE::Open(PGLOBAL g, char *filename, int id, MODE mode)
return true;
} // endif
-#if defined(TRACE)
- printf( "Xopen: filename=%s mode=%d\n", filename, mode);
-#endif // TRACE
+ if (trace)
+ htrc(" Xopen: filename=%s mode=%d\n", filename, mode);
#if defined(WIN32)
LONG high = 0;
@@ -2476,16 +2461,15 @@ bool XHUGE::Open(PGLOBAL g, char *filename, int id, MODE mode)
if (Hfile == INVALID_HANDLE_VALUE) {
/*rc = errno;*/
-#if defined(TRACE)
- printf("Open: %s\n", g->Message);
-#endif // TRACE
+ if (trace)
+ htrc("Open: %s\n", g->Message);
+
return true;
} // endif Hfile
-#if defined(TRACE)
- printf(" rc=%d oflag=%p mode=%d handle=%d fn=%s\n",
- rc, oflag, mode, Hfile, filename);
-#endif // TRACE
+ if (trace)
+ htrc(" oflag=%p mode=%d handle=%d fn=%s\n",
+ oflag, mode, Hfile, filename);
if (mode == MODE_INSERT) {
/*******************************************************************/
@@ -2588,15 +2572,15 @@ bool XHUGE::Read(PGLOBAL g, void *buf, int n, int size)
#else // UNIX
ssize_t count = (ssize_t)(n * size);
-#if defined(TRACE)
- printf("Hfile=%d n=%d size=%d count=%d\n", Hfile, n, size, count);
-#endif // TRACE
+ if (trace)
+ htrc("Hfile=%d n=%d size=%d count=%d\n", Hfile, n, size, count);
if (read(Hfile, buf, count) != count) {
sprintf(g->Message, MSG(READ_ERROR), "Index file", strerror(errno));
-#if defined(TRACE)
- printf("read error %d\n", errno);
-#endif // TRACE
+
+ if (trace)
+ htrc("read error %d\n", errno);
+
rc = true;
} // endif nbr
#endif // UNIX
@@ -2854,8 +2838,7 @@ bool KXYCOL::Init(PGLOBAL g, PCOL colp, int n, bool sm, int kln)
// Allocate the Value object used when moving items
Type = colp->GetResultType();
- if (!(Valp = AllocateValue(g, Type, len, colp->GetScale(),
- colp->IsUnsigned())))
+ if (!(Valp = AllocateValue(g, Type, len, prec, colp->IsUnsigned())))
return true;
Klen = Valp->GetClen();
@@ -2877,10 +2860,11 @@ bool KXYCOL::Init(PGLOBAL g, PCOL colp, int n, bool sm, int kln)
// Store this information to avoid sorting when already done
if (Asc)
-// IsSorted = colp->GetOpt() < 0;
+// IsSorted = colp->GetOpt() == 2;
IsSorted = false;
//SetNulls(colp->IsNullable()); for when null columns will be indexable
+ Colp = colp;
return false;
} // end of Init
@@ -2891,7 +2875,7 @@ bool KXYCOL::Init(PGLOBAL g, PCOL colp, int n, bool sm, int kln)
/***********************************************************************/
BYTE* KXYCOL::MapInit(PGLOBAL g, PCOL colp, int *n, BYTE *m)
{
- int len = colp->GetLength(), prec = colp->GetPrecision();
+ int len = colp->GetLength(), prec = colp->GetScale();
if (n[3] && colp->GetLength() > n[3]
&& colp->GetResultType() == TYPE_STRING) {
@@ -2906,7 +2890,7 @@ BYTE* KXYCOL::MapInit(PGLOBAL g, PCOL colp, int *n, BYTE *m)
this, colp, Type, n[0], len, m);
// Allocate the Value object used when moving items
- Valp = AllocateValue(g, Type, len, prec, false, NULL);
+ Valp = AllocateValue(g, Type, len, prec, colp->IsUnsigned());
Klen = Valp->GetClen();
if (n[2]) {
@@ -2926,7 +2910,7 @@ BYTE* KXYCOL::MapInit(PGLOBAL g, PCOL colp, int *n, BYTE *m)
// by blanks (if true) or keep the zero ending char (if false).
// Currently we set it to true to be compatible with QRY blocks,
// and last one to enable type checking (no conversion).
- Kblp = AllocValBlock(g, To_Keys, Type, n[0], len, prec, true, true);
+ Kblp = AllocValBlock(g, To_Keys, Type, n[0], len, prec, !Prefix, true);
if (n[1]) {
Koff.Size = n[1] * sizeof(int);
@@ -2937,6 +2921,7 @@ BYTE* KXYCOL::MapInit(PGLOBAL g, PCOL colp, int *n, BYTE *m)
Ndf = n[0];
//IsSorted = colp->GetOpt() < 0;
IsSorted = false;
+ Colp = colp;
return m + Bkeys.Size + Keys.Size + Koff.Size;
} // end of MapInit
#endif // XMAP
@@ -3054,9 +3039,8 @@ int KXYCOL::Compare(int i1, int i2)
// Do the actual comparison between values.
register int k = Kblp->CompVal(i1, i2);
-#ifdef DEBUG2
- htrc("Compare done result=%d\n", k);
-#endif
+ if (trace > 2)
+ htrc("Compare done result=%d\n", k);
return (Asc) ? k : -k;
} // end of Compare
@@ -3067,13 +3051,14 @@ int KXYCOL::Compare(int i1, int i2)
int KXYCOL::CompVal(int i)
{
// Do the actual comparison between numerical values.
-#ifdef DEBUG2
- register int k = (int)Kblp->CompVal(Valp, (int)i);
+ if (trace > 2) {
+ register int k = (int)Kblp->CompVal(Valp, (int)i);
+
+ htrc("Compare done result=%d\n", k);
+ return k;
+ } else
+ return Kblp->CompVal(Valp, i);
- htrc("Compare done result=%d\n", k);
- return k;
-#endif
- return Kblp->CompVal(Valp, i);
} // end of CompVal
/***********************************************************************/
diff --git a/storage/connect/xindex.h b/storage/connect/xindex.h
index 6ed0416bad5..62430ffa0ad 100644
--- a/storage/connect/xindex.h
+++ b/storage/connect/xindex.h
@@ -339,9 +339,6 @@ class DllExport XLOAD : public BLOCK {
// Members
#if defined(WIN32)
HANDLE Hfile; // Handle to file or map
-#if defined(XMAP)
- void *ViewBase; // Mapped view base address
-#endif // XMAP
#else // UNIX
int Hfile; // Descriptor to file or map
#endif // UNIX
@@ -369,9 +366,9 @@ class DllExport XFILE : public XLOAD {
protected:
// Members
- FILE *Xfile; // Index stream file
+ FILE *Xfile; // Index stream file
#if defined(XMAP)
- MMP Mmp; // To mapped index file
+ MMP Mmp; // Mapped view base address and length
#endif // XMAP
}; // end of class XFILE
diff --git a/storage/connect/xtable.h b/storage/connect/xtable.h
index 027e22f5e01..1f937bba6c1 100644
--- a/storage/connect/xtable.h
+++ b/storage/connect/xtable.h
@@ -142,9 +142,10 @@ class DllExport TDBASE : public TDB {
inline PKXBASE GetKindex(void) {return To_Kindex;}
inline PCOL GetSetCols(void) {return To_SetCols;}
inline void SetSetCols(PCOL colp) {To_SetCols = colp;}
+ inline void SetKindex(PKXBASE kxp) {To_Kindex = kxp;}
// Properties
- void SetKindex(PKXBASE kxp);
+ void ResetKindex(PGLOBAL g, PKXBASE kxp);
PCOL Key(int i) {return (To_Key_Col) ? To_Key_Col[i] : NULL;}
// Methods