Commit 39750cd4 authored by Olivier Bertrand's avatar Olivier Bertrand

- FIX a bug causing libxml2 not retrieving expanded multiple column values.

  This was working but the cause probably comes from freeing Xop object to
  handle memory leaks reported by Valgrind.
  Also add a test case on XML multiple tables.
added:
  storage/connect/mysql-test/connect/r/xml_mult.result
  storage/connect/mysql-test/connect/std_data/bookstore.xml
  storage/connect/mysql-test/connect/t/xml_mult.test
modified:
  storage/connect/domdoc.cpp
  storage/connect/tabxml.cpp
  storage/connect/tabxml.h

- Enhance the index types and flages returning functions.
modified:
  storage/connect/ha_connect.cc
  storage/connect/ha_connect.h

- Suppress irrelevant warning message (MDEV-6117)
modified:
  storage/connect/ha_connect.cc
parent 046ae9f5
......@@ -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
/******************************************************************/
......
......@@ -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)
......@@ -633,6 +633,50 @@ TABTYPE ha_connect::GetRealType(PTOS pos)
return type;
} // 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
......@@ -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");
......@@ -4550,7 +4595,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 +4930,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!");
......@@ -5123,7 +5168,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;
......
......@@ -167,7 +167,7 @@ class ha_connect: public handler
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 @@ class ha_connect: public handler
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 @@ class ha_connect: public handler
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(),
......
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;
<?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>
--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
......@@ -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
/***********************************************************************/
......
......@@ -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
......
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