diff options
author | Sergei Golubchik <sergii@pisem.net> | 2014-05-08 11:33:51 +0200 |
---|---|---|
committer | Sergei Golubchik <sergii@pisem.net> | 2014-05-08 11:33:51 +0200 |
commit | 229dad1f9b12f8e9f64b6a605bdf8e31c339d018 (patch) | |
tree | b7d0e0a22007e1c4dd24c52ab9ddd67cabaa0110 /storage | |
parent | 60dd52e3a36a700669e127bf39af0f0ac5ac2e0b (diff) | |
parent | 3743e1e0f626833d6941a8b04d90f7c836d12dcf (diff) | |
download | mariadb-git-229dad1f9b12f8e9f64b6a605bdf8e31c339d018.tar.gz |
merge with 10.0-connect
Diffstat (limited to 'storage')
-rw-r--r-- | storage/connect/connect.cc | 4 | ||||
-rw-r--r-- | storage/connect/domdoc.cpp | 24 | ||||
-rw-r--r-- | storage/connect/ha_connect.cc | 126 | ||||
-rw-r--r-- | storage/connect/ha_connect.h | 10 | ||||
-rw-r--r-- | storage/connect/maputil.cpp | 11 | ||||
-rw-r--r-- | storage/connect/myconn.cpp | 71 | ||||
-rw-r--r-- | storage/connect/myconn.h | 1 | ||||
-rw-r--r-- | storage/connect/mysql-test/connect/r/xml_mult.result | 102 | ||||
-rw-r--r-- | storage/connect/mysql-test/connect/std_data/bookstore.xml | 31 | ||||
-rw-r--r-- | storage/connect/mysql-test/connect/t/xml_mult.test | 64 | ||||
-rw-r--r-- | storage/connect/odbconn.cpp | 12 | ||||
-rw-r--r-- | storage/connect/tabdos.h | 3 | ||||
-rw-r--r-- | storage/connect/table.cpp | 15 | ||||
-rw-r--r-- | storage/connect/tabmysql.cpp | 51 | ||||
-rw-r--r-- | storage/connect/tabmysql.h | 5 | ||||
-rw-r--r-- | storage/connect/tabxml.cpp | 125 | ||||
-rw-r--r-- | storage/connect/tabxml.h | 1 | ||||
-rwxr-xr-x | storage/connect/xindex.cpp | 91 | ||||
-rw-r--r-- | storage/connect/xindex.h | 7 | ||||
-rw-r--r-- | storage/connect/xtable.h | 3 |
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 |