From 5133cb5e2530954a23b93ee22a49273f7333e36b Mon Sep 17 00:00:00 2001
From: Olivier Bertrand <bertrandop@gmail.com>
Date: Mon, 3 Feb 2014 16:14:13 +0100
Subject: [PATCH] This is a major update of CONNECT that goes from version 1.1
 to 1.2 =================================================================== -
 Implement a first support of the ALTER TABLE command. This fixes MDEV-5440  
 but does much more than only that. See the details of how ALTER is supported 
  in the new documentation and also in MDEV-5440 comment.   This is done
 principally by implementing for CONNECT the virtual function  
 check_if_supported_inplace_alter. modified:   storage/connect/connect.cc  
 storage/connect/global.h   storage/connect/ha_connect.cc  
 storage/connect/ha_connect.h  
 storage/connect/mysql-test/connect/r/bin.result  
 storage/connect/mysql-test/connect/r/csv.result  
 storage/connect/mysql-test/connect/r/dbf.result  
 storage/connect/mysql-test/connect/r/dir.result  
 storage/connect/mysql-test/connect/r/fix.result  
 storage/connect/mysql-test/connect/r/index.result  
 storage/connect/mysql-test/connect/r/ini.result  
 storage/connect/mysql-test/connect/r/occur.result  
 storage/connect/mysql-test/connect/r/pivot.result  
 storage/connect/mysql-test/connect/r/vec.result  
 storage/connect/mysql-test/connect/t/dbf.test   storage/connect/plugutil.c  
 storage/connect/user_connect.cc

- Fixes the tabname/table_name issue for XML tables. Implement
  multiple files XML tables.
modified:
  storage/connect/tabxml.cpp
  storage/connect/tabxml.h

- Set to varchar(256) the fields of catalog tables stored
  as STRBLK's (had length 0 --> CHAR(1))
  Add the GetCharString function to the VALBLK class
modified:
  storage/connect/ha_connect.cc
  storage/connect/valblk.cpp
  storage/connect/valblk.h
  storage/connect/value.cpp

- Translate CONNECT error messages to system_charset
  to avoid truncation on not ASCII characters.
modified:
  storage/connect/ha_connect.cc

- Update version number
modified:
  storage/connect/ha_connect.cc
  storage/connect/mysql-test/connect/r/xml.result

- Move the TDBASE::data_charset body from xtable.h to table.cpp.
  (dont' remember why)
modified:
  storage/connect/table.cpp
  storage/connect/xtable.h

- Other modifications are to enhance the support of OEM tables.
  In particular, they can now provide column definition in dicovery.
modified:
  storage/connect/colblk.h
  storage/connect/global.h
  storage/connect/ha_connect.cc
  storage/connect/mycat.cc
  storage/connect/plgcnx.h
  storage/connect/plgdbsem.h
  storage/connect/xtable.h

- Or to add or modify tracing.
modified:
  storage/connect/filamtxt.cpp
  storage/connect/ha_connect.cc
  storage/connect/plgdbutl.cpp
  storage/connect/tabfix.cpp
  storage/connect/tabmysql.cpp
---
 storage/connect/colblk.h                      |  14 +-
 storage/connect/connect.cc                    |   2 +-
 storage/connect/filamtxt.cpp                  |  12 +-
 storage/connect/global.h                      |   3 +-
 storage/connect/ha_connect.cc                 | 946 +++++++++++++-----
 storage/connect/ha_connect.h                  |  38 +-
 storage/connect/mycat.cc                      |  83 ++
 .../connect/mysql-test/connect/r/bin.result   |   4 -
 .../connect/mysql-test/connect/r/csv.result   |   4 -
 .../connect/mysql-test/connect/r/dbf.result   |  20 +-
 .../connect/mysql-test/connect/r/dir.result   |   2 -
 .../connect/mysql-test/connect/r/fix.result   |   4 -
 .../connect/mysql-test/connect/r/index.result |   2 -
 .../connect/mysql-test/connect/r/ini.result   |   4 -
 .../connect/mysql-test/connect/r/occur.result |   2 +
 .../connect/mysql-test/connect/r/pivot.result |  12 +-
 .../connect/mysql-test/connect/r/vec.result   |   4 -
 .../connect/mysql-test/connect/r/xml.result   |   2 +-
 storage/connect/mysql-test/connect/t/dbf.test |  14 +-
 storage/connect/plgcnx.h                      |  10 +-
 storage/connect/plgdbsem.h                    |  22 +-
 storage/connect/plgdbutl.cpp                  |  12 +-
 storage/connect/plugutil.c                    |   1 +
 storage/connect/tabfix.cpp                    |   2 +-
 storage/connect/table.cpp                     |  15 +-
 storage/connect/tabmysql.cpp                  |   2 +-
 storage/connect/tabxml.cpp                    |  61 +-
 storage/connect/tabxml.h                      |   1 +
 storage/connect/user_connect.cc               |   1 +
 storage/connect/valblk.cpp                    |  45 +-
 storage/connect/valblk.h                      |  13 +-
 storage/connect/value.cpp                     |  10 +-
 storage/connect/xtable.h                      |  18 +-
 33 files changed, 1029 insertions(+), 356 deletions(-)

diff --git a/storage/connect/colblk.h b/storage/connect/colblk.h
index 320350f1923..11fca3e4fb7 100644
--- a/storage/connect/colblk.h
+++ b/storage/connect/colblk.h
@@ -1,7 +1,7 @@
 /*************** Colblk H Declares Source Code File (.H) ***************/
-/*  Name: COLBLK.H    Version 1.6                                      */
+/*  Name: COLBLK.H    Version 1.7                                      */
 /*                                                                     */
-/*  (C) Copyright to the author Olivier BERTRAND          2005-2013    */
+/*  (C) Copyright to the author Olivier BERTRAND          2005-2014    */
 /*                                                                     */
 /*  This file contains the COLBLK and derived classes declares.        */
 /***********************************************************************/
@@ -99,7 +99,7 @@ class DllExport COLBLK : public XOBJECT {
 /***********************************************************************/
 /*  Class SPCBLK: Base class for special column descriptors.           */
 /***********************************************************************/
-class SPCBLK : public COLBLK {
+class DllExport SPCBLK : public COLBLK {
  public:
   // Constructor
   SPCBLK(PCOLUMN cp);
@@ -121,7 +121,7 @@ class SPCBLK : public COLBLK {
 /***********************************************************************/
 /*  Class RIDBLK: ROWID special column descriptor.                     */
 /***********************************************************************/
-class RIDBLK : public SPCBLK {
+class DllExport RIDBLK : public SPCBLK {
  public:
   // Constructor
   RIDBLK(PCOLUMN cp, bool rnm);
@@ -140,7 +140,7 @@ class RIDBLK : public SPCBLK {
 /***********************************************************************/
 /*  Class FIDBLK: FILEID special column descriptor.                    */
 /***********************************************************************/
-class FIDBLK : public SPCBLK {
+class DllExport FIDBLK : public SPCBLK {
  public:
   // Constructor
   FIDBLK(PCOLUMN cp);
@@ -161,7 +161,7 @@ class FIDBLK : public SPCBLK {
 /***********************************************************************/
 /*  Class TIDBLK: TABID special column descriptor.                     */
 /***********************************************************************/
-class TIDBLK : public SPCBLK {
+class DllExport TIDBLK : public SPCBLK {
  public:
   // Constructor
   TIDBLK(PCOLUMN cp);
@@ -186,7 +186,7 @@ class TIDBLK : public SPCBLK {
 /***********************************************************************/
 /*  Class SIDBLK: SERVID special column descriptor.                    */
 /***********************************************************************/
-class SIDBLK : public SPCBLK {
+class DllExport SIDBLK : public SPCBLK {
  public:
   // Constructor
   SIDBLK(PCOLUMN cp);
diff --git a/storage/connect/connect.cc b/storage/connect/connect.cc
index f3c2559f13e..9340ae97258 100644
--- a/storage/connect/connect.cc
+++ b/storage/connect/connect.cc
@@ -347,7 +347,7 @@ bool CntOpenTable(PGLOBAL g, PTDB tdbp, MODE mode, char *c1, char *c2,
   if (xtrace)
     printf("About to open the table: tdbp=%p\n", tdbp);
 
-  if (mode != MODE_ANY) {
+  if (mode != MODE_ANY && mode != MODE_ALTER) {
     if (tdbp->OpenDB(g)) {
       printf("%s\n", g->Message);
       return true;
diff --git a/storage/connect/filamtxt.cpp b/storage/connect/filamtxt.cpp
index 2291f2c2b00..1d3f17e2228 100644
--- a/storage/connect/filamtxt.cpp
+++ b/storage/connect/filamtxt.cpp
@@ -535,7 +535,7 @@ int DOSFAM::ReadBuffer(PGLOBAL g)
   if (!Stream)
     return RC_EF;
 
-  if (trace)
+  if (trace > 1)
     htrc("ReadBuffer: Tdbp=%p To_Line=%p Placed=%d\n",
                       Tdbp, Tdbp->To_Line, Placed); 
 
@@ -548,20 +548,20 @@ int DOSFAM::ReadBuffer(PGLOBAL g)
 
     CurBlk = (int)Rows++;
 
-     if (trace)
+     if (trace > 1)
       htrc("ReadBuffer: CurBlk=%d\n", CurBlk); 
 
   } else
     Placed = false;
 
-  if (trace)
+  if (trace > 1)
     htrc(" About to read: stream=%p To_Buf=%p Buflen=%d\n",
                           Stream, To_Buf, Buflen);
 
   if (fgets(To_Buf, Buflen, Stream)) {
     p = To_Buf + strlen(To_Buf) - 1;
 
-    if (trace)
+    if (trace > 1)
       htrc(" Read: To_Buf=%p p=%c\n", To_Buf, To_Buf, p);
 
 #if defined(UNIX)
@@ -589,7 +589,7 @@ int DOSFAM::ReadBuffer(PGLOBAL g)
     } else if (*p == '\n')
       *p = '\0';          // Eliminate ending new-line character
 
-    if (trace)
+    if (trace > 1)
       htrc(" To_Buf='%s'\n", To_Buf);
 
     strcpy(Tdbp->To_Line, To_Buf);
@@ -610,7 +610,7 @@ int DOSFAM::ReadBuffer(PGLOBAL g)
     rc = RC_FX;
   } // endif's fgets
 
-  if (trace)
+  if (trace > 1)
     htrc("ReadBuffer: rc=%d\n", rc);
 
   IsRead = true;
diff --git a/storage/connect/global.h b/storage/connect/global.h
index 4c0bc993123..8bccd742a64 100644
--- a/storage/connect/global.h
+++ b/storage/connect/global.h
@@ -219,9 +219,10 @@ typedef struct _global {            /* Global structure                */
   uint      Sarea_Size;             /* Work area size                  */
   PACTIVITY Activityp, ActivityStart;
   char      Message[MAX_STR];
-  short     Trace;
   int       Createas;               /* To pass info to created table   */
   void     *Xchk;                   /* indexes in create/alter         */
+  short     Alchecked;              /* Checked for ALTER               */
+  short     Trace;
   int       jump_level;
   jmp_buf   jumper[MAX_JUMP + 2];
   } GLOBAL;
diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc
index d051ef76698..4533c628686 100644
--- a/storage/connect/ha_connect.cc
+++ b/storage/connect/ha_connect.cc
@@ -1,4 +1,4 @@
-/* Copyright (C) Olivier Bertrand 2004 - 2013
+/* Copyright (C) Olivier Bertrand 2004 - 2014
 
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
@@ -107,6 +107,7 @@
 #include "field.h"
 #include "sql_parse.h"
 #include "sql_base.h"
+#include <sys/stat.h>
 #if defined(NEW_WAY)
 #include "sql_table.h"
 #endif   // NEW_WAY
@@ -164,8 +165,13 @@ extern "C" char  plgini[];
 extern "C" char  nmfile[];
 extern "C" char  pdebug[];
 
+/***********************************************************************/
+/*  Initialize the ha_connect static members.                          */
+/***********************************************************************/
+#define CONNECT_INI "connect.ini"
 extern "C" {
-       char  version[]= "Version 1.01.0011 December 15, 2013";
+       char  connectini[_MAX_PATH]= CONNECT_INI;
+       char  version[]= "Version 1.02.0001 February 03, 2014";
 
 #if defined(XMSG)
        char  msglang[];            // Default message language
@@ -173,17 +179,17 @@ extern "C" {
        int  trace= 0;              // The general trace value
 } // extern "C"
 
-/****************************************************************************/
-/*  Initialize the ha_connect static members.                               */
-/****************************************************************************/
-#define CONNECT_INI "connect.ini"
-char  connectini[_MAX_PATH]= CONNECT_INI;
 int   xtrace= 0;
 ulong ha_connect::num= 0;
 //int  DTVAL::Shift= 0;
 
+/***********************************************************************/
+/*  Utility functions.                                                 */
+/***********************************************************************/
+PQRYRES OEMColumns(PGLOBAL g, PTOS topt, char *tab, char *db, bool info);
+
 static PCONNECT GetUser(THD *thd, PCONNECT xp);
-static PGLOBAL GetPlug(THD *thd, PCONNECT& lxp);
+static PGLOBAL  GetPlug(THD *thd, PCONNECT& lxp);
 
 static handler *connect_create_handler(handlerton *hton,
                                    TABLE_SHARE *table,
@@ -474,6 +480,7 @@ ha_connect::ha_connect(handlerton *hton, TABLE_SHARE *table_arg)
   valid_query_id= 0;
   creat_query_id= (table && table->in_use) ? table->in_use->query_id : 0;
   stop= false;
+  alter= false;
   indexing= -1;
   locked= 0;
   data_file_name= NULL;
@@ -491,6 +498,11 @@ ha_connect::ha_connect(handlerton *hton, TABLE_SHARE *table_arg)
 /****************************************************************************/
 ha_connect::~ha_connect(void)
 {
+  if (xtrace)
+    printf("Delete CONNECT %p, table: %s, xp=%p count=%d\n", this,
+                         table ? table->s->table_name.str : "<null>",
+                         xp, xp ? xp->count : 0);
+
   if (xp) {
     PCONNECT p;
 
@@ -562,12 +574,55 @@ static PGLOBAL GetPlug(THD *thd, PCONNECT& lxp)
   return (lxp) ? lxp->g : NULL;
 } // end of GetPlug
 
+/****************************************************************************/
+/*  Get the implied table type.                                             */
+/****************************************************************************/
+TABTYPE ha_connect::GetRealType(PTOS pos)
+{
+  TABTYPE type= GetTypeID(pos->type);
+
+  if (type == TAB_UNDEF)
+    type= pos->srcdef ? TAB_MYSQL : pos->tabname ? TAB_PRX : TAB_DOS;
+
+  return type;
+} // end of GetRealType
+
+/** @brief
+  This is a list of flags that indicate what functionality the storage
+  engine implements. The current table flags are documented in handler.h
+*/
+ulonglong ha_connect::table_flags() const
+{
+  ulonglong   flags= HA_NO_TRANSACTIONS | HA_REC_NOT_IN_SEQ |
+                     HA_NO_AUTO_INCREMENT | HA_NO_PREFIX_CHAR_KEYS |
+                     HA_HAS_RECORDS | HA_CAN_VIRTUAL_COLUMNS |
+                     HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE |
+//                   HA_NULL_IN_KEY |    not implemented yet
+                     HA_DUPLICATE_KEY_NOT_IN_ORDER |
+                     HA_MUST_USE_TABLE_CONDITION_PUSHDOWN;
+  ha_connect *hp= (ha_connect*)this;
+  PTOS        pos= hp->GetTableOptionStruct(table);
+
+  if (pos) {
+    TABTYPE type= hp->GetRealType(pos);
+    
+    if (IsFileType(type))
+      flags|= HA_FILE_BASED;
+
+    // No data change on ALTER for outward tables
+    if (!IsFileType(type) || hp->FileExists(pos->filename))
+      flags|= HA_NO_COPY_ON_ALTER;
+
+    } // endif pos
+
+  return flags;
+} // end of table_flags
 
 /****************************************************************************/
 /*  Return the value of an option specified in the option list.             */
 /****************************************************************************/
-static char *GetListOption(PGLOBAL g, const char *opname,
-                           const char *oplist, const char *def=NULL)
+char *GetListOption(PGLOBAL g, const char *opname,
+                               const char *oplist, const char *def)
 {
   char  key[16], val[256];
   char *pk, *pv, *pn;
@@ -619,7 +674,8 @@ static char *GetListOption(PGLOBAL g, const char *opname,
 /****************************************************************************/
 PTOS ha_connect::GetTableOptionStruct(TABLE *tab)
 {
-  return (tshp) ? tshp->option_struct : tab->s->option_struct;
+  return (tshp) ? tshp->option_struct : 
+    (tab) ? tab->s->option_struct : NULL;
 } // end of GetTableOptionStruct
 
 /****************************************************************************/
@@ -972,24 +1028,27 @@ void *ha_connect::GetColumnOption(PGLOBAL g, void *field, PCOLINFO pcf)
 /****************************************************************************/
 /*  Returns the index description structure used to make the index.         */
 /****************************************************************************/
-PIXDEF ha_connect::GetIndexInfo(void)
+PIXDEF ha_connect::GetIndexInfo(TABLE_SHARE *s)
 {
   char    *name, *pn;
   bool     unique;
   PIXDEF   xdp, pxd=NULL, toidx= NULL;
   PKPDEF   kpp, pkp;
-  PGLOBAL& g= xp->g;
   KEY      kp;
+  PGLOBAL& g= xp->g;
 
-  for (int n= 0; (unsigned)n < table->s->keynames.count; n++) {
+  if (!s)
+    s= table->s;
+
+  for (int n= 0; (unsigned)n < s->keynames.count; n++) {
     if (xtrace)
       printf("Getting created index %d info\n", n + 1);
 
     // Find the index to describe
-    kp= table->s->key_info[n];
+    kp= s->key_info[n];
 
     // Now get index information
-    pn= (char*)table->s->keynames.type_names[n];
+    pn= (char*)s->keynames.type_names[n];
     name= (char*)PlugSubAlloc(g, NULL, strlen(pn) + 1);
     strcpy(name, pn);    // This is probably unuseful
     unique= (kp.flags & 1) != 0;
@@ -1292,7 +1351,7 @@ int ha_connect::MakeRecord(char *buf)
     if (fp->vcol_info && !fp->stored_in_db)
       continue;            // This is a virtual column
 
-    if (bitmap_is_set(map, fp->field_index)) {
+    if (bitmap_is_set(map, fp->field_index) || alter) {
       // This is a used field, fill the buffer with value
       for (colp= tdbp->GetColumns(); colp; colp= colp->GetNext())
         if (!stricmp(colp->GetName(), (char*)fp->field_name))
@@ -1457,18 +1516,17 @@ int ha_connect::ScanRecord(PGLOBAL g, uchar *buf)
           break;
         default:
           fp->val_str(&attribute);
-          if (charset == &my_charset_bin)
-          {
-            value->SetValue_psz(attribute.c_ptr_safe());
-          }
-          else
-          {
+
+          if (charset != &my_charset_bin) {
             // Convert from SQL field charset to DATA_CHARSET
             uint cnv_errors;
+
             data_charset_value.copy(attribute.ptr(), attribute.length(),
                                     attribute.charset(), charset, &cnv_errors);
             value->SetValue_psz(data_charset_value.c_ptr_safe());
-          }
+          } else
+            value->SetValue_psz(attribute.c_ptr_safe());
+
           break;
         } // endswitch Type
 
@@ -1598,7 +1656,7 @@ PFIL ha_connect::CheckCond(PGLOBAL g, PFIL filp, AMT tty, Item *cond)
   if (!cond)
     return NULL;
 
-  if (xtrace > 1)
+  if (xtrace)
     printf("Cond type=%d\n", cond->type());
 
   if (cond->type() == COND::COND_ITEM) {
@@ -1608,7 +1666,7 @@ PFIL ha_connect::CheckCond(PGLOBAL g, PFIL filp, AMT tty, Item *cond)
     if (x)
       return NULL;
 
-    if (xtrace > 1)
+    if (xtrace)
       printf("Cond: Ftype=%d name=%s\n", cond_item->functype(),
                                          cond_item->func_name());
 
@@ -1655,7 +1713,7 @@ PFIL ha_connect::CheckCond(PGLOBAL g, PFIL filp, AMT tty, Item *cond)
     Item_func *condf= (Item_func *)cond;
     Item*     *args= condf->arguments();
 
-    if (xtrace > 1)
+    if (xtrace)
       printf("Func type=%d argnum=%d\n", condf->functype(),
                                          condf->argument_count());
 
@@ -1684,11 +1742,11 @@ PFIL ha_connect::CheckCond(PGLOBAL g, PFIL filp, AMT tty, Item *cond)
       return NULL;
 
     for (i= 0; i < condf->argument_count(); i++) {
-      if (xtrace > 1)
+      if (xtrace)
         printf("Argtype(%d)=%d\n", i, args[i]->type());
 
       if (i >= 2 && !ismul) {
-        if (xtrace > 1)
+        if (xtrace)
           printf("Unexpected arg for vop=%d\n", vop);
 
         continue;
@@ -1710,6 +1768,8 @@ PFIL ha_connect::CheckCond(PGLOBAL g, PFIL filp, AMT tty, Item *cond)
         if (fop && fop->special) {
           if (tty == TYPE_AM_TBL && !stricmp(fop->special, "TABID"))
             fnm= "TABID";
+          else if (tty == TYPE_AM_PLG)
+            fnm= fop->special;
           else
             return NULL;
 
@@ -1718,7 +1778,7 @@ PFIL ha_connect::CheckCond(PGLOBAL g, PFIL filp, AMT tty, Item *cond)
         else
           fnm= pField->field->field_name;
 
-        if (xtrace > 1) {
+        if (xtrace) {
           printf("Field index=%d\n", pField->field->field_index);
           printf("Field name=%s\n", pField->field->field_name);
           } // endif xtrace
@@ -1728,15 +1788,36 @@ PFIL ha_connect::CheckCond(PGLOBAL g, PFIL filp, AMT tty, Item *cond)
           return NULL;
 
         strcat(body, fnm);
+      } else if (args[i]->type() == COND::FUNC_ITEM) {
+        if (tty == TYPE_AM_MYSQL) {
+          if (!CheckCond(g, filp, tty, args[i]))
+            return NULL;
+
+        } else
+          return NULL;
+
       } else {
         char    buff[256];
         String *res, tmp(buff, sizeof(buff), &my_charset_bin);
         Item_basic_constant *pval= (Item_basic_constant *)args[i];
 
+        switch (args[i]->type()) {
+          case COND::STRING_ITEM:
+          case COND::INT_ITEM:
+          case COND::REAL_ITEM:
+          case COND::NULL_ITEM:
+          case COND::DECIMAL_ITEM:
+          case COND::DATE_ITEM:
+          case COND::CACHE_ITEM:
+            break;
+          default:
+            return NULL;
+          } // endswitch type
+
         if ((res= pval->val_str(&tmp)) == NULL)
           return NULL;                      // To be clarified
 
-        if (xtrace > 1)
+        if (xtrace)
           printf("Value=%.*s\n", res->length(), res->ptr());
 
         // IN and BETWEEN clauses should be col VOP list
@@ -1781,7 +1862,7 @@ PFIL ha_connect::CheckCond(PGLOBAL g, PFIL filp, AMT tty, Item *cond)
       filp->Op= vop;
 
   } else {
-    if (xtrace > 1)
+    if (xtrace)
       printf("Unsupported condition\n");
 
     return NULL;
@@ -1819,7 +1900,8 @@ const COND *ha_connect::cond_push(const COND *cond)
     bool x= (tty == TYPE_AM_MYX || tty == TYPE_AM_XDBC); 
 
     if (tty == TYPE_AM_WMI || tty == TYPE_AM_ODBC ||
-        tty == TYPE_AM_TBL || tty == TYPE_AM_MYSQL || x) {
+        tty == TYPE_AM_TBL || tty == TYPE_AM_MYSQL || 
+        tty == TYPE_AM_PLG || x) {
       PGLOBAL& g= xp->g;
       PFIL filp= (PFIL)PlugSubAlloc(g, NULL, sizeof(FILTER));
 
@@ -1830,7 +1912,7 @@ const COND *ha_connect::cond_push(const COND *cond)
 
       if (CheckCond(g, filp, tty, (Item *)cond)) {
         if (xtrace)
-          puts(filp->Body);
+          printf("cond_push: %s\n", filp->Body);
 
         if (!x)
           PlugSubAlloc(g, NULL, strlen(filp->Body) + 1);
@@ -1879,9 +1961,19 @@ bool ha_connect::get_error_message(int error, String* buf)
 {
   DBUG_ENTER("ha_connect::get_error_message");
 
-  if (xp && xp->g)
-    buf->copy(xp->g->Message, (uint)strlen(xp->g->Message),
-              system_charset_info);
+  if (xp && xp->g) {
+    PGLOBAL g= xp->g;
+    char   *msg= (char*)PlugSubAlloc(g, NULL, strlen(g->Message) * 3);
+    uint    dummy_errors;
+    uint32  len= copy_and_convert(msg, strlen(g->Message) * 3,
+                               system_charset_info,
+                               g->Message, strlen(g->Message),
+                               &my_charset_latin1,
+                               &dummy_errors);
+    msg[len]= '\0';
+    buf->copy(msg, (uint)strlen(msg), system_charset_info);
+  } else
+    buf->copy("Cannot retrieve msg", 19, system_charset_info);
 
   DBUG_RETURN(false);
 } // end of get_error_message
@@ -2030,6 +2122,10 @@ int ha_connect::write_row(uchar *buf)
   PGLOBAL& g= xp->g;
   DBUG_ENTER("ha_connect::write_row");
 
+  // This is not tested yet
+  if (xmod == MODE_ALTER)
+    xmod= MODE_INSERT;
+
   // Open the table if it was not opened yet (locked)
   if (!IsOpened() || xmod != tdbp->GetMode()) {
     if (IsOpened())
@@ -2155,6 +2251,9 @@ int ha_connect::index_init(uint idx, bool sorted)
   PGLOBAL& g= xp->g;
   DBUG_ENTER("index_init");
 
+  if (xtrace)
+    printf("index_init: this=%p idx=%u sorted=%d\n", this, idx, sorted);
+
   if ((rc= rnd_init(0)))
     return rc;
 
@@ -2184,6 +2283,10 @@ int ha_connect::index_init(uint idx, bool sorted)
     rc= 0;
   } // endif indexing
 
+  if (xtrace)
+    printf("index_init: rc=%d indexing=%d active_index=%d\n", 
+            rc, indexing, active_index);
+
   DBUG_RETURN(rc);
 } // end of index_init
 
@@ -2406,8 +2509,15 @@ int ha_connect::rnd_init(bool scan)
               (xp) ? xp->g : NULL);
   DBUG_ENTER("ha_connect::rnd_init");
 
+  // This is not tested yet
+  if (xmod == MODE_ALTER) {
+    xmod= MODE_READ;
+    alter= 1;
+    } // endif xmod
+
   if (xtrace)
-    printf("%p in rnd_init: scan=%d\n", this, scan);
+    printf("rnd_init: this=%p scan=%d xmod=%d alter=%d\n", 
+            this, scan, xmod, alter);
 
   if (!g || !table || xmod == MODE_INSERT)
     DBUG_RETURN(HA_ERR_INITIALIZATION);
@@ -2632,7 +2742,8 @@ int ha_connect::info(uint flag)
   if (!valid_info) {
     // tdbp must be available to get updated info
     if (xp->CheckQuery(valid_query_id) || !tdbp) {
-      if (xmod == MODE_ANY) {               // Pure info, not a query
+      if (xmod == MODE_ANY || xmod == MODE_ALTER) {
+        // Pure info, not a query
         pure= true;
         xp->CheckCleanup();
         } // endif xmod
@@ -2752,19 +2863,9 @@ int ha_connect::delete_all_rows()
 bool ha_connect::check_privileges(THD *thd, PTOS options, char *dbn)
 {
   const char *db= (dbn && *dbn) ? dbn : NULL;
+  TABTYPE     type=GetRealType(options);
 
-  if (!options->type) {
-    if (options->srcdef)
-      options->type= "MYSQL";
-    else if (options->tabname)
-      options->type= "PROXY";
-    else
-      options->type= "DOS";
-
-    } // endif type
-
-  switch (GetTypeID(options->type))
-  {
+  switch (type) {
     case TAB_UNDEF:
 //  case TAB_CATLG:
     case TAB_PLG:
@@ -2784,18 +2885,30 @@ bool ha_connect::check_privileges(THD *thd, PTOS options, char *dbn)
     case TAB_XML:
     case TAB_INI:
     case TAB_VEC:
-      if (!options->filename)
+      if (options->filename && *options->filename) {
+        char *s, path[FN_REFLEN], dbpath[FN_REFLEN];
+#if defined(WIN32)
+  		  s= "\\";
+#else   // !WIN32
+  		  s= "/";
+#endif  // !WIN32
+        strcpy(dbpath, mysql_real_data_home);
+    
+        if (db)
+          strcat(strcat(dbpath, db), s);
+    
+        (void) fn_format(path, options->filename, dbpath, "",
+                         MY_RELATIVE_PATH | MY_UNPACK_FILENAME);
+
+        if (!is_secure_file_path(path)) {
+          my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
+          return true;
+          } // endif path
+
+      } else
         return false;
-      char path[FN_REFLEN];
-      (void) fn_format(path, options->filename, mysql_real_data_home, "",
-                       MY_RELATIVE_PATH | MY_UNPACK_FILENAME);
-      if (!is_secure_file_path(path))
-      {
-        my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
-        return true;
-      }
-      /* Fall through to check FILE_ACL */
 
+      /* Fall through to check FILE_ACL */
     case TAB_ODBC:
     case TAB_MYSQL:
     case TAB_DIR:
@@ -2811,7 +2924,7 @@ bool ha_connect::check_privileges(THD *thd, PTOS options, char *dbn)
     case TAB_OCCUR:
     case TAB_PIVOT:
       return false;
-  }
+    } // endswitch type
 
   my_printf_error(ER_UNKNOWN_ERROR, "check_privileges failed", MYF(0));
   return true;
@@ -2883,7 +2996,6 @@ MODE ha_connect::CheckMode(PGLOBAL g, THD *thd,
         break;
       case SQLCOM_DROP_TABLE:
       case SQLCOM_RENAME_TABLE:
-      case SQLCOM_ALTER_TABLE:
         newmode= MODE_ANY;
         break;
       case SQLCOM_DROP_INDEX:
@@ -2895,6 +3007,9 @@ MODE ha_connect::CheckMode(PGLOBAL g, THD *thd,
       case SQLCOM_DROP_VIEW:
         newmode= MODE_ANY;
         break;
+      case SQLCOM_ALTER_TABLE:
+        newmode= MODE_ALTER;
+        break;
       default:
         printf("Unsupported sql_command=%d", thd_sql_command(thd));
         strcpy(g->Message, "CONNECT Unsupported command");
@@ -2926,7 +3041,6 @@ MODE ha_connect::CheckMode(PGLOBAL g, THD *thd,
         break;
       case SQLCOM_DROP_INDEX:
       case SQLCOM_CREATE_INDEX:
-      case SQLCOM_ALTER_TABLE:
         *chk= true;
 //      stop= true;
       case SQLCOM_DROP_TABLE:
@@ -2937,6 +3051,10 @@ MODE ha_connect::CheckMode(PGLOBAL g, THD *thd,
       case SQLCOM_DROP_VIEW:
         newmode= MODE_ANY;
         break;
+      case SQLCOM_ALTER_TABLE:
+        *chk= true;
+        newmode= MODE_ALTER;
+        break;
       default:
         printf("Unsupported sql_command=%d", thd_sql_command(thd));
         strcpy(g->Message, "CONNECT Unsupported command");
@@ -3023,7 +3141,8 @@ int ha_connect::external_lock(THD *thd, int lock_type)
   DBUG_ASSERT(thd == current_thd);
 
   if (xtrace)
-    printf("%p external_lock: lock_type=%d\n", this, lock_type);
+    printf("external_lock: this=%p thd=%p xp=%d g=%p lock_type=%d\n",
+            this, thd, xp, g, lock_type);
 
   if (!g)
     DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
@@ -3043,13 +3162,17 @@ int ha_connect::external_lock(THD *thd, int lock_type)
     } // endswitch mode
 
   if (newmode == MODE_ANY) {
+    int sqlcom= thd_sql_command(thd);
+
     // This is unlocking, do it by closing the table
-    if (xp->CheckQueryID() && thd_sql_command(thd) != SQLCOM_UNLOCK_TABLES
-                           && thd_sql_command(thd) != SQLCOM_LOCK_TABLES)
+    if (xp->CheckQueryID() && sqlcom != SQLCOM_UNLOCK_TABLES
+                           && sqlcom != SQLCOM_LOCK_TABLES)
       rc= 2;          // Logical error ???
-    else if (g->Xchk) {
-      if (!tdbp || *tdbp->GetName() == '#') {
-        if (!tdbp && !(tdbp= GetTDB(g)))
+//  else if (g->Xchk && (sqlcom == SQLCOM_CREATE_INDEX || 
+//                       sqlcom == SQLCOM_DROP_INDEX)) {
+    else if (g->Xchk) { 
+      if (!tdbp) {
+        if (!(tdbp= GetTDB(g)))
           DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
         else if (!((PTDBASE)tdbp)->GetDef()->Indexable()) {
           sprintf(g->Message, "external_lock: Table %s is not indexable", tdbp->GetName());
@@ -3132,31 +3255,21 @@ int ha_connect::external_lock(THD *thd, int lock_type)
         if (adp)
           // Here we do make the new indexes
           if (tdp->MakeIndex(g, adp, true) == RC_FX) {
-//#if defined(_DEBUG)
-            // Make it a warning to avoid crash on debug
+            // Make it a warning to avoid crash
             push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 
                               0, g->Message);
             rc= 0;
-//#else   // !_DEBUG
-//          my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
-//          rc= HA_ERR_INTERNAL_ERROR;
-//#endif  // !DEBUG
             } // endif MakeIndex
 
-        } // endif Mode
+        } // endif Tdbp
 
       } // endelse Xchk
 
     if (CloseTable(g)) {
       // This is an error while builing index
-//#if defined(_DEBUG)
-      // Make it a warning to avoid crash on debug
+      // Make it a warning to avoid crash
       push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, g->Message);
       rc= 0;
-//#else   // !_DEBUG
-//      my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
-//      rc= HA_ERR_INTERNAL_ERROR;
-//#endif  // !DEBUG
       } // endif Close
 
     locked= 0;
@@ -3183,19 +3296,32 @@ int ha_connect::external_lock(THD *thd, int lock_type)
     valid_info= false;
     } // endif CheckCleanup
 
+#if 0
   if (xcheck) {
     // This must occur after CheckCleanup
-    g->Xchk= new(g) XCHK;
-    ((PCHK)g->Xchk)->oldsep= GetBooleanOption("Sepindex", false);
-    ((PCHK)g->Xchk)->oldpix= GetIndexInfo();
+    if (!g->Xchk) {
+      g->Xchk= new(g) XCHK;
+      ((PCHK)g->Xchk)->oldsep= GetBooleanOption("Sepindex", false);
+      ((PCHK)g->Xchk)->oldpix= GetIndexInfo();
+      } // endif Xchk
+
   } else
   	g->Xchk= NULL;
+#endif // 0
 
   if (cras)
     g->Createas= 1;       // To tell created table to ignore FLAG
 
-  if (xtrace)
-    printf("Calling CntCheckDB db=%s\n", GetDBName(NULL));
+  if (xtrace) {
+#if 0
+    printf("xcheck=%d cras=%d\n", xcheck, cras);
+
+    if (xcheck)
+      printf("oldsep=%d oldpix=%p\n",
+              ((PCHK)g->Xchk)->oldsep, ((PCHK)g->Xchk)->oldpix);
+#endif // 0
+    printf("Calling CntCheckDB db=%s cras=%d\n", GetDBName(NULL), cras);
+    } // endif xtrace
 
   // Set or reset the good database environment
   if (CntCheckDB(g, this, GetDBName(NULL))) {
@@ -3212,7 +3338,7 @@ int ha_connect::external_lock(THD *thd, int lock_type)
       else
         tdbp= NULL;
 
-      }// endif tdbp
+      } // endif tdbp
 
     xmod= newmode;
 
@@ -3330,7 +3456,6 @@ filename_to_dbname_and_tablename(const char *filename,
   return false;
 } // end of filename_to_dbname_and_tablename
 
-
 /**
   @brief
   Used to delete or rename a table. By the time delete_table() has been
@@ -3355,55 +3480,86 @@ filename_to_dbname_and_tablename(const char *filename,
 int ha_connect::delete_or_rename_table(const char *name, const char *to)
 {
   DBUG_ENTER("ha_connect::delete_or_rename_table");
-  /* We have to retrieve the information about this table options. */
-  ha_table_option_struct *pos;
-  char         key[MAX_DBKEY_LENGTH], db[128], tabname[128];
-  int          rc= 0;
-  uint         key_length;
-  TABLE_SHARE *share;
-  THD         *thd= current_thd;
+  char db[128], tabname[128];
+  int  rc= 0;
+  bool ok= false;
+  THD *thd= current_thd;
+  int  sqlcom= thd_sql_command(thd);
+
+  if (xtrace) {
+    if (to)
+      printf("rename_table: this=%p thd=%p sqlcom=%d from=%s to=%s\n", 
+              this, thd, sqlcom, name, to);
+    else
+      printf("delete_table: this=%p thd=%p sqlcom=%d name=%s\n",
+              this, thd, sqlcom, name);
+
+    } // endif xtrace
 
   if (to && (filename_to_dbname_and_tablename(to, db, sizeof(db),
-                                             tabname, sizeof(tabname)) ||
-             *tabname == '#'))
-    goto fin;
+                                             tabname, sizeof(tabname))
+      || (*tabname == '#' && sqlcom == SQLCOM_CREATE_INDEX)))
+    DBUG_RETURN(0);
 
   if (filename_to_dbname_and_tablename(name, db, sizeof(db),
-                                       tabname, sizeof(tabname)) ||
-      *tabname == '#')
-    goto fin;
+                                       tabname, sizeof(tabname))
+      || (*tabname == '#' && sqlcom == SQLCOM_CREATE_INDEX))
+    DBUG_RETURN(0);
 
-  key_length= tdc_create_key(key, db, tabname);
+  // If a temporary file exists, all the tests below were passed
+  // successfully when making it, so they are not needed anymore
+  // in particular because they sometimes cause DBUG_ASSERT crash.
+  if (*tabname != '#') {
+    // We have to retrieve the information about this table options.
+    ha_table_option_struct *pos;
+    char         key[MAX_DBKEY_LENGTH];
+    uint         key_length;
+    TABLE_SHARE *share;
 
-  // share contains the option struct that we need
-  if (!(share= alloc_table_share(db, tabname, key, key_length)))
-    goto fin;
+    key_length= tdc_create_key(key, db, tabname);
 
-  // Get the share info from the .frm file
-  if (open_table_def(thd, share))
-    goto err;
+    // share contains the option struct that we need
+    if (!(share= alloc_table_share(db, tabname, key, key_length)))
+      DBUG_RETURN(rc);
 
-  // Now we can work
-  pos= share->option_struct;
+#if 0
+    if (*tabname == '#') {
+      // These are in ???? charset after renaming
+      char *p= strchr(share->path.str, '@');
+      strcpy(p, share->table_name.str);
+      share->path.length= strlen(share->path.str);
+      share->normalized_path.length= share->path.length; 
+      } // endif tabname
+#endif // 0
+
+    // Get the share info from the .frm file
+    if (!open_table_def(thd, share)) {
+      // Now we can work
+      if ((pos= share->option_struct)) {
+        if (check_privileges(thd, pos, db))
+          rc= HA_ERR_INTERNAL_ERROR;         // ???
+        else
+          if (IsFileType(GetRealType(pos)) && !pos->filename)
+            ok= true;
+  
+        } // endif pos
+
+    } else       // Avoid infamous DBUG_ASSERT
+      thd->get_stmt_da()->reset_diagnostics_area();
 
-  if (check_privileges(thd, pos, db))
-  {
     free_table_share(share);
-    DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
-  }
+  } else              // Temporary file
+    ok= true;
 
-  if (IsFileType(GetTypeID(pos->type)) && !pos->filename) {
+  if (ok) {
     // Let the base handler do the job
     if (to)
       rc= handler::rename_table(name, to);
-    else
-      rc= handler::delete_table(name);
-    } // endif filename
+    else if ((rc= handler::delete_table(name)) == ENOENT)
+      rc= 0;        // No files is not an error for CONNECT
+
+    } // endif ok
 
-  // Done no more need for this
- err:
-  free_table_share(share);
- fin:
   DBUG_RETURN(rc);
 } // end of delete_or_rename_table
 
@@ -4113,6 +4269,13 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
       else
         ok= true;
 
+      break;
+    case TAB_OEM:
+      if (topt->module && topt->subtype)
+        ok= true;
+      else
+        strcpy(g->Message, "Missing OEM module or subtype");
+
       break;
     default:
       sprintf(g->Message, "Cannot get column info for table type %s", topt->type);
@@ -4217,6 +4380,9 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
       case TAB_PIVOT:
         qrp= PivotColumns(g, tab, src, pic, fcl, host, db, user, pwd, port);
         break;
+      case TAB_OEM:
+        qrp= OEMColumns(g, topt, tab, (char*)db, fnc == FNC_COL);
+        break;
       default:
         strcpy(g->Message, "System error during assisted discovery");
         break;
@@ -4236,6 +4402,9 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
         dec= crp->Prec;
         flg= crp->Flag;
      
+        if (!len && typ == TYPE_STRING)
+          len= 256;      // STRBLK's have 0 length
+
 #if defined(NEW_WAY)
         // Now add the field
         rc= add_fields(g, thd, &alter_info, cnm, typ, len, dec,
@@ -4422,8 +4591,15 @@ int ha_connect::create(const char *name, TABLE *table_arg,
   PGLOBAL g= xp->g;
 
   DBUG_ENTER("ha_connect::create");
+  int  sqlcom= thd_sql_command(table_arg->in_use);
   PTOS options= GetTableOptionStruct(table_arg);
 
+  table= table_arg;         // Used by called functions
+
+  if (xtrace)
+    printf("create: this=%p thd=%p xp=%p g=%p sqlcom=%d name=%s\n",
+           this, thd, xp, g, sqlcom, GetTableName());
+
   // CONNECT engine specific table options:
   DBUG_ASSERT(options);
   type= GetTypeID(options->type);
@@ -4682,83 +4858,89 @@ int ha_connect::create(const char *name, TABLE *table_arg,
 
     } // endfor field
 
-  table= table_arg;         // Used by called functions
-
-  if (IsFileType(type)) {
-    if (!options->filename) {
-      // The file name is not specified, create a default file in
-      // the database directory named table_name.table_type.
-      // (temporarily not done for XML because a void file causes
-      // the XML parsers to report an error on the first Insert)
-      char buf[256], fn[_MAX_PATH], dbpath[128], lwt[12];
-      int  h;
-
-      strcpy(buf, GetTableName());
-
-      if (*buf != '#') {
-        // Check for incompatible options
-        if (options->sepindex) {
-          my_message(ER_UNKNOWN_ERROR,
-                "SEPINDEX is incompatible with unspecified file name",
-                MYF(0));
-          DBUG_RETURN(HA_ERR_UNSUPPORTED);
-        } else if (GetTypeID(options->type) == TAB_VEC)
-          if (!table->s->max_rows || options->split) {
-            my_printf_error(ER_UNKNOWN_ERROR, 
-                "%s tables whose file name is unspecified cannot be split",
-                MYF(0), options->type);
-            DBUG_RETURN(HA_ERR_UNSUPPORTED);
-          } else if (options->header == 2) {
-            my_printf_error(ER_UNKNOWN_ERROR, 
-            "header=2 is not allowed for %s tables whose file name is unspecified",
-                MYF(0), options->type);
-            DBUG_RETURN(HA_ERR_UNSUPPORTED);
-          } // endif's
-
-        // Fold type to lower case
-        for (int i= 0; i < 12; i++)
-          if (!options->type[i]) {
-            lwt[i]= 0;
-            break;
-          } else
-            lwt[i]= tolower(options->type[i]);
-        
-        strcat(strcat(buf, "."), lwt);
-        sprintf(g->Message, "No file name. Table will use %s", buf);
-        push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, g->Message);
-        strcat(strcat(strcpy(dbpath, "./"), table->s->db.str), "/");
-        PlugSetPath(fn, buf, dbpath);
+  if ((sqlcom == SQLCOM_CREATE_TABLE || *GetTableName() == '#') 
+        && IsFileType(type) && !options->filename) {
+    // The file name is not specified, create a default file in
+    // the database directory named table_name.table_type.
+    // (temporarily not done for XML because a void file causes
+    // the XML parsers to report an error on the first Insert)
+    char buf[256], fn[_MAX_PATH], dbpath[128], lwt[12];
+    int  h;
+
+    strcpy(buf, GetTableName());
+
+    // Check for incompatible options
+    if (options->sepindex) {
+      my_message(ER_UNKNOWN_ERROR,
+            "SEPINDEX is incompatible with unspecified file name",
+            MYF(0));
+      DBUG_RETURN(HA_ERR_UNSUPPORTED);
+    } else if (GetTypeID(options->type) == TAB_VEC)
+      if (!table->s->max_rows || options->split) {
+        my_printf_error(ER_UNKNOWN_ERROR, 
+            "%s tables whose file name is unspecified cannot be split",
+            MYF(0), options->type);
+        DBUG_RETURN(HA_ERR_UNSUPPORTED);
+      } else if (options->header == 2) {
+        my_printf_error(ER_UNKNOWN_ERROR, 
+        "header=2 is not allowed for %s tables whose file name is unspecified",
+            MYF(0), options->type);
+        DBUG_RETURN(HA_ERR_UNSUPPORTED);
+      } // endif's
+
+    // Fold type to lower case
+    for (int i= 0; i < 12; i++)
+      if (!options->type[i]) {
+        lwt[i]= 0;
+        break;
+      } else
+        lwt[i]= tolower(options->type[i]);
     
-        if ((h= ::open(fn, O_CREAT | O_EXCL, 0666)) == -1) {
-          if (errno == EEXIST)
-            sprintf(g->Message, "Default file %s already exists", fn);
-          else
-            sprintf(g->Message, "Error %d creating file %s", errno, fn);
-
-          push_warning(table->in_use, 
-                       Sql_condition::WARN_LEVEL_WARN, 0, g->Message);
-        } else
-          ::close(h);
+    strcat(strcat(buf, "."), lwt);
+    sprintf(g->Message, "No file name. Table will use %s", buf);
+    push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, g->Message);
+    strcat(strcat(strcpy(dbpath, "./"), table->s->db.str), "/");
+    PlugSetPath(fn, buf, dbpath);
     
-        if (type == TAB_FMT || options->readonly)
-          push_warning(table->in_use, Sql_condition::WARN_LEVEL_WARN, 0,
-            "Congratulation, you just created a read-only void table!");
+    if ((h= ::open(fn, O_CREAT | O_EXCL, 0666)) == -1) {
+      if (errno == EEXIST)
+        sprintf(g->Message, "Default file %s already exists", fn);
+      else
+        sprintf(g->Message, "Error %d creating file %s", errno, fn);
 
-        } // endif buf
+      push_warning(table->in_use, 
+                   Sql_condition::WARN_LEVEL_WARN, 0, g->Message);
+    } else
+      ::close(h);
+    
+    if (type == TAB_FMT || options->readonly)
+      push_warning(table->in_use, Sql_condition::WARN_LEVEL_WARN, 0,
+        "Congratulation, you just created a read-only void table!");
 
-      } // endif filename
+    } // endif
 
-    } // endif type
+  if (xtrace)
+    printf("xchk=%d createas=%d\n", g->Xchk, g->Createas);
 
-  // To check whether indexes have to be made or remade
+  // To check whether indices have to be made or remade
   if (!g->Xchk) {
     PIXDEF xdp;
 
-    // We should be in CREATE TABLE
-    if (thd_sql_command(table->in_use) != SQLCOM_CREATE_TABLE)
+    // We should be in CREATE TABLE or ALTER_TABLE
+    if (sqlcom != SQLCOM_CREATE_TABLE && sqlcom != SQLCOM_ALTER_TABLE)
       push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0,
         "Wrong command in create, please contact CONNECT team");
 
+    if (sqlcom == SQLCOM_ALTER_TABLE && g->Alchecked == 0 &&
+        (!IsFileType(type) || FileExists(options->filename))) {
+      // This is an ALTER to CONNECT from another engine.
+      // It cannot be accepted because the table data would be lost
+      // except when the target file does not exist.
+      strcpy(g->Message, "Operation denied. Table data would be lost.");
+      my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
+      DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
+      } // endif outward
+
     // Get the index definitions
     if (xdp= GetIndexInfo()) {
       if (IsTypeIndexable(type)) {
@@ -4786,7 +4968,13 @@ int ha_connect::create(const char *name, TABLE *table_arg,
       } // endif xdp
 
   } else {
+    // This should not happen anymore with indexing new way
+    my_message(ER_UNKNOWN_ERROR,
+               "CONNECT index modification should be in-place", MYF(0));
+    DBUG_RETURN(HA_ERR_UNSUPPORTED);
+#if 0
     PIXDEF xdp= GetIndexInfo();
+    PCHK   xcp= (PCHK)g->Xchk;
 
     if (xdp) {
       if (!IsTypeIndexable(type)) {
@@ -4795,19 +4983,356 @@ int ha_connect::create(const char *name, TABLE *table_arg,
         my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
         rc= HA_ERR_INTERNAL_ERROR;
       } else {
-        ((PCHK)g->Xchk)->newpix= xdp;
-        ((PCHK)g->Xchk)->newsep= GetBooleanOption("Sepindex", false);
+        xcp->newpix= xdp;
+        xcp->newsep= GetBooleanOption("Sepindex", false);
       } // endif Indexable
 
-    } else if (!((PCHK)g->Xchk)->oldpix)
+    } else if (!xcp->oldpix)
       g->Xchk= NULL;
 
+    if (xtrace && g->Xchk)
+      printf("oldsep=%d newsep=%d oldpix=%p newpix=%p\n",
+              xcp->oldsep, xcp->newsep, xcp->oldpix, xcp->newpix);
+
+//  if (g->Xchk && 
+//      (sqlcom != SQLCOM_CREATE_INDEX && sqlcom != SQLCOM_DROP_INDEX)) {
+    if (g->Xchk) {
+      PIXDEF xp1, xp2;
+      bool   b= false;        // true if index changes
+
+      if (xcp->oldsep == xcp->newsep) {
+        for (xp1= xcp->newpix, xp2= xcp->oldpix; 
+             xp1 || xp2; 
+             xp1= xp1->Next, xp2= xp2->Next)
+          if (!xp1 || !xp2 || !IsSameIndex(xp1, xp2)) {
+            b= true;
+            break;
+            } // endif xp1
+
+      } else
+        b= true;
+
+      if (!b)
+        g->Xchk= NULL;
+
+#if 0
+      if (b) {
+        // CONNECT does not support indexing via ALTER TABLE
+        my_message(ER_UNKNOWN_ERROR,
+           "CONNECT does not support index modification via ALTER TABLE",
+           MYF(0));
+        DBUG_RETURN(HA_ERR_UNSUPPORTED);
+        } // endif b
+#endif // 0
+
+      } // endif Xchk
+
+#endif // 0
   } // endif Xchk
 
   table= st;
   DBUG_RETURN(rc);
 } // end of create
 
+/**
+  Used to check whether a file based outward table can be populated by
+  an ALTER TABLE command. The conditions are:
+  - file does not exist or is void
+  - user has file privilege
+*/
+bool ha_connect::FileExists(const char *fn)
+{
+  if (!fn || !*fn)
+    return false;
+
+  if (table) {
+    char *s, filename[_MAX_PATH], path[128];
+    int   n;
+    struct stat info;
+
+    if (check_access(ha_thd(), FILE_ACL, table->s->db.str,
+                     NULL, NULL, 0, 0))
+      return true;
+
+#if defined(WIN32)
+		s= "\\";
+#else   // !WIN32
+		s= "/";
+#endif  // !WIN32
+
+    strcat(strcat(strcat(strcpy(path, "."), s), table->s->db.str), s);
+    PlugSetPath(filename, fn, path);
+    n= stat(filename, &info);
+
+    if (n < 0) {
+      if (errno != ENOENT) {
+        char buf[_MAX_PATH + 20];
+
+        sprintf(buf, "Error %d for file %s", errno, filename);
+        push_warning(table->in_use, Sql_condition::WARN_LEVEL_WARN, 0, buf);
+        return true;
+      } else
+        return false;
+
+    } else
+      return (info.st_size) ? true : false;
+
+    } // endif table
+
+  return true;
+} // end of FileExists
+
+/**
+  check whether a string option have changed
+  */
+bool ha_connect::SameChar(TABLE *tab, char *opn)
+{
+  char *str1, *str2;
+  bool  b1, b2;
+
+  tshp= tab->s;                 // The altered table
+  str1= GetStringOption(opn);
+  tshp= NULL;
+  str2= GetStringOption(opn);
+  b1= (!str1 || !*str1);
+  b2= (!str2 || !*str2);
+
+  if (b1 && b2)
+    return true;
+  else if ((b1 && !b2) || (!b1 && b2) || stricmp(str1, str2))
+    return false;
+
+  return true;
+} // end of SameChar
+
+/**
+  check whether a Boolean option have changed
+  */
+bool ha_connect::SameBool(TABLE *tab, char *opn)
+{
+  bool b1, b2;
+
+  tshp= tab->s;                 // The altered table
+  b1= GetBooleanOption(opn, false);
+  tshp= NULL;
+  b2= GetBooleanOption(opn, false);
+  return (b1 == b2);
+} // end of SameBool
+
+/**
+  check whether an integer option have changed
+  */
+bool ha_connect::SameInt(TABLE *tab, char *opn)
+{
+  int i1, i2;
+
+  tshp= tab->s;                 // The altered table
+  i1= GetIntegerOption(opn);
+  tshp= NULL;
+  i2= GetIntegerOption(opn);
+
+  if (!stricmp(opn, "lrecl"))
+    return (i1 == i2 || !i1 || !i2);
+  else if (!stricmp(opn, "ending"))
+    return (i1 == i2 || i1 <= 0 || i2 <= 0);
+  else
+    return (i1 == i2);
+
+} // end of SameInt
+
+
+ /**
+    Check if a storage engine supports a particular alter table in-place
+
+    @param    altered_table     TABLE object for new version of table.
+    @param    ha_alter_info     Structure describing changes to be done
+                                by ALTER TABLE and holding data used
+                                during in-place alter.
+
+    @retval   HA_ALTER_ERROR                  Unexpected error.
+    @retval   HA_ALTER_INPLACE_NOT_SUPPORTED  Not supported, must use copy.
+    @retval   HA_ALTER_INPLACE_EXCLUSIVE_LOCK Supported, but requires X lock.
+    @retval   HA_ALTER_INPLACE_SHARED_LOCK_AFTER_PREPARE
+                                              Supported, but requires SNW lock
+                                              during main phase. Prepare phase
+                                              requires X lock.
+    @retval   HA_ALTER_INPLACE_SHARED_LOCK    Supported, but requires SNW lock.
+    @retval   HA_ALTER_INPLACE_NO_LOCK_AFTER_PREPARE
+                                              Supported, concurrent reads/writes
+                                              allowed. However, prepare phase
+                                              requires X lock.
+    @retval   HA_ALTER_INPLACE_NO_LOCK        Supported, concurrent
+                                              reads/writes allowed.
+
+    @note The default implementation uses the old in-place ALTER API
+    to determine if the storage engine supports in-place ALTER or not.
+
+    @note Called without holding thr_lock.c lock.
+ */
+enum_alter_inplace_result
+ha_connect::check_if_supported_inplace_alter(TABLE *altered_table,
+                                          Alter_inplace_info *ha_alter_info)
+{
+  DBUG_ENTER("check_if_supported_alter");
+
+  bool            idx= false, outward= false;
+  THD            *thd= ha_thd();
+  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;
+
+  if (!g || !table) {
+    my_message(ER_UNKNOWN_ERROR, "Cannot check ALTER operations", MYF(0));
+    DBUG_RETURN(HA_ALTER_ERROR);
+    } // endif Xchk
+
+  newopt= altered_table->s->option_struct;
+  oldopt= table->s->option_struct;
+
+  // If this is the start of a new query, cleanup the previous one
+  if (xp->CheckCleanup()) {
+    tdbp= NULL;
+    valid_info= false;
+    } // endif CheckCleanup
+
+  g->Alchecked= 1;       // Tested in create
+  g->Xchk= NULL;
+  type= GetRealType(oldopt);
+  newtyp= GetRealType(newopt);
+
+  // No copy algorithm for outward tables
+  outward= (!IsFileType(type) || (oldopt->filename && *oldopt->filename));
+
+  // Index operations
+  Alter_inplace_info::HA_ALTER_FLAGS index_operations=
+    Alter_inplace_info::ADD_INDEX | 
+    Alter_inplace_info::DROP_INDEX |
+    Alter_inplace_info::ADD_UNIQUE_INDEX | 
+    Alter_inplace_info::DROP_UNIQUE_INDEX |
+    Alter_inplace_info::ADD_PK_INDEX | 
+    Alter_inplace_info::DROP_PK_INDEX;
+
+  Alter_inplace_info::HA_ALTER_FLAGS inplace_offline_operations=
+    Alter_inplace_info::ALTER_COLUMN_EQUAL_PACK_LENGTH |
+    Alter_inplace_info::ALTER_COLUMN_NAME |
+    Alter_inplace_info::ALTER_COLUMN_DEFAULT |
+    Alter_inplace_info::CHANGE_CREATE_OPTION |
+    Alter_inplace_info::ALTER_RENAME | index_operations;
+
+  if (ha_alter_info->handler_flags & index_operations ||
+      !SameChar(altered_table, "optname") ||
+      !SameBool(altered_table, "sepindex")) {
+    if (!IsTypeIndexable(type)) {
+      sprintf(g->Message, "Table type %s is not indexable", oldopt->type);
+      my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
+      DBUG_RETURN(HA_ALTER_ERROR);
+     } // endif Indexable
+
+    g->Xchk= new(g) XCHK;
+    PCHK xcp= (PCHK)g->Xchk;
+
+    xcp->oldpix= GetIndexInfo(table->s);
+    xcp->newpix= GetIndexInfo(altered_table->s);
+    xcp->oldsep= GetBooleanOption("sepindex", false);
+    xcp->oldsep= xcp->SetName(g, GetStringOption("optname"));
+    tshp= altered_table->s;
+    xcp->newsep= GetBooleanOption("sepindex", false);
+    xcp->newsep= xcp->SetName(g, GetStringOption("optname"));
+    tshp= NULL;
+
+    if (xtrace && g->Xchk)
+      printf(
+        "oldsep=%d newsep=%d oldopn=%s newopn=%s oldpix=%p newpix=%p\n",
+              xcp->oldsep, xcp->newsep, 
+              SVP(xcp->oldopn), SVP(xcp->newopn), 
+              xcp->oldpix, xcp->newpix);
+
+    if (sqlcom == SQLCOM_ALTER_TABLE)
+      idx= true;
+    else
+      DBUG_RETURN(HA_ALTER_INPLACE_EXCLUSIVE_LOCK);
+
+    } // endif index operation
+
+    if (!SameChar(altered_table, "filename")) {
+      if (!outward) {
+        // Conversion to outward table is only allowed for file based
+        // tables whose file does not exist.
+        tshp= altered_table->s;
+        char *fn= GetStringOption("filename");
+        tshp= NULL;
+
+        if (FileExists(fn)) {
+          strcpy(g->Message, "Operation denied. Table data would be lost.");
+          my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
+          DBUG_RETURN(HA_ALTER_ERROR);
+        } else
+          goto fin;
+
+      } else
+        goto fin;
+
+      } // endif filename
+
+  /* Is there at least one operation that requires copy algorithm? */
+  if (ha_alter_info->handler_flags & ~inplace_offline_operations)
+    goto fin;
+
+  /*
+    ALTER TABLE tbl_name CONVERT TO CHARACTER SET .. and
+    ALTER TABLE table_name DEFAULT CHARSET = .. most likely
+    change column charsets and so not supported in-place through
+    old API.
+
+    Changing of PACK_KEYS, MAX_ROWS and ROW_FORMAT options were
+    not supported as in-place operations in old API either.
+  */
+  if (create_info->used_fields & (HA_CREATE_USED_CHARSET |
+                                  HA_CREATE_USED_DEFAULT_CHARSET |
+                                  HA_CREATE_USED_PACK_KEYS |
+                                  HA_CREATE_USED_MAX_ROWS) ||
+      (table->s->row_type != create_info->row_type))
+    goto fin;
+
+#if 0
+  uint table_changes= (ha_alter_info->handler_flags &
+                       Alter_inplace_info::ALTER_COLUMN_EQUAL_PACK_LENGTH) ?
+    IS_EQUAL_PACK_LENGTH : IS_EQUAL_YES;
+
+  if (table->file->check_if_incompatible_data(create_info, table_changes)
+      == COMPATIBLE_DATA_YES)
+    DBUG_RETURN(HA_ALTER_INPLACE_EXCLUSIVE_LOCK);
+#endif // 0
+
+  // This was in check_if_incompatible_data
+  if (type == newtyp &&
+      SameInt(altered_table, "lrecl") &&
+      SameInt(altered_table, "elements") &&
+      SameInt(altered_table, "header") &&
+      SameInt(altered_table, "quoted") &&
+      SameInt(altered_table, "ending") &&
+      SameInt(altered_table, "compressed"))
+    DBUG_RETURN(HA_ALTER_INPLACE_EXCLUSIVE_LOCK);
+
+fin:
+  if (idx) {
+    // Indexing is only supported inplace
+    my_message(ER_UNKNOWN_ERROR, 
+      "Alter operations not supported together by CONNECT", MYF(0));
+    DBUG_RETURN(HA_ALTER_ERROR);
+  } else if (outward) {
+    push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, 
+      "This is an outward table, table data were not modified.");
+    DBUG_RETURN(HA_ALTER_INPLACE_EXCLUSIVE_LOCK);
+  } else
+    DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
+
+} // end of check_if_supported_inplace_alter
+
 
 /**
   check_if_incompatible_data() called if ALTER TABLE can't detect otherwise
@@ -4818,46 +5343,17 @@ int ha_connect::create(const char *name, TABLE *table_arg,
   (sql/sql_tables.cc) to decide should we rewrite whole table or only .frm
   file.
 
+  @note: This function is no more called by check_if_supported_inplace_alter
 */
 
 bool ha_connect::check_if_incompatible_data(HA_CREATE_INFO *info,
                                         uint table_changes)
 {
-//ha_table_option_struct *param_old, *param_new;
   DBUG_ENTER("ha_connect::check_if_incompatible_data");
   // TO DO: really implement and check it.
-  THD *thd= current_thd;
-
-  push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, 
-    "The current version of CONNECT did not check what you changed in ALTER. Use at your own risk");
-  
-  if (table) {
-    PTOS newopt= info->option_struct;
-    PTOS oldopt= table->s->option_struct;
-
-#if 0
-    if (newopt->sepindex != oldopt->sepindex) {
-      // All indexes to be remade
-      PGLOBAL g= GetPlug(thd);
-
-      if (!g)
-        push_warning(thd, Sql_condition::WARN_LEVEL_WARN, 0, 
-          "Execute OPTIMIZE TABLE to remake the indexes");
-      else
-        g->Xchk= new(g) XCHK;
-
-      } // endif sepindex
-#endif // 0
-
-    if (oldopt->type != newopt->type)
-      DBUG_RETURN(COMPATIBLE_DATA_NO);
-
-    if (newopt->filename)
-      DBUG_RETURN(COMPATIBLE_DATA_NO);
-
-    } // endif table
-
-  DBUG_RETURN(COMPATIBLE_DATA_YES);
+  push_warning(ha_thd(), Sql_condition::WARN_LEVEL_WARN, 0, 
+      "Unexpected call to check_if_incompatible_data.");
+  DBUG_RETURN(COMPATIBLE_DATA_NO);
 } // end of check_if_incompatible_data
 
 
diff --git a/storage/connect/ha_connect.h b/storage/connect/ha_connect.h
index 754e2e37a7f..908c26fefdc 100644
--- a/storage/connect/ha_connect.h
+++ b/storage/connect/ha_connect.h
@@ -50,9 +50,20 @@ typedef struct _xinfo {
 
 class XCHK : public BLOCK {
 public:
-  XCHK(void) {oldsep= newsep= false; oldpix= newpix= NULL;}
+  XCHK(void) {oldsep= newsep= false; 
+              oldopn= newopn= NULL;
+              oldpix= newpix= NULL;}
+
+  inline char *SetName(PGLOBAL g, char *name) {
+    char *nm= NULL;
+    if (name) {nm= (char*)PlugSubAlloc(g, NULL, strlen(name) + 1);
+               strcpy(nm, name);}
+    return nm;}
+
   bool         oldsep;              // Sepindex before create/alter
   bool         newsep;              // Sepindex after create/alter
+  char        *oldopn;              // Optname before create/alter
+  char        *newopn;              // Optname after create/alter
   PIXDEF       oldpix;              // The indexes before create/alter
   PIXDEF       newpix;              // The indexes after create/alter
 }; // end of class XCHK
@@ -156,15 +167,20 @@ class ha_connect: public handler
   // CONNECT Implementation
   static   bool connect_init(void);
   static   bool connect_end(void);
+  TABTYPE  GetRealType(PTOS pos);
   char    *GetStringOption(char *opname, char *sdef= NULL);
   PTOS     GetTableOptionStruct(TABLE *table_arg);
   bool     GetBooleanOption(char *opname, bool bdef);
   bool     SetBooleanOption(char *opname, bool b);
   int      GetIntegerOption(char *opname);
   bool     SetIntegerOption(char *opname, int n);
+  bool     SameChar(TABLE *tab, char *opn);
+  bool     SameInt(TABLE *tab, char *opn);
+  bool     SameBool(TABLE *tab, char *opn);
+  bool     FileExists(const char *fn);
   PFOS     GetFieldOptionStruct(Field *fp);
   void    *GetColumnOption(PGLOBAL g, void *field, PCOLINFO pcf);
-  PIXDEF   GetIndexInfo(void);
+  PIXDEF   GetIndexInfo(TABLE_SHARE *s= NULL);
   const char *GetDBName(const char *name);
   const char *GetTableName(void);
 //int      GetColNameLen(Field *fp);
@@ -199,18 +215,19 @@ class ha_connect: public handler
    */
   const char **bas_ext() const;
 
+ /**
+    Check if a storage engine supports a particular alter table in-place
+    @note Called without holding thr_lock.c lock.
+ */
+ virtual enum_alter_inplace_result
+ check_if_supported_inplace_alter(TABLE *altered_table,
+                                  Alter_inplace_info *ha_alter_info);
+
   /** @brief
     This is a list of flags that indicate what functionality the storage engine
     implements. The current table flags are documented in handler.h
   */
-  ulonglong table_flags() const
-  {
-    return (HA_NO_TRANSACTIONS | HA_REC_NOT_IN_SEQ | HA_HAS_RECORDS |
-            HA_NO_AUTO_INCREMENT | HA_NO_PREFIX_CHAR_KEYS |
-            HA_NO_COPY_ON_ALTER | HA_CAN_VIRTUAL_COLUMNS |
-            HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE |
-            /*HA_NULL_IN_KEY |*/ HA_MUST_USE_TABLE_CONDITION_PUSHDOWN);
-  }
+  ulonglong table_flags() const;
 
   /** @brief
     This is a bitmap of flags that indicates how the storage engine
@@ -464,6 +481,7 @@ const char *GetValStr(OPVAL vop, bool neg);
   XINFO         xinfo;                // The table info structure
   bool          valid_info;           // True if xinfo is valid
   bool          stop;                 // Used when creating index
+  bool          alter;                // True when converting to other engine
   int           indexing;             // Type of indexing for CONNECT
   int           locked;               // Table lock
   THR_LOCK_DATA lock_data;
diff --git a/storage/connect/mycat.cc b/storage/connect/mycat.cc
index 092d38a142a..dc5db156af0 100644
--- a/storage/connect/mycat.cc
+++ b/storage/connect/mycat.cc
@@ -259,6 +259,89 @@ uint GetFuncID(const char *func)
   return fnc;
   } // end of GetFuncID
 
+/***********************************************************************/
+/*  OEMColumn: Get table column info for an OEM table.                 */
+/***********************************************************************/
+PQRYRES OEMColumns(PGLOBAL g, PTOS topt, char *tab, char *db, bool info)
+  {
+  typedef PQRYRES (__stdcall *XCOLDEF) (PGLOBAL, PVOID, char*, char*, bool);
+  const char *module, *subtype;
+  char    c, getname[40] = "Col";
+#if defined(WIN32)
+  HANDLE  hdll;               /* Handle to the external DLL            */
+#else   // !WIN32
+  void   *hdll;               /* Handle for the loaded shared library  */
+#endif  // !WIN32
+  XCOLDEF coldef = NULL;
+  PQRYRES qrp = NULL;
+
+  module = topt->module;
+  subtype = topt->subtype;
+
+  if (!module || !subtype)
+    return NULL;
+
+  // The exported name is always in uppercase
+  for (int i = 0; ; i++) {
+    c = subtype[i];
+    getname[i + 3] = toupper(c);
+    if (!c) break;
+    } // endfor i
+
+#if defined(WIN32)
+  // Load the Dll implementing the table
+  if (!(hdll = LoadLibrary(module))) {
+    char  buf[256];
+    DWORD rc = GetLastError();
+
+    sprintf(g->Message, MSG(DLL_LOAD_ERROR), rc, module);
+    FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
+                  FORMAT_MESSAGE_IGNORE_INSERTS, NULL, rc, 0,
+                  (LPTSTR)buf, sizeof(buf), NULL);
+    strcat(strcat(g->Message, ": "), buf);
+    return NULL;
+    } // endif hDll
+
+  // Get the function returning an instance of the external DEF class
+  if (!(coldef = (XCOLDEF)GetProcAddress((HINSTANCE)hdll, getname))) {
+    sprintf(g->Message, MSG(PROCADD_ERROR), GetLastError(), getname);
+    FreeLibrary((HMODULE)hdll);
+    return NULL;
+    } // endif coldef
+#else   // !WIN32
+  const char *error = NULL;
+
+  // Load the desired shared library
+  if (!(hdll = dlopen(Module, RTLD_LAZY))) {
+    error = dlerror();
+    sprintf(g->Message, MSG(SHARED_LIB_ERR), Module, SVP(error));
+    return NULL;
+    } // endif Hdll
+
+  // Get the function returning an instance of the external DEF class
+  if (!(coldef = (XCOLDEF)dlsym(hdll, getname))) {
+    error = dlerror();
+    sprintf(g->Message, MSG(GET_FUNC_ERR), getname, SVP(error));
+    dlclose(hdll);
+    return NULL;
+    } // endif coldef
+#endif  // !WIN32
+
+  // Just in case the external Get function does not set error messages
+  sprintf(g->Message, "Error getting column info from %s", subtype);
+
+  // Get the table column definition
+  qrp = coldef(g, topt, tab, db, info);
+
+#if defined(WIN32)
+  FreeLibrary((HMODULE)hdll);
+#else   // !WIN32
+  dlclose(hdll);
+#endif  // !WIN32
+
+  return qrp;
+  } // end of OEMColumns
+
 /* ------------------------- Class CATALOG --------------------------- */
 
 /***********************************************************************/
diff --git a/storage/connect/mysql-test/connect/r/bin.result b/storage/connect/mysql-test/connect/r/bin.result
index 10deb54cb2e..bbf5614b555 100644
--- a/storage/connect/mysql-test/connect/r/bin.result
+++ b/storage/connect/mysql-test/connect/r/bin.result
@@ -50,8 +50,6 @@ dept INT(4) NOT NULL FIELD_FORMAT='S'
 INSERT INTO t1 VALUES (7777,'BILL','1973-06-30',4444,5555.555,777);
 ERROR HY000: Table 't1' is read only
 ALTER TABLE t1 READONLY=NO;
-Warnings:
-Warning	1105	The current version of CONNECT did not check what you changed in ALTER. Use at your own risk
 SHOW CREATE TABLE t1;
 Table	Create Table
 t1	CREATE TABLE `t1` (
@@ -71,8 +69,6 @@ fig	name	birth	id	salary	dept
 5555	RONALD	1980-02-26	3333	4444.44	555
 7777	BILL	1973-06-30	4444	5555.56	777
 ALTER TABLE t1 READONLY=YES;
-Warnings:
-Warning	1105	The current version of CONNECT did not check what you changed in ALTER. Use at your own risk
 SHOW CREATE TABLE t1;
 Table	Create Table
 t1	CREATE TABLE `t1` (
diff --git a/storage/connect/mysql-test/connect/r/csv.result b/storage/connect/mysql-test/connect/r/csv.result
index 94fd95a5d83..3f424964881 100644
--- a/storage/connect/mysql-test/connect/r/csv.result
+++ b/storage/connect/mysql-test/connect/r/csv.result
@@ -63,8 +63,6 @@ Archibald	2001-05-17	3
 Nabucho	2003-08-12	2
 RONALD	1980-02-26	4
 ALTER TABLE t1 READONLY=no;
-Warnings:
-Warning	1105	The current version of CONNECT did not check what you changed in ALTER. Use at your own risk
 SHOW CREATE TABLE t1;
 Table	Create Table
 t1	CREATE TABLE `t1` (
@@ -80,8 +78,6 @@ Nabucho	2003-08-12	2
 RONALD	1980-02-26	4
 BILL	1973-06-30	5
 ALTER TABLE t1 READONLY=1;
-Warnings:
-Warning	1105	The current version of CONNECT did not check what you changed in ALTER. Use at your own risk
 SHOW CREATE TABLE t1;
 Table	Create Table
 t1	CREATE TABLE `t1` (
diff --git a/storage/connect/mysql-test/connect/r/dbf.result b/storage/connect/mysql-test/connect/r/dbf.result
index c7bb5739e75..bc09f85a631 100644
--- a/storage/connect/mysql-test/connect/r/dbf.result
+++ b/storage/connect/mysql-test/connect/r/dbf.result
@@ -69,8 +69,6 @@ a
 10
 20
 ALTER TABLE t1 READONLY=Yes;
-Warnings:
-Warning	1105	The current version of CONNECT did not check what you changed in ALTER. Use at your own risk
 SHOW CREATE TABLE t1;
 Table	Create Table
 t1	CREATE TABLE `t1` (
@@ -85,8 +83,6 @@ ERROR HY000: Table 't1' is read only
 TRUNCATE TABLE t1;
 ERROR HY000: Table 't1' is read only
 ALTER TABLE t1 READONLY=NO;
-Warnings:
-Warning	1105	The current version of CONNECT did not check what you changed in ALTER. Use at your own risk
 SHOW CREATE TABLE t1;
 Table	Create Table
 t1	CREATE TABLE `t1` (
@@ -508,12 +504,12 @@ DROP TABLE IF EXISTS t1;
 CREATE TABLE t1
 (
 a VARCHAR(10) NOT NULL
-) ENGINE=CONNECT TABLE_TYPE=DBF FILE_NAME='t1.dbf';
+) ENGINE=CONNECT TABLE_TYPE=DBF FILE_NAME='t1c.dbf';
 INSERT INTO t1 VALUES ('10');
 SELECT * FROM t1;
 a
 10
-CALL dbf_header('MYSQLD_DATADIR/test/t1.dbf');
+CALL dbf_header('MYSQLD_DATADIR/test/t1c.dbf');
 --------	--------
 FileSize	77
 DBF_Version	03
@@ -532,17 +528,15 @@ Dec	0
 Flags	00
 --------	--------
 ALTER TABLE t1 MODIFY a VARCHAR(10) NOT NULL;
-Warnings:
-Warning	1105	The current version of CONNECT did not check what you changed in ALTER. Use at your own risk
 SHOW CREATE TABLE t1;
 Table	Create Table
 t1	CREATE TABLE `t1` (
   `a` varchar(10) NOT NULL
-) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`=DBF `FILE_NAME`='t1.dbf'
+) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`=DBF `FILE_NAME`='t1c.dbf'
 SELECT * FROM t1;
 a
 10
-CALL dbf_header('MYSQLD_DATADIR/test/t1.dbf');
+CALL dbf_header('MYSQLD_DATADIR/test/t1c.dbf');
 --------	--------
 FileSize	77
 DBF_Version	03
@@ -561,15 +555,17 @@ Dec	0
 Flags	00
 --------	--------
 ALTER TABLE t1 MODIFY a INT(10) NOT NULL;
+Warnings:
+Warning	1105	This is an outward table, table data were not modified.
 SHOW CREATE TABLE t1;
 Table	Create Table
 t1	CREATE TABLE `t1` (
   `a` int(10) NOT NULL
-) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`=DBF `FILE_NAME`='t1.dbf'
+) ENGINE=CONNECT DEFAULT CHARSET=latin1 `TABLE_TYPE`=DBF `FILE_NAME`='t1c.dbf'
 SELECT * FROM t1;
 a
 10
-CALL dbf_header('MYSQLD_DATADIR/test/t1.dbf');
+CALL dbf_header('MYSQLD_DATADIR/test/t1c.dbf');
 --------	--------
 FileSize	77
 DBF_Version	03
diff --git a/storage/connect/mysql-test/connect/r/dir.result b/storage/connect/mysql-test/connect/r/dir.result
index f4feb5fa960..34a591fb26c 100644
--- a/storage/connect/mysql-test/connect/r/dir.result
+++ b/storage/connect/mysql-test/connect/r/dir.result
@@ -13,8 +13,6 @@ boys	.txt	282
 boys2	.txt	282
 boyswin	.txt	288
 ALTER TABLE t1 OPTION_LIST='subdir=0';
-Warnings:
-Warning	1105	The current version of CONNECT did not check what you changed in ALTER. Use at your own risk
 SHOW CREATE TABLE t1;
 Table	Create Table
 t1	CREATE TABLE `t1` (
diff --git a/storage/connect/mysql-test/connect/r/fix.result b/storage/connect/mysql-test/connect/r/fix.result
index c218561c3aa..96ba3f84a0d 100644
--- a/storage/connect/mysql-test/connect/r/fix.result
+++ b/storage/connect/mysql-test/connect/r/fix.result
@@ -22,8 +22,6 @@ SELECT * FROM t1;
 id
 10
 ALTER TABLE t1 READONLY=1;
-Warnings:
-Warning	1105	The current version of CONNECT did not check what you changed in ALTER. Use at your own risk
 SHOW CREATE TABLE t1;
 Table	Create Table
 t1	CREATE TABLE `t1` (
@@ -38,8 +36,6 @@ ERROR HY000: Table 't1' is read only
 TRUNCATE TABLE t1;
 ERROR HY000: Table 't1' is read only
 ALTER TABLE t1 READONLY=0;
-Warnings:
-Warning	1105	The current version of CONNECT did not check what you changed in ALTER. Use at your own risk
 SHOW CREATE TABLE t1;
 Table	Create Table
 t1	CREATE TABLE `t1` (
diff --git a/storage/connect/mysql-test/connect/r/index.result b/storage/connect/mysql-test/connect/r/index.result
index b365046a55d..bffaaecc785 100644
--- a/storage/connect/mysql-test/connect/r/index.result
+++ b/storage/connect/mysql-test/connect/r/index.result
@@ -37,8 +37,6 @@ SUM(brut)
 # Testing file mapping
 #
 ALTER TABLE t1 MAPPED=yes;
-Warnings:
-Warning	1105	The current version of CONNECT did not check what you changed in ALTER. Use at your own risk
 SELECT * FROM t1 LIMIT 10;
 matricule	nom	prenom	sexe	aanais	mmnais	ddentree	ddnom	brut	net	service	sitmat	formation
 5745	ESCOURCHE	BENEDICTE	2	1935	7	1962-12-01	1994-05-01	18345	14275.50	0	M	TECHN
diff --git a/storage/connect/mysql-test/connect/r/ini.result b/storage/connect/mysql-test/connect/r/ini.result
index fa03435323e..79996eb8525 100644
--- a/storage/connect/mysql-test/connect/r/ini.result
+++ b/storage/connect/mysql-test/connect/r/ini.result
@@ -185,8 +185,6 @@ UK	10
 FR	20
 RU	30
 ALTER TABLE t1 READONLY=1;
-Warnings:
-Warning	1105	The current version of CONNECT did not check what you changed in ALTER. Use at your own risk
 SHOW CREATE TABLE t1;
 Table	Create Table
 t1	CREATE TABLE `t1` (
@@ -202,8 +200,6 @@ ERROR HY000: Table 't1' is read only
 TRUNCATE TABLE t1;
 ERROR HY000: Table 't1' is read only
 ALTER TABLE t1 READONLY=0;
-Warnings:
-Warning	1105	The current version of CONNECT did not check what you changed in ALTER. Use at your own risk
 SHOW CREATE TABLE t1;
 Table	Create Table
 t1	CREATE TABLE `t1` (
diff --git a/storage/connect/mysql-test/connect/r/occur.result b/storage/connect/mysql-test/connect/r/occur.result
index a497dfc9942..fbcda4660be 100644
--- a/storage/connect/mysql-test/connect/r/occur.result
+++ b/storage/connect/mysql-test/connect/r/occur.result
@@ -193,6 +193,8 @@ Kevin	8
 Lisbeth	2
 Mary	2
 ALTER TABLE xpet MODIFY number INT NOT NULL;
+Warnings:
+Warning	1105	This is an outward table, table data were not modified.
 SELECT * FROM xpet;
 name	race	number
 John	dog	2
diff --git a/storage/connect/mysql-test/connect/r/pivot.result b/storage/connect/mysql-test/connect/r/pivot.result
index 11eee6233a4..2e4a924c8c3 100644
--- a/storage/connect/mysql-test/connect/r/pivot.result
+++ b/storage/connect/mysql-test/connect/r/pivot.result
@@ -44,8 +44,6 @@ Car  DOUBLE(8,2) FLAG=1,
 Food DOUBLE(8,2) FLAG=1)
 ENGINE=CONNECT TABLE_TYPE=PIVOT TABNAME=expenses;
 ALTER TABLE pivex OPTION_LIST='port=PORT';
-Warnings:
-Warning	1105	The current version of CONNECT did not check what you changed in ALTER. Use at your own risk
 SELECT * FROM pivex;
 Who	Week	Beer	Car	Food
 Beth	3	16.00	0.00	0.00
@@ -61,6 +59,8 @@ Joe	5	14.00	0.00	12.00
 # Restricting the columns in a Pivot Table
 #
 ALTER TABLE pivex DROP COLUMN week;
+Warnings:
+Warning	1105	This is an outward table, table data were not modified.
 SELECT * FROM pivex;
 Who	Beer	Car	Food
 Beth	51.00	0.00	29.00
@@ -81,8 +81,6 @@ SRCDEF='select who, week, what, sum(amount) as amount from expenses where week i
 Warnings:
 Warning	1105	Cannot check looping reference
 ALTER TABLE pivex OPTION_LIST='PivotCol=what,FncCol=amount,port=PORT';
-Warnings:
-Warning	1105	The current version of CONNECT did not check what you changed in ALTER. Use at your own risk
 SELECT * FROM pivex;
 Who	Week	Beer	Car	Food
 Beth	4	15.00	0.00	17.00
@@ -103,8 +101,6 @@ What CHAR(12) NOT NULL,
 `5` DOUBLE(8,2) FLAG=1)
 ENGINE=CONNECT TABLE_TYPE=PIVOT TABNAME=expenses;
 ALTER TABLE pivex OPTION_LIST='PivotCol=Week,port=PORT';
-Warnings:
-Warning	1105	The current version of CONNECT did not check what you changed in ALTER. Use at your own risk
 SELECT * FROM pivex;
 Who	What	3	4	5
 Beth	Beer	16.00	15.00	20.00
@@ -130,8 +126,6 @@ SRCDEF='select who, what, case when week=3 then ''First'' when week=5 then ''Las
 Warnings:
 Warning	1105	Cannot check looping reference
 ALTER TABLE pivex OPTION_LIST='PivotCol=wk,FncCol=amnt,port=PORT';
-Warnings:
-Warning	1105	The current version of CONNECT did not check what you changed in ALTER. Use at your own risk
 SELECT * FROM pivex;
 Who	What	First	Middle	Last
 Beth	Beer	104.96	98.40	131.20
@@ -202,8 +196,6 @@ ENGINE=CONNECT TABLE_TYPE=PIVOT TABNAME=pets OPTION_LIST='PivotCol=race,groupby=
 SELECT * FROM pivet;
 ERROR HY000: Got error 122 'Cannot find matching column' from CONNECT
 ALTER TABLE pivet OPTION_LIST='PivotCol=race,groupby=1,accept=1';
-Warnings:
-Warning	1105	The current version of CONNECT did not check what you changed in ALTER. Use at your own risk
 SELECT * FROM pivet;
 name	dog	cat
 John	2	0
diff --git a/storage/connect/mysql-test/connect/r/vec.result b/storage/connect/mysql-test/connect/r/vec.result
index 926c0f2f4c6..e93305fb07a 100644
--- a/storage/connect/mysql-test/connect/r/vec.result
+++ b/storage/connect/mysql-test/connect/r/vec.result
@@ -94,8 +94,6 @@ t1vec	.blk	8
 # Testing READONLY
 #
 ALTER TABLE t1 READONLY=yes;
-Warnings:
-Warning	1105	The current version of CONNECT did not check what you changed in ALTER. Use at your own risk
 SHOW CREATE TABLE t1;
 Table	Create Table
 t1	CREATE TABLE `t1` (
@@ -111,8 +109,6 @@ ERROR HY000: Table 't1' is read only
 TRUNCATE TABLE t1;
 ERROR HY000: Table 't1' is read only
 ALTER TABLE t1 READONLY=no;
-Warnings:
-Warning	1105	The current version of CONNECT did not check what you changed in ALTER. Use at your own risk
 SHOW CREATE TABLE t1;
 Table	Create Table
 t1	CREATE TABLE `t1` (
diff --git a/storage/connect/mysql-test/connect/r/xml.result b/storage/connect/mysql-test/connect/r/xml.result
index e412e44a9ba..aeb1f5edbcd 100644
--- a/storage/connect/mysql-test/connect/r/xml.result
+++ b/storage/connect/mysql-test/connect/r/xml.result
@@ -413,7 +413,7 @@ DROP TABLE t1;
 SET @a=LOAD_FILE('MYSQLD_DATADIR/test/t1.xml');
 SELECT CAST(@a AS CHAR CHARACTER SET latin1);
 CAST(@a AS CHAR CHARACTER SET latin1)	<?xml version="1.0" encoding="iso-8859-1"?>
-<!-- Created by CONNECT Version 1.01.0011 December 15, 2013 -->
+<!-- Created by CONNECT Version 1.02.0001 February 03, 2014 -->
 <t1>
 	<line>
 		<node>ÀÁÂÃ</node>
diff --git a/storage/connect/mysql-test/connect/t/dbf.test b/storage/connect/mysql-test/connect/t/dbf.test
index 3fd30f98f20..7b364e9b921 100644
--- a/storage/connect/mysql-test/connect/t/dbf.test
+++ b/storage/connect/mysql-test/connect/t/dbf.test
@@ -442,30 +442,32 @@ DROP TABLE IF EXISTS t1;
 --echo #
 --echo # Testing ALTER
 --echo #
+# Temporarily change the file name because ALTER that are not executed not in place
+# delete the data file when it has the same path/name than the default file name.
 CREATE TABLE t1
 (
   a VARCHAR(10) NOT NULL
-) ENGINE=CONNECT TABLE_TYPE=DBF FILE_NAME='t1.dbf';
+) ENGINE=CONNECT TABLE_TYPE=DBF FILE_NAME='t1c.dbf';
 INSERT INTO t1 VALUES ('10');
 SELECT * FROM t1;
---chmod 0777 $MYSQLD_DATADIR/test/t1.dbf
+--chmod 0777 $MYSQLD_DATADIR/test/t1c.dbf
 --vertical_results
 --replace_result $MYSQLD_DATADIR MYSQLD_DATADIR
-eval CALL dbf_header('$MYSQLD_DATADIR/test/t1.dbf');
+eval CALL dbf_header('$MYSQLD_DATADIR/test/t1c.dbf');
 --horizontal_results
 ALTER TABLE t1 MODIFY a VARCHAR(10) NOT NULL;
 SHOW CREATE TABLE t1;
 SELECT * FROM t1;
 --vertical_results
 --replace_result $MYSQLD_DATADIR MYSQLD_DATADIR
-eval CALL dbf_header('$MYSQLD_DATADIR/test/t1.dbf');
+eval CALL dbf_header('$MYSQLD_DATADIR/test/t1c.dbf');
 --horizontal_results
 ALTER TABLE t1 MODIFY a INT(10) NOT NULL;
 SHOW CREATE TABLE t1;
 SELECT * FROM t1;
 --vertical_results
 --replace_result $MYSQLD_DATADIR MYSQLD_DATADIR
-eval CALL dbf_header('$MYSQLD_DATADIR/test/t1.dbf');
+eval CALL dbf_header('$MYSQLD_DATADIR/test/t1c.dbf');
 --horizontal_results
 
 # TODO: this does not work on Windows
@@ -478,7 +480,7 @@ eval CALL dbf_header('$MYSQLD_DATADIR/test/t1.dbf');
 #eval CALL dbf_header('$MYSQLD_DATADIR/test/t1.dbf');
 #--horizontal_results
 DROP TABLE IF EXISTS t1;
---remove_file $MYSQLD_DATADIR/test/t1.dbf
+--remove_file $MYSQLD_DATADIR/test/t1c.dbf
 
 
 --echo #
diff --git a/storage/connect/plgcnx.h b/storage/connect/plgcnx.h
index 7ce72b45268..fe3997d1986 100644
--- a/storage/connect/plgcnx.h
+++ b/storage/connect/plgcnx.h
@@ -1,6 +1,6 @@
 /**************************************************************************/
 /*  PLGCNX.H                                                              */
-/*  Copyright to the author: Olivier Bertrand         2000-2012           */
+/*  Copyright to the author: Olivier Bertrand         2000-2014           */
 /*                                                                        */
 /*  This is the connection DLL's declares.                                */
 /**************************************************************************/
@@ -62,6 +62,7 @@ enum INFO {INDX_RC,                  /* Index of PlugDB return code field */
            INDX_SIZE,                /* Index of returned data size field */
            INDX_MAX};                /* Size of info array                */
 
+#ifdef NOT_USED
 /**************************************************************************/
 /*  Internal message types.                                               */
 /**************************************************************************/
@@ -97,9 +98,9 @@ enum VENDOR {VDR_UNKNOWN   = -2,     /* Not known or not connected        */
 /**************************************************************************/
 enum CKEYS {K_ProgMsg, K_Lang, K_ActiveDB, K_Cmax};
 enum LKEYS {K_NBcol, K_NBlin, K_CurPos, K_RC, K_Result, K_Elapsed,
-            K_Continued, K_Maxsize, K_Lmax, K_Maxcol,
+            K_Continued, K_Maxsize, K_Affrows, K_Lmax, K_Maxcol,
             K_Maxres, K_Maxlin, K_NBparm};
-enum NKEYS {K_Type, K_Length, K_Prec, K_DataLen, K_Nmax};
+enum NKEYS {K_Type, K_Length, K_Prec, K_DataLen, K_Unsigned, K_Nmax};
 
 /**************************************************************************/
 /*  Result description structures.                                        */
@@ -157,7 +158,6 @@ typedef struct _ResDesc {
 #define XTRN
 #endif
 
-#ifdef NOT_USED
 //#if !defined(NO_FUNC)
 #ifdef __cplusplus
 extern "C" {
@@ -172,7 +172,7 @@ XTRN bool CNXFUNC(PLGGetCharValue)(CNXKEY, char *, int, int);
 XTRN bool CNXFUNC(PLGGetIntValue)(CNXKEY, int *, int);
 XTRN bool CNXFUNC(PLGGetColValue) (CNXKEY, int *, int, int);
 XTRN bool CNXFUNC(PLGGetMessage)  (CNXKEY, char *, int);
-XTRN bool CNXFUNC(PLGGetHeader)   (CNXKEY, char *, int, int);
+XTRN bool CNXFUNC(PLGGetHeader)   (CNXKEY, char *, int, int, int);
 
 #ifdef __cplusplus
 }
diff --git a/storage/connect/plgdbsem.h b/storage/connect/plgdbsem.h
index b62979451ee..e251ded13df 100644
--- a/storage/connect/plgdbsem.h
+++ b/storage/connect/plgdbsem.h
@@ -1,7 +1,7 @@
 /************** PlgDBSem H Declares Source Code File (.H) **************/
-/*  Name: PLGDBSEM.H  Version 3.5                                      */
+/*  Name: PLGDBSEM.H  Version 3.6                                      */
 /*                                                                     */
-/*  (C) Copyright to the author Olivier BERTRAND          1998-2012    */
+/*  (C) Copyright to the author Olivier BERTRAND          1998-2014    */
 /*                                                                     */
 /*  This file contains the PlugDB++ application type definitions.      */
 /***********************************************************************/
@@ -166,7 +166,8 @@ enum MODE {MODE_ERROR   = -1,         /* Invalid mode                  */
            MODE_WRITE   = 20,         /* Input/Output mode             */
            MODE_UPDATE  = 30,         /* Input/Output mode             */
            MODE_INSERT  = 40,         /* Input/Output mode             */
-           MODE_DELETE  = 50};        /* Input/Output mode             */
+           MODE_DELETE  = 50,         /* Input/Output mode             */
+           MODE_ALTER   = 60};        /* alter mode                    */
 
 #if !defined(RC_OK_DEFINED)
 #define RC_OK_DEFINED
@@ -549,8 +550,6 @@ PPARM    Vcolist(PGLOBAL, PTDB, PSZ, bool);
 void     PlugPutOut(PGLOBAL, FILE *, short, void *, uint);
 void     PlugLineDB(PGLOBAL, PSZ, short, void *, uint);
 char    *PlgGetDataPath(PGLOBAL g);
-void    *PlgDBalloc(PGLOBAL, void *, MBLOCK&);
-void    *PlgDBrealloc(PGLOBAL, void *, MBLOCK&, size_t);
 void     AddPointer(PTABS, void *);
 PDTP     MakeDateFormat(PGLOBAL, PSZ, bool, bool, int);
 int      ExtractDate(char *, PDTP, int, int val[6]);
@@ -558,9 +557,10 @@ int      ExtractDate(char *, PDTP, int, int val[6]);
 /**************************************************************************/
 /*  Allocate the result structure that will contain result data.          */
 /**************************************************************************/
-PQRYRES PlgAllocResult(PGLOBAL g, int ncol, int maxres, int ids,
-                       int *buftyp, XFLD *fldtyp, 
-                       unsigned int *length, bool blank, bool nonull);
+DllExport PQRYRES PlgAllocResult(PGLOBAL g, int ncol, int maxres, int ids,
+                                 int *buftyp, XFLD *fldtyp, 
+                                 unsigned int *length, 
+                                 bool blank, bool nonull);
 
 /***********************************************************************/
 /*  Exported utility routines.                                         */
@@ -576,12 +576,16 @@ DllExport PCATLG  PlgGetCatalog(PGLOBAL g, bool jump = true);
 DllExport bool    PlgSetXdbPath(PGLOBAL g, PSZ, PSZ, char *, int, char *, int);
 DllExport void    PlgDBfree(MBLOCK&);
 DllExport void   *PlgDBSubAlloc(PGLOBAL g, void *memp, size_t size);
+DllExport void   *PlgDBalloc(PGLOBAL, void *, MBLOCK&);
+DllExport void   *PlgDBrealloc(PGLOBAL, void *, MBLOCK&, size_t);
 //lExport PSZ     GetIniString(PGLOBAL, void *, LPCSTR, LPCSTR, LPCSTR, LPCSTR);
 //lExport int     GetIniSize(char *, char *, char *, char *);
 //lExport bool    WritePrivateProfileInt(LPCSTR, LPCSTR, int, LPCSTR);
 DllExport void    NewPointer(PTABS, void *, void *);
 DllExport char    *GetIni(int n= 0);
 DllExport void    SetTrc(void);
+DllExport char   *GetListOption(PGLOBAL, const char *, const char *, 
+                                         const char *def=NULL);
 
 #define MSGID_NONE                         0
 #define MSGID_CANNOT_OPEN                  1
@@ -597,4 +601,4 @@ int global_open(GLOBAL *g, int msgid, const char *filename, int flags, int mode)
 DllExport LPCSTR PlugSetPath(LPSTR to, LPCSTR name, LPCSTR dir);
 char *MakeEscape(PGLOBAL g, char* str, char q);
 
-bool PushWarning(PGLOBAL, PTDBASE, int level = 1);
+DllExport bool PushWarning(PGLOBAL, PTDBASE, int level = 1);
diff --git a/storage/connect/plgdbutl.cpp b/storage/connect/plgdbutl.cpp
index b5c4239c992..c3c74463271 100644
--- a/storage/connect/plgdbutl.cpp
+++ b/storage/connect/plgdbutl.cpp
@@ -1,11 +1,11 @@
 /********** PlgDBUtl Fpe C++ Program Source Code File (.CPP) ***********/
 /* PROGRAM NAME: PLGDBUTL                                              */
 /* -------------                                                       */
-/*  Version 3.8                                                        */
+/*  Version 3.9                                                        */
 /*                                                                     */
 /* COPYRIGHT:                                                          */
 /* ----------                                                          */
-/*  (C) Copyright to the author Olivier BERTRAND          1998-2013    */
+/*  (C) Copyright to the author Olivier BERTRAND          1998-2014    */
 /*                                                                     */
 /* WHAT THIS PROGRAM DOES:                                             */
 /* -----------------------                                             */
@@ -90,6 +90,7 @@ bool  Initdone = false;
 bool  plugin = false;  // True when called by the XDB plugin handler 
 
 extern "C" {
+extern char  connectini[];
        char  plgxini[_MAX_PATH] = PLGXINI;
        char  plgini[_MAX_PATH] = PLGINI;
 #if defined(WIN32)
@@ -232,6 +233,7 @@ DllExport char *GetIni(int n)
 #if defined(XMSG)
     case 5: return msglang; break;
 #endif   // XMSG
+    case 6: return connectini; break;
 //  default: return plgini;
     } // endswitch GetIni
 
@@ -1329,7 +1331,7 @@ void *PlgDBalloc(PGLOBAL g, void *area, MBLOCK& mp)
   maxsub = (pph->FreeBlk < minsub) ? 0 : pph->FreeBlk - minsub;
   mp.Sub = mp.Size <= ((mp.Sub) ? maxsub : (maxsub >> 2));
 
-  if (trace)
+  if (trace > 1)
     htrc("PlgDBalloc: in %p size=%d used=%d free=%d sub=%d\n",
           arp, mp.Size, pph->To_Free, pph->FreeBlk, mp.Sub);
 
@@ -1372,7 +1374,7 @@ void *PlgDBrealloc(PGLOBAL g, void *area, MBLOCK& mp, size_t newsize)
 //  assert (mp.Memp != NULL);
 #endif
 
-  if (trace)
+  if (trace > 1)
     htrc("PlgDBrealloc: %p size=%d sub=%d\n", mp.Memp, mp.Size, mp.Sub);
 
   if (newsize == mp.Size)
@@ -1429,7 +1431,7 @@ void *PlgDBrealloc(PGLOBAL g, void *area, MBLOCK& mp, size_t newsize)
 /***********************************************************************/
 void PlgDBfree(MBLOCK& mp)
   {
-  if (trace)
+  if (trace > 1)
     htrc("PlgDBfree: %p sub=%d size=%d\n", mp.Memp, mp.Sub, mp.Size);
 
   if (!mp.Sub && mp.Memp)
diff --git a/storage/connect/plugutil.c b/storage/connect/plugutil.c
index ec2ac399ad0..91b850022fb 100644
--- a/storage/connect/plugutil.c
+++ b/storage/connect/plugutil.c
@@ -152,6 +152,7 @@ PGLOBAL PlugInit(LPCSTR Language, uint worksize)
     g->Sarea_Size = worksize;
     g->Trace = 0;
     g->Createas = 0;
+    g->Alchecked = 0;
     g->Activityp = g->ActivityStart = NULL;
     g->Xchk = NULL;
     strcpy(g->Message, "");
diff --git a/storage/connect/tabfix.cpp b/storage/connect/tabfix.cpp
index 2358dc07638..99063e86b57 100644
--- a/storage/connect/tabfix.cpp
+++ b/storage/connect/tabfix.cpp
@@ -331,7 +331,7 @@ void BINCOL::ReadColumn(PGLOBAL g)
   int     rc;
   PTDBFIX tdbp = (PTDBFIX)To_Tdb;
 
-  if (trace)
+  if (trace > 1)
     htrc("BIN ReadColumn: col %s R%d coluse=%.4X status=%.4X buf_type=%d\n",
       Name, tdbp->GetTdb_No(), ColUse, Status, Buf_Type);
 
diff --git a/storage/connect/table.cpp b/storage/connect/table.cpp
index efe203e8e75..37035ed752d 100644
--- a/storage/connect/table.cpp
+++ b/storage/connect/table.cpp
@@ -1,7 +1,7 @@
 /************** Table C++ Functions Source Code File (.CPP) ************/
-/*  Name: TABLE.CPP  Version 2.6                                       */
+/*  Name: TABLE.CPP  Version 2.7                                       */
 /*                                                                     */
-/*  (C) Copyright to the author Olivier BERTRAND          1999-2013    */
+/*  (C) Copyright to the author Olivier BERTRAND          1999-2014    */
 /*                                                                     */
 /*  This file contains the TBX, TDB and OPJOIN classes functions.      */
 /***********************************************************************/
@@ -262,6 +262,17 @@ PCATLG TDBASE::GetCat(void)
   return (To_Def) ? To_Def->GetCat() : NULL;
   }  // end of GetCat
 
+/***********************************************************************/
+/*  Return the pointer on the charset of this table.                   */
+/***********************************************************************/
+CHARSET_INFO *TDBASE::data_charset(void)
+  {
+  // If no DATA_CHARSET is specified, we assume that character
+  // set of the remote data is the same with CHARACTER SET 
+  // definition of the SQL column.
+  return m_data_charset ? m_data_charset : &my_charset_bin;
+  } // end of data_charset
+
 /***********************************************************************/
 /*  Return the datapath of the DB this table belongs to.               */
 /***********************************************************************/
diff --git a/storage/connect/tabmysql.cpp b/storage/connect/tabmysql.cpp
index fcf083bcbce..564eddbaf2b 100644
--- a/storage/connect/tabmysql.cpp
+++ b/storage/connect/tabmysql.cpp
@@ -1283,7 +1283,7 @@ void MYSQLCOL::ReadColumn(PGLOBAL g)
       tdbp->Fetched = TRUE;
 
   if ((buf = ((PTDBMY)To_Tdb)->Myc.GetCharField(Rank))) {
-    if (trace)
+    if (trace > 1)
       htrc("MySQL ReadColumn: name=%s buf=%s\n", Name, buf);
 
     // TODO: have a true way to differenciate temporal values
diff --git a/storage/connect/tabxml.cpp b/storage/connect/tabxml.cpp
index 5fef4fd9ef0..aa1133b0e92 100644
--- a/storage/connect/tabxml.cpp
+++ b/storage/connect/tabxml.cpp
@@ -1,9 +1,9 @@
 /************* Tabxml C++ Program Source Code File (.CPP) **************/
 /* PROGRAM NAME: TABXML                                                */
 /* -------------                                                       */
-/*  Version 2.6                                                        */
+/*  Version 2.7                                                        */
 /*                                                                     */
-/*  Author Olivier BERTRAND          2007 - 2013                       */
+/*  Author Olivier BERTRAND          2007 - 2014                       */
 /*                                                                     */
 /*  This program are the XML tables classes using MS-DOM or libxml2.   */
 /***********************************************************************/
@@ -47,6 +47,7 @@
 #include "xindex.h"
 #include "plgxml.h"
 #include "tabxml.h"
+#include "tabmul.h"
 
 extern "C" {
 extern char version[];
@@ -136,7 +137,8 @@ bool XMLDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
     } // endswitch typname
 
   Tabname = Cat->GetStringCatInfo(g, "Name", Name);  // Deprecated
-  Tabname = Cat->GetStringCatInfo(g, "Table_name", Tabname);
+  Tabname = Cat->GetStringCatInfo(g, "Table_name", Tabname); // Deprecated
+  Tabname = Cat->GetStringCatInfo(g, "Tabname", Tabname);
   Rowname = Cat->GetStringCatInfo(g, "Rownode", defrow);
   Colname = Cat->GetStringCatInfo(g, "Colnode", defcol);
   Mulnode = Cat->GetStringCatInfo(g, "Mulnode", "");
@@ -177,7 +179,12 @@ bool XMLDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
 /***********************************************************************/
 PTDB XMLDEF::GetTable(PGLOBAL g, MODE m)
   {
-  return new(g) TDBXML(this);
+  PTDBASE tdbp = new(g) TDBXML(this);
+
+  if (Multiple)
+    tdbp = new(g) TDBMUL(tdbp);
+
+  return tdbp;
   } // end of GetTable
 
 /***********************************************************************/
@@ -245,6 +252,7 @@ TDBXML::TDBXML(PXMLDEF tdp) : TDBASE(tdp)
   Void = false;
   Usedom = tdp->Usedom;
   Header = tdp->Header;
+  Multiple = tdp->Multiple;
   Nrow = -1;
   Irow = Header - 1;
   Nsub = 0;
@@ -287,6 +295,7 @@ TDBXML::TDBXML(PTDBXML tdbp) : TDBASE(tdbp)
   Void = tdbp->Void;
   Usedom = tdbp->Usedom;
   Header = tdbp->Header;
+  Multiple = tdbp->Multiple;
   Nrow = tdbp->Nrow;
   Irow = tdbp->Irow;
   Nsub = tdbp->Nsub;
@@ -578,7 +587,7 @@ bool TDBXML::Initialize(PGLOBAL g)
 #endif
   } // end of try-catches
 
-  if (Root && Columns && !Nodedone) {
+  if (Root && Columns && (Multiple || !Nodedone)) {
     // Allocate class nodes to avoid dynamic allocation
     for (colp = (PXMLCOL)Columns; colp; colp = (PXMLCOL)colp->GetNext())
       if (!colp->IsSpecial())            // Not a pseudo column
@@ -671,7 +680,10 @@ void TDBXML::SetNodeAttr(PGLOBAL g, char *attr, PXNODE node)
 int TDBXML::Cardinality(PGLOBAL g)
   {
   if (!g)
-    return (Xpand || Coltype == 2) ? 0 : 1;
+    return (Multiple || Xpand || Coltype == 2) ? 0 : 1;
+
+  if (Multiple)
+    return 10;
 
   if (Nrow < 0)
     if (Initialize(g))
@@ -685,8 +697,13 @@ int TDBXML::Cardinality(PGLOBAL g)
 /***********************************************************************/
 int TDBXML::GetMaxSize(PGLOBAL g)
   {
-  if (MaxSize < 0)
-    MaxSize = Cardinality(g) * ((Xpand) ? Limit : 1);
+  if (MaxSize < 0) {
+    if (!Multiple)
+      MaxSize = Cardinality(g) * ((Xpand) ? Limit : 1);
+    else
+      MaxSize = 10;
+
+  } // endif MaxSize
 
   return MaxSize;
   } // end of GetMaxSize
@@ -952,6 +969,34 @@ void TDBXML::CloseDB(PGLOBAL g)
     Docp->CloseDoc(g, To_Xb);
     } // endif docp
 
+  if (Multiple) {
+    // Reset all constants to start a new parse
+    Docp = NULL;
+    Root = NULL;
+    Curp = NULL;
+    DBnode = NULL;
+    TabNode = NULL;
+    RowNode = NULL;
+    ColNode = NULL;
+    Nlist = NULL;
+    Clist = NULL;
+    To_Xb = NULL;
+    Colp = NULL;
+    Changed = false;
+    Checked = false;
+    NextSame = false;
+    NewRow = false;
+    Hasnod = false;
+    Write = false;
+//  Bufdone = false;
+    Nodedone = false;
+    Void = false;
+    Nrow = -1;
+    Irow = Header - 1;
+    Nsub = 0;
+    N = 0;
+    } // endif Multiple
+
   } // end of CloseDB
 
 // ------------------------ XMLCOL functions ----------------------------
diff --git a/storage/connect/tabxml.h b/storage/connect/tabxml.h
index 5aa038530c7..817bea45b3b 100644
--- a/storage/connect/tabxml.h
+++ b/storage/connect/tabxml.h
@@ -139,6 +139,7 @@ class DllExport TDBXML : public TDBASE {
   int     Coltype;                  // Default column type
   int     Limit;                    // Limit of multiple values
   int     Header;                   // n first rows are header rows
+  int     Multiple;                 // If multiple files
   int     Nrow;                     // The table cardinality
   int     Irow;                     // The current row index
   int     Nsub;                     // The current subrow index
diff --git a/storage/connect/user_connect.cc b/storage/connect/user_connect.cc
index 877f612fc0a..b778d3f0883 100644
--- a/storage/connect/user_connect.cc
+++ b/storage/connect/user_connect.cc
@@ -146,6 +146,7 @@ bool user_connect::CheckCleanup(void)
     PlugSubSet(g, g->Sarea, g->Sarea_Size);
     g->Xchk = NULL;
     g->Createas = 0;
+    g->Alchecked = 0;
     last_query_id= thdp->query_id;
 
     if (xtrace)
diff --git a/storage/connect/valblk.cpp b/storage/connect/valblk.cpp
index bef5d6ef716..c0127072896 100644
--- a/storage/connect/valblk.cpp
+++ b/storage/connect/valblk.cpp
@@ -1,7 +1,7 @@
 /************ Valblk C++ Functions Source Code File (.CPP) *************/
-/*  Name: VALBLK.CPP  Version 2.0                                      */
+/*  Name: VALBLK.CPP  Version 2.1                                      */
 /*                                                                     */
-/*  (C) Copyright to the author Olivier BERTRAND          2005-2013    */
+/*  (C) Copyright to the author Olivier BERTRAND          2005-2014    */
 /*                                                                     */
 /*  This file contains the VALBLK and derived classes functions.       */
 /*  Second family is VALBLK, representing simple suballocated arrays   */
@@ -236,6 +236,23 @@ void TYPBLK<TYPE>::Init(PGLOBAL g, bool check)
   Global = g;
   } // end of Init
 
+/***********************************************************************/
+/*  TYPVAL GetCharString: get string representation of a typed value.  */
+/***********************************************************************/
+template <class TYPE>
+char *TYPBLK<TYPE>::GetCharString(char *p, int n)
+  {
+  sprintf(p, Fmt, Typp[n]);
+  return p;
+  } // end of GetCharString
+
+template <>
+char *TYPBLK<double>::GetCharString(char *p, int n)
+  {
+  sprintf(p, Fmt, Prec, Typp[n]);
+  return p;
+  } // end of GetCharString
+
 /***********************************************************************/
 /*  Set one value in a block.                                          */
 /***********************************************************************/
@@ -677,6 +694,14 @@ double CHRBLK::GetFloatValue(int n)
   return atof((char *)GetValPtrEx(n));
   } // end of GetFloatValue
 
+/***********************************************************************/
+/*  STRING GetCharString: get string representation of a char value.   */
+/***********************************************************************/
+char *CHRBLK::GetCharString(char *p, int n)
+  {
+  return (char *)GetValPtrEx(n);
+  } // end of GetCharString
+
 /***********************************************************************/
 /*  Set one value in a block.                                          */
 /***********************************************************************/
@@ -1185,6 +1210,22 @@ bool DATBLK::SetFormat(PGLOBAL g, PSZ fmt, int len, int year)
   return false;
   } // end of SetFormat
 
+/***********************************************************************/
+/*  DTVAL GetCharString: get string representation of a date value.    */
+/***********************************************************************/
+char *DATBLK::GetCharString(char *p, int n)
+  {
+  char *vp;
+
+  if (Dvalp) {
+    Dvalp->SetValue(Typp[n]);
+    vp = Dvalp->GetCharString(p);
+  } else
+    vp = TYPBLK<int>::GetCharString(p, n);
+
+  return vp;
+  } // end of GetCharString
+
 /***********************************************************************/
 /*  Set one value in a block from a char string.                       */
 /***********************************************************************/
diff --git a/storage/connect/valblk.h b/storage/connect/valblk.h
index debeb0669b0..1edfe7f76b4 100644
--- a/storage/connect/valblk.h
+++ b/storage/connect/valblk.h
@@ -1,7 +1,7 @@
 /*************** Valblk H Declares Source Code File (.H) ***************/
-/*  Name: VALBLK.H    Version 2.0                                      */
+/*  Name: VALBLK.H    Version 2.1                                      */
 /*                                                                     */
-/*  (C) Copyright to the author Olivier BERTRAND          2005-2013    */
+/*  (C) Copyright to the author Olivier BERTRAND          2005-2014    */
 /*                                                                     */
 /*  This file contains the VALBLK and derived classes declares.        */
 /***********************************************************************/
@@ -58,6 +58,7 @@ class VALBLK : public BLOCK {
   virtual longlong GetBigintValue(int n) = 0;
   virtual ulonglong GetUBigintValue(int n) = 0;
   virtual double GetFloatValue(int n) = 0;
+  virtual char  *GetCharString(char *p, int n) = 0;
   virtual void   ReAlloc(void *mp, int n) {Blkp = mp; Nval = n;}
   virtual void   Reset(int n) = 0;
   virtual bool   SetFormat(PGLOBAL g, PSZ fmt, int len, int year = 0);
@@ -133,6 +134,7 @@ class TYPBLK : public VALBLK {
   virtual longlong GetBigintValue(int n) {return (longlong)Typp[n];}
   virtual ulonglong GetUBigintValue(int n) {return (ulonglong)Typp[n];}
   virtual double GetFloatValue(int n) {return (double)Typp[n];}
+  virtual char  *GetCharString(char *p, int n);
   virtual void   Reset(int n) {Typp[n] = 0;}
 
   // Methods
@@ -199,6 +201,7 @@ class CHRBLK : public VALBLK {
   virtual longlong GetBigintValue(int n);
   virtual ulonglong GetUBigintValue(int n);
   virtual double GetFloatValue(int n);
+  virtual char  *GetCharString(char *p, int n);
   virtual void   Reset(int n);
   virtual void   SetPrec(int p) {Ci = (p != 0);}
   virtual bool   IsCi(void) {return Ci;}
@@ -252,6 +255,7 @@ class STRBLK : public VALBLK {
   virtual longlong GetBigintValue(int n);
   virtual ulonglong GetUBigintValue(int n);
   virtual double GetFloatValue(int n) {return atof(Strp[n]);}
+  virtual char  *GetCharString(char *p, int n) {return Strp[n];}
   virtual void   Reset(int n) {Strp[n] = NULL;}
 
   // Methods
@@ -286,10 +290,11 @@ class DATBLK : public TYPBLK<int> {
   DATBLK(void *mp, int size);
 
   // Implementation
-  virtual bool SetFormat(PGLOBAL g, PSZ fmt, int len, int year = 0);
+  virtual bool  SetFormat(PGLOBAL g, PSZ fmt, int len, int year = 0);
+  virtual char *GetCharString(char *p, int n);
 
   // Methods
-  virtual void SetValue(PSZ sp, int n);
+  virtual void  SetValue(PSZ sp, int n);
 
  protected:
   // Members
diff --git a/storage/connect/value.cpp b/storage/connect/value.cpp
index 65a08ba277e..8a839f3b50b 100644
--- a/storage/connect/value.cpp
+++ b/storage/connect/value.cpp
@@ -1,7 +1,7 @@
 /************* Value C++ Functions Source Code File (.CPP) *************/
-/*  Name: VALUE.CPP  Version 2.3                                       */
+/*  Name: VALUE.CPP  Version 2.4                                       */
 /*                                                                     */
-/*  (C) Copyright to the author Olivier BERTRAND          2001-2013    */
+/*  (C) Copyright to the author Olivier BERTRAND          2001-2014    */
 /*                                                                     */
 /*  This file contains the VALUE and derived classes family functions. */
 /*  These classes contain values of different types. They are used so  */
@@ -1142,7 +1142,11 @@ void TYPVAL<PSZ>::SetValue_psz(PSZ s)
 void TYPVAL<PSZ>::SetValue_pvblk(PVBLK blk, int n)
   {
   // STRBLK's can return a NULL pointer
-  SetValue_psz(blk->GetCharValue(n));
+  PSZ vp = blk->GetCharString(Strp, n);
+
+  if (vp != Strp)
+    SetValue_psz(vp);
+
   } // end of SetValue_pvblk
 
 /***********************************************************************/
diff --git a/storage/connect/xtable.h b/storage/connect/xtable.h
index 174ceb19731..8884860cb5b 100644
--- a/storage/connect/xtable.h
+++ b/storage/connect/xtable.h
@@ -1,7 +1,7 @@
 /**************** Table H Declares Source Code File (.H) ***************/
-/*  Name: TABLE.H    Version 2.2                                       */
+/*  Name: TABLE.H    Version 2.3                                       */
 /*                                                                     */
-/*  (C) Copyright to the author Olivier BERTRAND          1999-2012    */
+/*  (C) Copyright to the author Olivier BERTRAND          1999-2014    */
 /*                                                                     */
 /*  This file contains the TBX, OPJOIN and TDB class definitions.      */
 /***********************************************************************/
@@ -185,15 +185,7 @@ class DllExport TDBASE : public TDB {
   virtual bool   SetRecpos(PGLOBAL g, int recpos);
   virtual bool   IsReadOnly(void) {return Read_Only;}
   virtual bool   IsView(void) {return FALSE;}
-  virtual CHARSET_INFO *data_charset()
-  {
-    /*
-      If no DATA_CHARSET is specified, we assume that character
-      set of the remote data is the same with CHARACTER SET 
-      definition of the SQL column.
-    */
-    return m_data_charset ? m_data_charset : &my_charset_bin;
-  }
+  virtual CHARSET_INFO *data_charset(void);
   virtual int    GetProgMax(PGLOBAL g) {return GetMaxSize(g);}
   virtual int    GetProgCur(void) {return GetRecpos();}
   virtual PSZ    GetFile(PGLOBAL g) {return "Not a file";}
@@ -229,7 +221,7 @@ class DllExport TDBASE : public TDB {
 /***********************************************************************/
 /*  The abstract base class declaration for the catalog tables.        */
 /***********************************************************************/
-class TDBCAT : public TDBASE {
+class DllExport TDBCAT : public TDBASE {
   friend class CATCOL;
  public:
   // Constructor
@@ -268,7 +260,7 @@ class TDBCAT : public TDBASE {
 /***********************************************************************/
 /*  Class CATCOL: ODBC info column.                                    */
 /***********************************************************************/
-class CATCOL : public COLBLK {
+class DllExport CATCOL : public COLBLK {
   friend class TDBCAT;
  public:
   // Constructors
-- 
2.30.9