summaryrefslogtreecommitdiff
path: root/storage
diff options
context:
space:
mode:
authorOlivier Bertrand <bertrandop@gmail.com>2015-02-28 23:01:55 +0100
committerOlivier Bertrand <bertrandop@gmail.com>2015-02-28 23:01:55 +0100
commitd862d7c049f95575242164341605b7e69d71e427 (patch)
treed6cebd444750355e66b1b199e6ff954c01bfef26 /storage
parentaa107ef3ab47c9bfbd177672e64d2af56ce1b1b5 (diff)
downloadmariadb-git-d862d7c049f95575242164341605b7e69d71e427.tar.gz
- Implement random access to ODBC tables
modified: storage/connect/odbconn.cpp storage/connect/odbconn.h - Fix get proper length of ODBC DECIMAL column in discovery modified: storage/connect/ha_connect.cc storage/connect/mysql-test/connect/r/odbc_oracle.result - Implement random access to JSON tables modified: storage/connect/tabjson.cpp storage/connect/tabjson.h - Fix MDEV-7636 modified: storage/connect/tabutil.cpp
Diffstat (limited to 'storage')
-rw-r--r--storage/connect/ha_connect.cc2
-rw-r--r--storage/connect/mysql-test/connect/r/odbc_oracle.result10
-rw-r--r--storage/connect/odbconn.cpp73
-rw-r--r--storage/connect/odbconn.h4
-rw-r--r--storage/connect/tabjson.cpp45
-rw-r--r--storage/connect/tabjson.h5
-rw-r--r--storage/connect/tabodbc.cpp129
-rw-r--r--storage/connect/tabodbc.h5
-rw-r--r--storage/connect/tabutil.cpp10
9 files changed, 209 insertions, 74 deletions
diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc
index 64c81272b59..ea81bf43a01 100644
--- a/storage/connect/ha_connect.cc
+++ b/storage/connect/ha_connect.cc
@@ -5462,7 +5462,9 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
case TYPE_DOUBLE:
// Some data sources do not count dec in length (prec)
prec += (dec + 2); // To be safe
+ break;
case TYPE_DECIM:
+ prec= len;
break;
default:
dec= 0;
diff --git a/storage/connect/mysql-test/connect/r/odbc_oracle.result b/storage/connect/mysql-test/connect/r/odbc_oracle.result
index fff2f192184..96d8e53b8e5 100644
--- a/storage/connect/mysql-test/connect/r/odbc_oracle.result
+++ b/storage/connect/mysql-test/connect/r/odbc_oracle.result
@@ -126,7 +126,7 @@ TABNAME='T1';
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `A` decimal(38,0) DEFAULT NULL,
+ `A` decimal(40,0) DEFAULT NULL,
`B` double(40,0) DEFAULT NULL
) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtr' `TABLE_TYPE`='ODBC' `TABNAME`='T1'
SELECT * FROM t1 ORDER BY A;
@@ -138,7 +138,7 @@ CREATE TABLE t2 AS SELECT * FROM t1;
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
- `A` decimal(38,0) DEFAULT NULL,
+ `A` decimal(40,0) DEFAULT NULL,
`B` double(40,0) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
SELECT * FROM t2;
@@ -162,7 +162,7 @@ TABNAME='MTR.T1';
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `A` decimal(38,0) DEFAULT NULL,
+ `A` decimal(40,0) DEFAULT NULL,
`B` double(40,0) DEFAULT NULL
) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtr' `TABLE_TYPE`='ODBC' `TABNAME`='MTR.T1'
SELECT * FROM t1;
@@ -178,7 +178,7 @@ TABNAME='MTR.V1';
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `A` decimal(38,0) DEFAULT NULL,
+ `A` decimal(40,0) DEFAULT NULL,
`B` double(40,0) DEFAULT NULL
) ENGINE=CONNECT DEFAULT CHARSET=latin1 CONNECTION='DSN=ConnectEngineOracle;UID=mtr;PWD=mtr' `TABLE_TYPE`='ODBC' `TABNAME`='MTR.V1'
SELECT * FROM t1;
@@ -190,7 +190,7 @@ CREATE TABLE t2 AS SELECT * FROM t1;
SHOW CREATE TABLE t2;
Table Create Table
t2 CREATE TABLE `t2` (
- `A` decimal(38,0) DEFAULT NULL,
+ `A` decimal(40,0) DEFAULT NULL,
`B` double(40,0) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
SELECT * FROM t2;
diff --git a/storage/connect/odbconn.cpp b/storage/connect/odbconn.cpp
index fec14820ef6..ea20672eb29 100644
--- a/storage/connect/odbconn.cpp
+++ b/storage/connect/odbconn.cpp
@@ -102,7 +102,12 @@ static int GetSQLCType(int type)
case TYPE_BIGINT: tp = SQL_C_SBIGINT; break;
case TYPE_DOUBLE: tp = SQL_C_DOUBLE; break;
case TYPE_TINY : tp = SQL_C_TINYINT; break;
+//#if (ODBCVER >= 0x0300)
+// case TYPE_DECIM: tp = SQL_C_NUMERIC; break; (CRASH!!!)
+//#else
case TYPE_DECIM: tp = SQL_C_CHAR; break;
+//#endif
+
} // endswitch type
return tp;
@@ -923,13 +928,13 @@ ODBConn::ODBConn(PGLOBAL g, TDBODBC *tdbp)
m_RowsetSize = (DWORD)((tdbp) ? tdbp->Rows : 10);
m_Catver = (tdbp) ? tdbp->Catver : 0;
m_Rows = 0;
+ m_Fetch = 0;
m_Connect = NULL;
m_User = NULL;
m_Pwd = NULL;
m_Updatable = true;
m_Transact = false;
m_Scrollable = (tdbp) ? tdbp->Scrollable : false;
- m_First = true;
m_Full = false;
m_UseCnc = false;
m_IDQuoteChar[0] = '"';
@@ -984,7 +989,7 @@ void ODBConn::ThrowDBX(RETCODE rc, PSZ msg, HSTMT hstmt)
void ODBConn::ThrowDBX(PSZ msg)
{
- DBX* xp = new(m_G) DBX(0, msg);
+ DBX* xp = new(m_G) DBX(0, "Error");
xp->m_ErrMsg[0] = msg;
throw xp;
@@ -1099,8 +1104,7 @@ int ODBConn::Open(PSZ ConnectString, POPARM sop, DWORD options)
// VerifyConnect(); Deprecated
GetConnectInfo();
} catch(DBX *xp) {
-// strcpy(g->Message, xp->m_ErrMsg[0]);
- strcpy(g->Message, xp->GetErrorMessage(0));
+ sprintf(g->Message, "%s: %s", xp->m_Msg, xp->GetErrorMessage(0));
Close();
// Free();
return -1;
@@ -1356,7 +1360,7 @@ int ODBConn::ExecDirectSQL(char *sql, ODBCCOL *tocols)
rc = SQLFreeStmt(m_hstmt, SQL_CLOSE);
if (!Check(rc))
- ThrowDBX(rc, "SQLFreeStmt");
+ ThrowDBX(rc, "SQLFreeStmt", m_hstmt);
m_hstmt = NULL;
} // endif m_hstmt
@@ -1371,7 +1375,7 @@ int ODBConn::ExecDirectSQL(char *sql, ODBCCOL *tocols)
(void*)SQL_SCROLLABLE, 0);
if (!Check(rc))
- ThrowDBX(rc, "SQLSetStmtAttr");
+ ThrowDBX(rc, "Scrollable", hstmt);
} // endif m_Scrollable
@@ -1422,7 +1426,7 @@ int ODBConn::ExecDirectSQL(char *sql, ODBCCOL *tocols)
for (n = 0, colp = tocols; colp; colp = (PODBCCOL)colp->GetNext())
if (!colp->IsSpecial())
- n++;
+ n++;
// n can be 0 for query such as Select count(*) from table
if (n && n != (UWORD)ncol)
@@ -1458,7 +1462,7 @@ int ODBConn::ExecDirectSQL(char *sql, ODBCCOL *tocols)
for (int i = 0; i < MAX_NUM_OF_MSG && x->m_ErrMsg[i]; i++)
htrc(x->m_ErrMsg[i]);
- strcpy(m_G->Message, x->GetErrorMessage(0));
+ sprintf(m_G->Message, "%s: %s", x->m_Msg, x->GetErrorMessage(0));
if (b)
SQLCancel(hstmt);
@@ -1521,7 +1525,7 @@ int ODBConn::GetResultSize(char *sql, ODBCCOL *colp)
/***********************************************************************/
/* Fetch next row. */
/***********************************************************************/
-int ODBConn::Fetch()
+int ODBConn::Fetch(int pos)
{
ASSERT(m_hstmt);
int irc;
@@ -1531,7 +1535,9 @@ int ODBConn::Fetch()
try {
// do {
- if (m_RowsetSize) {
+ if (pos) {
+ rc = SQLExtendedFetch(m_hstmt, SQL_FETCH_ABSOLUTE, pos, &crow, NULL);
+ } else if (m_RowsetSize) {
rc = SQLExtendedFetch(m_hstmt, SQL_FETCH_NEXT, 1, &crow, NULL);
} else {
rc = SQLFetch(m_hstmt);
@@ -1544,29 +1550,22 @@ int ODBConn::Fetch()
m_hstmt, m_RowsetSize, rc);
if (!Check(rc))
- ThrowDBX(rc, "Fetch", m_hstmt);
-
- irc = (rc == SQL_NO_DATA_FOUND) ? 0 : (int)crow;
-
- if (m_First) {
- // First fetch. Check whether the full table was read
- if ((m_Full = irc < (signed)m_RowsetSize)) {
- m_Tdb->Memory = 0; // Not needed anymore
- m_Rows = irc; // Table size
- } // endif m_Full
-
- m_First = false;
- } // endif m_First
+ ThrowDBX(rc, "Fetching", m_hstmt);
- if (m_Tdb->Memory == 1)
- m_Rows += irc;
+ if (rc == SQL_NO_DATA_FOUND) {
+ m_Full = (m_Fetch == 1);
+ irc = 0;
+ } else
+ irc = (int)crow;
+ m_Fetch++;
+ m_Rows += irc;
} catch(DBX *x) {
if (trace)
for (int i = 0; i < MAX_NUM_OF_MSG && x->m_ErrMsg[i]; i++)
htrc(x->m_ErrMsg[i]);
- strcpy(g->Message, x->GetErrorMessage(0));
+ sprintf(g->Message, "%s: %s", x->m_Msg, x->GetErrorMessage(0));
irc = -1;
} // end try/catch
@@ -1602,7 +1601,7 @@ int ODBConn::PrepareSQL(char *sql)
for (int i = 0; i < MAX_NUM_OF_MSG && x->m_ErrMsg[i]; i++)
htrc(x->m_ErrMsg[i]);
- strcpy(g->Message, x->GetErrorMessage(0));
+ sprintf(g->Message, "%s: %s", x->m_Msg, x->GetErrorMessage(0));
} // end try/catch
} // endif Mode
@@ -1648,7 +1647,7 @@ int ODBConn::PrepareSQL(char *sql)
for (int i = 0; i < MAX_NUM_OF_MSG && x->m_ErrMsg[i]; i++)
htrc(x->m_ErrMsg[i]);
- strcpy(g->Message, x->GetErrorMessage(0));
+ sprintf(g->Message, "%s: %s", x->m_Msg, x->GetErrorMessage(0));
if (b)
SQLCancel(hstmt);
@@ -1700,7 +1699,7 @@ int ODBConn::ExecuteSQL(void)
} // endif ncol
} catch(DBX *x) {
- strcpy(m_G->Message, x->GetErrorMessage(0));
+ sprintf(m_G->Message, "%s: %s", x->m_Msg, x->GetErrorMessage(0));
SQLCancel(m_hstmt);
rc = SQLFreeStmt(m_hstmt, SQL_DROP);
m_hstmt = NULL;
@@ -1737,7 +1736,7 @@ bool ODBConn::BindParam(ODBCCOL *colp)
ThrowDBX(rc, "SQLDescribeParam", m_hstmt);
} catch(DBX *x) {
- strcpy(m_G->Message, x->GetErrorMessage(0));
+ sprintf(m_G->Message, "%s: %s", x->m_Msg, x->GetErrorMessage(0));
colsize = colp->GetPrecision();
sqlt = GetSQLType(buftype);
dec = IsTypeChar(buftype) ? 0 : colp->GetScale();
@@ -1845,7 +1844,7 @@ bool ODBConn::ExecSQLcommand(char *sql)
for (int i = 0; i < MAX_NUM_OF_MSG && x->m_ErrMsg[i]; i++)
htrc(x->m_ErrMsg[i]);
- sprintf(g->Message, "Remote: %s", x->GetErrorMessage(0));
+ sprintf(g->Message, "Remote %s: %s", x->m_Msg, x->GetErrorMessage(0));
if (b)
SQLCancel(hstmt);
@@ -1930,7 +1929,7 @@ PQRYRES ODBConn::GetMetaData(PGLOBAL g, char *dsn, char *src)
} // endfor i
} catch(DBX *x) {
- strcpy(g->Message, x->GetErrorMessage(0));
+ sprintf(g->Message, "%s: %s", x->m_Msg, x->GetErrorMessage(0));
goto err;
} // end try/catch
@@ -1981,7 +1980,7 @@ PQRYRES ODBConn::GetMetaData(PGLOBAL g, char *dsn, char *src)
} // endfor i
} catch(DBX *x) {
- strcpy(g->Message, x->GetErrorMessage(0));
+ sprintf(g->Message, "%s: %s", x->m_Msg, x->GetErrorMessage(0));
qrp = NULL;
} // end try/catch
@@ -2033,7 +2032,7 @@ bool ODBConn::GetDataSources(PQRYRES qrp)
} // endfor i
} catch(DBX *x) {
- strcpy(m_G->Message, x->GetErrorMessage(0));
+ sprintf(m_G->Message, "%s: %s", x->m_Msg, x->GetErrorMessage(0));
rv = true;
} // end try/catch
@@ -2084,7 +2083,7 @@ bool ODBConn::GetDrivers(PQRYRES qrp)
} // endfor n
} catch(DBX *x) {
- strcpy(m_G->Message, x->GetErrorMessage(0));
+ sprintf(m_G->Message, "%s: %s", x->m_Msg, x->GetErrorMessage(0));
rv = true;
} // end try/catch
@@ -2402,7 +2401,7 @@ int ODBConn::GetCatInfo(CATPARM *cap)
for (int i = 0; i < MAX_NUM_OF_MSG && x->m_ErrMsg[i]; i++)
htrc(x->m_ErrMsg[i]);
- strcpy(g->Message, x->GetErrorMessage(0));
+ sprintf(g->Message, "%s: %s", x->m_Msg, x->GetErrorMessage(0));
irc = -1;
} // end try/catch
@@ -2506,7 +2505,7 @@ int ODBConn::Rewind(char *sql, ODBCCOL *tocols)
rbuf = (int)crow;
} catch(DBX *x) {
- strcpy(m_G->Message, x->GetErrorMessage(0));
+ sprintf(m_G->Message, "%s: %s", x->m_Msg, x->GetErrorMessage(0));
rbuf = -1;
} // end try/catch
diff --git a/storage/connect/odbconn.h b/storage/connect/odbconn.h
index b7c5e0c942d..41cc2439354 100644
--- a/storage/connect/odbconn.h
+++ b/storage/connect/odbconn.h
@@ -141,7 +141,7 @@ class ODBConn : public BLOCK {
//void SetUserPwd(PSZ pwd) {m_Pwd = pwd;}
int GetResultSize(char *sql, ODBCCOL *colp);
int ExecDirectSQL(char *sql, ODBCCOL *tocols);
- int Fetch(void);
+ int Fetch(int pos = 0);
int PrepareSQL(char *sql);
int ExecuteSQL(void);
bool BindParam(ODBCCOL *colp);
@@ -192,10 +192,10 @@ class ODBConn : public BLOCK {
PSZ m_Pwd;
int m_Catver;
int m_Rows;
+ int m_Fetch;
bool m_Updatable;
bool m_Transact;
bool m_Scrollable;
bool m_UseCnc;
- bool m_First;
bool m_Full;
}; // end of ODBConn class definition
diff --git a/storage/connect/tabjson.cpp b/storage/connect/tabjson.cpp
index 41a6e72a76a..ccc21960bfd 100644
--- a/storage/connect/tabjson.cpp
+++ b/storage/connect/tabjson.cpp
@@ -1291,6 +1291,51 @@ int TDBJSON::MakeIndex(PGLOBAL g, PIXDEF pxdf, bool add)
} // end of MakeIndex
/***********************************************************************/
+/* Return the position in the table. */
+/***********************************************************************/
+int TDBJSON::GetRecpos(void)
+ {
+#if 0
+ union {
+ uint Rpos;
+ BYTE Spos[4];
+ };
+
+ Rpos = htonl(Fpos);
+ Spos[0] = (BYTE)NextSame;
+ return Rpos;
+#endif // 0
+ return Fpos;
+ } // end of GetRecpos
+
+/***********************************************************************/
+/* Set the position in the table. */
+/***********************************************************************/
+bool TDBJSON::SetRecpos(PGLOBAL g, int recpos)
+ {
+#if 0
+ union {
+ uint Rpos;
+ BYTE Spos[4];
+ };
+
+ Rpos = recpos;
+ NextSame = Spos[0];
+ Spos[0] = 0;
+ Fpos = (signed)ntohl(Rpos);
+
+//if (Fpos != (signed)ntohl(Rpos)) {
+// Fpos = ntohl(Rpos);
+// same = false;
+//} else
+// same = true;
+#endif // 0
+
+ Fpos = recpos - 1;
+ return false;
+ } // end of SetRecpos
+
+/***********************************************************************/
/* JSON Access Method opening routine. */
/***********************************************************************/
bool TDBJSON::OpenDB(PGLOBAL g)
diff --git a/storage/connect/tabjson.h b/storage/connect/tabjson.h
index eb9d078012b..397c2cf5d3a 100644
--- a/storage/connect/tabjson.h
+++ b/storage/connect/tabjson.h
@@ -174,10 +174,9 @@ class TDBJSON : public TDBJSN {
virtual int Cardinality(PGLOBAL g);
virtual int GetMaxSize(PGLOBAL g);
virtual void ResetSize(void);
- virtual int GetRecpos(void) {return Fpos;}
virtual int GetProgCur(void) {return N;}
- virtual bool SetRecpos(PGLOBAL g, int recpos)
- {Fpos = recpos - 1; return false;}
+ virtual int GetRecpos(void);
+ virtual bool SetRecpos(PGLOBAL g, int recpos);
virtual bool OpenDB(PGLOBAL g);
virtual int ReadDB(PGLOBAL g);
virtual bool PrepareWriting(PGLOBAL g) {return false;}
diff --git a/storage/connect/tabodbc.cpp b/storage/connect/tabodbc.cpp
index bf76a124b70..3bf1238cebc 100644
--- a/storage/connect/tabodbc.cpp
+++ b/storage/connect/tabodbc.cpp
@@ -135,9 +135,16 @@ bool ODBCDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
//Options = ODBConn::noOdbcDialog | ODBConn::useCursorLib;
Cto= GetIntCatInfo("ConnectTimeout", DEFAULT_LOGIN_TIMEOUT);
Qto= GetIntCatInfo("QueryTimeout", DEFAULT_QUERY_TIMEOUT);
- Scrollable = GetBoolCatInfo("Scrollable", false);
+
+ if ((Scrollable = GetBoolCatInfo("Scrollable", false)) && !Elemt)
+ Elemt = 1; // Cannot merge SQLFetch and SQLExtendedFetch
+
UseCnc = GetBoolCatInfo("UseDSN", false);
- Memory = GetBoolCatInfo("Memory", false);
+
+ // Memory was Boolean, it is now integer
+ if (!(Memory = GetIntCatInfo("Memory", 0)))
+ Memory = GetBoolCatInfo("Memory", false) ? 1 : 0;
+
Pseudo = 2; // FILID is Ok but not ROWID
return false;
} // end of DefineAM
@@ -206,7 +213,7 @@ TDBODBC::TDBODBC(PODEF tdp) : TDBASE(tdp)
Quoted = MY_MAX(0, tdp->GetQuoted());
Rows = tdp->GetElemt();
Catver = tdp->Catver;
- Memory = (tdp->Memory) ? 1 : 0;
+ Memory = tdp->Memory;
Scrollable = tdp->Scrollable;
Ops.UseCnc = tdp->UseCnc;
} else {
@@ -238,11 +245,13 @@ TDBODBC::TDBODBC(PODEF tdp) : TDBASE(tdp)
DBQ = NULL;
Qrp = NULL;
Fpos = 0;
+ Curpos = 0;
AftRows = 0;
CurNum = 0;
Rbuf = 0;
BufSize = 0;
Nparm = 0;
+ Placed = false;
} // end of TDBODBC standard constructor
TDBODBC::TDBODBC(PTDBODBC tdbp) : TDBASE(tdbp)
@@ -267,15 +276,15 @@ TDBODBC::TDBODBC(PTDBODBC tdbp) : TDBASE(tdbp)
Options = tdbp->Options;
Quoted = tdbp->Quoted;
Rows = tdbp->Rows;
- Fpos = tdbp->Fpos;
- AftRows = tdbp->AftRows;
-//Tpos = tdbp->Tpos;
-//Spos = tdbp->Spos;
- CurNum = tdbp->CurNum;
- Rbuf = tdbp->Rbuf;
+ Fpos = 0;
+ Curpos = 0;
+ AftRows = 0;
+ CurNum = 0;
+ Rbuf = 0;
BufSize = tdbp->BufSize;
Nparm = tdbp->Nparm;
Qrp = tdbp->Qrp;
+ Placed = false;
} // end of TDBODBC copy constructor
// Method
@@ -811,10 +820,12 @@ bool TDBODBC::OpenDB(PGLOBAL g)
return true;
} // endif Rewind
- } // endif Memory
+ } else
+ Rbuf = Qrp->Nblin;
CurNum = 0;
Fpos = 0;
+ Curpos = 1;
return false;
} // endif use
@@ -841,6 +852,37 @@ bool TDBODBC::OpenDB(PGLOBAL g)
/* Make the command and allocate whatever is used for getting results. */
/*********************************************************************/
if (Mode == MODE_READ || Mode == MODE_READX) {
+ if (Memory > 1 && !Srcdef) {
+ char *Sql;
+ int n;
+
+ if ((Sql = MakeSQL(g, true))) {
+ // Allocate a Count(*) column
+ Cnp = new(g) ODBCCOL;
+ Cnp->InitValue(g);
+
+ if ((n = Ocp->GetResultSize(Sql, Cnp)) < 0) {
+ strcpy(g->Message, "Cannot get result size");
+ return true;
+ } // endif n
+
+ Ocp->m_Rows = n;
+
+ if ((Qrp = Ocp->AllocateResult(g)))
+ Memory = 2; // Must be filled
+ else {
+ strcpy(g->Message, "Memory allocation failed");
+ return true;
+ } // endif n
+
+ Ocp->m_Rows = 0;
+ } else {
+ strcpy(g->Message, "MakeSQL failed");
+ return true;
+ } // endif Sql
+
+ } // endif Memory
+
if ((Query = MakeSQL(g, false))) {
for (PODBCCOL colp = (PODBCCOL)Columns; colp;
colp = (PODBCCOL)colp->GetNext())
@@ -882,10 +924,41 @@ bool TDBODBC::OpenDB(PGLOBAL g)
/***********************************************************************/
int TDBODBC::GetRecpos(void)
{
- return Fpos; // To be really implemented
+ return Fpos;
} // end of GetRecpos
/***********************************************************************/
+/* SetRecpos: set the position of next read record. */
+/***********************************************************************/
+bool TDBODBC::SetRecpos(PGLOBAL g, int recpos)
+ {
+ if (Ocp->m_Full) {
+ Fpos = 0;
+ CurNum = recpos - 1;
+ } else if (Memory == 3) {
+ Fpos = recpos;
+ CurNum = -1;
+ } else if (Scrollable) {
+ // Is new position in the current row set?
+ if (recpos >= Curpos && recpos < Curpos + Rbuf) {
+ CurNum = recpos - Curpos;
+ Fpos = 0;
+ } else {
+ Fpos = recpos;
+ CurNum = 0;
+ } // endif recpos
+
+ } else {
+ strcpy(g->Message, "This action requires a scrollable cursor");
+ return true;
+ } // endif's
+
+ // Indicate the table position was externally set
+ Placed = true;
+ return false;
+ } // end of SetRecpos
+
+/***********************************************************************/
/* VRDNDOS: Data Base read routine for odbc access method. */
/***********************************************************************/
int TDBODBC::ReadDB(PGLOBAL g)
@@ -924,22 +997,32 @@ int TDBODBC::ReadDB(PGLOBAL g)
/* Now start the reading process. */
/* Here is the place to fetch the line(s). */
/*********************************************************************/
- if (Memory != 3) {
- if (++CurNum >= Rbuf) {
- Rbuf = Ocp->Fetch();
- CurNum = 0;
- } // endif CurNum
+ if (Placed) {
+ if (Fpos && CurNum >= 0)
+ Rbuf = Ocp->Fetch((Curpos = Fpos));
rc = (Rbuf > 0) ? RC_OK : (Rbuf == 0) ? RC_EF : RC_FX;
- } else // Getting result from memory
- rc = (Fpos < Qrp->Nblin) ? RC_OK : RC_EF;
+ Placed = false;
+ } else {
+ if (Memory != 3) {
+ if (++CurNum >= Rbuf) {
+ Rbuf = Ocp->Fetch();
+ Curpos = Fpos + 1;
+ CurNum = 0;
+ } // endif CurNum
- if (rc == RC_OK) {
- if (Memory == 2)
- Qrp->Nblin++;
+ rc = (Rbuf > 0) ? RC_OK : (Rbuf == 0) ? RC_EF : RC_FX;
+ } else // Getting result from memory
+ rc = (Fpos < Qrp->Nblin) ? RC_OK : RC_EF;
- Fpos++; // Used for memory
- } // endif rc
+ if (rc == RC_OK) {
+ if (Memory == 2)
+ Qrp->Nblin++;
+
+ Fpos++; // Used for memory and pos
+ } // endif rc
+
+ } // endif Placed
if (trace > 1)
htrc(" Read: Rbuf=%d rc=%d\n", Rbuf, rc);
diff --git a/storage/connect/tabodbc.h b/storage/connect/tabodbc.h
index eb20eb6efde..b8c9d85aae5 100644
--- a/storage/connect/tabodbc.h
+++ b/storage/connect/tabodbc.h
@@ -64,8 +64,8 @@ class DllExport ODBCDEF : public TABDEF { /* Logical table description */
int Quoted; /* Identifier quoting level */
int Maxerr; /* Maxerr for an Exec table */
int Maxres; /* Maxres for a catalog table */
+ int Memory; /* Put result set in memory */
bool Scrollable; /* Use scrollable cursor */
- bool Memory; /* Put result set in memory */
bool Xsrc; /* Execution type */
bool UseCnc; /* Use SQLConnect (!SQLDriverConnect) */
}; // end of ODBCDEF
@@ -93,6 +93,7 @@ class TDBODBC : public TDBASE {
// Methods
virtual PTDB CopyOne(PTABS t);
virtual int GetRecpos(void);
+ virtual bool SetRecpos(PGLOBAL g, int recpos);
virtual PSZ GetFile(PGLOBAL g);
virtual void SetFile(PGLOBAL g, PSZ fn);
virtual void ResetSize(void);
@@ -148,6 +149,7 @@ class TDBODBC : public TDBASE {
int Qto; // Query timeout
int Quoted; // The identifier quoting level
int Fpos; // Position of last read record
+ int Curpos; // Cursor position of last fetch
int AftRows; // The number of affected rows
int Rows; // Rowset size
int Catver; // Catalog ODBC version
@@ -157,6 +159,7 @@ class TDBODBC : public TDBASE {
int Nparm; // The number of statement parameters
int Memory; // 0: No 1: Alloc 2: Put 3: Get
bool Scrollable; // Use scrollable cursor
+ bool Placed; // True for position reading
bool UseCnc; // Use SQLConnect (!SQLDriverConnect)
PQRYRES Qrp; // Points to storage result
}; // end of class TDBODBC
diff --git a/storage/connect/tabutil.cpp b/storage/connect/tabutil.cpp
index c1c112633fd..c114497aa69 100644
--- a/storage/connect/tabutil.cpp
+++ b/storage/connect/tabutil.cpp
@@ -1,7 +1,7 @@
/************* Tabutil cpp Declares Source Code File (.CPP) ************/
-/* Name: TABUTIL.CPP Version 1.0 */
+/* Name: TABUTIL.CPP Version 1.1 */
/* */
-/* (C) Copyright to the author Olivier BERTRAND 2013 */
+/* (C) Copyright to the author Olivier BERTRAND 2013 - 2015 */
/* */
/* Utility function used by the PROXY, XCOL, OCCUR, and TBL tables. */
/***********************************************************************/
@@ -9,7 +9,8 @@
/***********************************************************************/
/* Include relevant section of system dependant header files. */
/***********************************************************************/
-#include "my_global.h"
+#define MYSQL_SERVER 1
+#include <my_global.h>
#include "sql_class.h"
#include "table.h"
#include "field.h"
@@ -108,6 +109,9 @@ TABLE_SHARE *GetTableShare(PGLOBAL g, THD *thd, const char *db,
} // endif is_view
} else {
+ if (thd->is_error())
+ thd->clear_error(); // Avoid stopping info commands
+
sprintf(g->Message, "Error %d opening share\n", s->error);
free_table_share(s);
return NULL;