1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-08 11:22:35 +03:00

- Fix bug when closing some table types

modified:
  storage/connect/tabmul.cpp
  storage/connect/tabmysql.cpp
  storage/connect/tabodbc.cpp

- Add Insert support for ODBC table
  Add the send command feature to ODBC tables
  (not documented yet)

modified:
  storage/connect/ha_connect.cc
  storage/connect/myconn.cpp
  storage/connect/odbccat.h
  storage/connect/odbconn.cpp
  storage/connect/odbconn.h
  storage/connect/tabodbc.cpp
  storage/connect/tabodbc.h
This commit is contained in:
Olivier Bertrand
2013-10-11 13:57:56 +02:00
parent 8619da05d9
commit ca4c54aaee
9 changed files with 746 additions and 106 deletions

View File

@@ -1,5 +1,5 @@
/************ Odbconn C++ Functions Source Code File (.CPP) ************/
/* Name: ODBCONN.CPP Version 1.6 */
/* Name: ODBCONN.CPP Version 1.7 */
/* */
/* (C) Copyright to the author Olivier BERTRAND 1998-2013 */
/* */
@@ -229,7 +229,6 @@ static void ResetNullValues(CATPARM *cap)
/***********************************************************************/
/* ODBCColumns: constructs the result blocks containing all columns */
/* of an ODBC table that will be retrieved by GetData commands. */
/* Note: The first two columns (Qualifier, Owner) are ignored. */
/***********************************************************************/
PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *table,
char *colpat, bool info)
@@ -318,6 +317,17 @@ PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *table,
return qrp;
} // end of ODBCColumns
/**************************************************************************/
/* ODBCSrcCols: constructs the result blocks containing the */
/* description of all the columns of a Srcdef option. */
/**************************************************************************/
PQRYRES ODBCSrcCols(PGLOBAL g, char *dsn, char *src)
{
ODBConn *ocp = new(g) ODBConn(g, NULL);
return ocp->GetMetaData(g, dsn, src);
} // end of ODBCSrcCols
#if 0
/**************************************************************************/
/* MyODBCCols: returns column info as required by ha_connect::pre_create. */
@@ -804,6 +814,17 @@ void DBX::BuildErrorMessage(ODBConn* pdb, HSTMT hstmt)
} // end of BuildErrorMessage
const char *DBX::GetErrorMessage(int i)
{
if (i < 0 || i >= MAX_NUM_OF_MSG)
return "No ODBC error";
else if (m_ErrMsg[i])
return m_ErrMsg[i];
else
return (m_Msg) ? m_Msg : "Unknown error";
} // end of GetErrorMessage
/***********************************************************************/
/* ODBConn construction/destruction. */
/***********************************************************************/
@@ -822,7 +843,7 @@ ODBConn::ODBConn(PGLOBAL g, TDBODBC *tdbp)
m_Catver = (tdbp) ? tdbp->Catver : 0;
m_Connect = NULL;
m_Updatable = true;
//m_Transactions = false;
m_Transact = false;
m_IDQuoteChar = '\'';
//*m_ErrMsg = '\0';
} // end of ODBConn
@@ -1208,8 +1229,7 @@ int ODBConn::ExecDirectSQL(char *sql, ODBCCOL *tocols)
void *buffer;
bool b;
UWORD n;
SWORD ncol, len, tp;
SQLLEN afrw;
SWORD len, tp, ncol = 0;
ODBCCOL *colp;
RETCODE rc;
HSTMT hstmt;
@@ -1244,26 +1264,44 @@ int ODBConn::ExecDirectSQL(char *sql, ODBCCOL *tocols)
if (trace)
htrc("ExecDirect hstmt=%p %.64s\n", hstmt, sql);
do {
rc = SQLExecDirect(hstmt, (PUCHAR)sql, SQL_NTS);
} while (rc == SQL_STILL_EXECUTING);
if (!Check(rc))
ThrowDBX(rc, "SQLExecDirect", hstmt);
do {
rc = SQLNumResultCols(hstmt, &ncol);
} while (rc == SQL_STILL_EXECUTING);
if (ncol == 0) {
// Update or Delete statement
rc = SQLRowCount(hstmt, &afrw);
if (m_Tdb->Srcdef) {
// Be sure this is a query returning a result set
do {
rc = SQLPrepare(hstmt, (PUCHAR)sql, SQL_NTS);
} while (rc == SQL_STILL_EXECUTING);
if (!Check(rc))
ThrowDBX(rc, "SQLRowCount", hstmt);
ThrowDBX(rc, "SQLPrepare", hstmt);
return afrw;
} // endif ncol
if (!Check(rc = SQLNumResultCols(hstmt, &ncol)))
ThrowDBX(rc, "SQLNumResultCols", hstmt);
if (ncol == 0) {
strcpy(g->Message, "This Srcdef does not return a result set");
return -1;
} // endif ncol
// Ok, now we can proceed
do {
rc = SQLExecute(hstmt);
} while (rc == SQL_STILL_EXECUTING);
if (!Check(rc))
ThrowDBX(rc, "SQLExecute", hstmt);
} else {
do {
rc = SQLExecDirect(hstmt, (PUCHAR)sql, SQL_NTS);
} while (rc == SQL_STILL_EXECUTING);
if (!Check(rc))
ThrowDBX(rc, "SQLExecDirect", hstmt);
do {
rc = SQLNumResultCols(hstmt, &ncol);
} while (rc == SQL_STILL_EXECUTING);
} // endif Srcdef
for (n = 0, colp = tocols; colp; colp = (PODBCCOL)colp->GetNext())
if (!colp->IsSpecial())
@@ -1411,10 +1449,33 @@ int ODBConn::PrepareSQL(char *sql)
{
PGLOBAL& g = m_G;
bool b;
UINT txn = 0;
SWORD nparm;
RETCODE rc;
HSTMT hstmt;
if (m_Tdb->GetMode() != MODE_READ) {
// Does the data source support transactions
rc = SQLGetInfo(m_hdbc, SQL_TXN_CAPABLE, &txn, 0, NULL);
if (Check(rc) && txn != SQL_TC_NONE) try {
rc = SQLSetConnectAttr(m_hdbc, SQL_ATTR_AUTOCOMMIT,
SQL_AUTOCOMMIT_OFF, SQL_IS_UINTEGER);
if (!Check(rc))
ThrowDBX(SQL_INVALID_HANDLE, "SQLSetConnectAttr");
m_Transact = true;
} 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));
} // end try/catch
} // endif Mode
try {
b = false;
@@ -1454,13 +1515,19 @@ 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(m_G->Message, x->GetErrorMessage(0));
strcpy(g->Message, x->GetErrorMessage(0));
if (b)
SQLCancel(hstmt);
rc = SQLFreeStmt(hstmt, SQL_DROP);
m_hstmt = NULL;
if (m_Transact) {
rc = SQLEndTran(SQL_HANDLE_DBC, m_hdbc, SQL_ROLLBACK);
m_Transact = false;
} // endif m_Transact
return -1;
} // end try/catch
@@ -1469,27 +1536,59 @@ int ODBConn::PrepareSQL(char *sql)
} // end of PrepareSQL
/***********************************************************************/
/* Bind a parameter for inserting. */
/* Execute a prepared statement. */
/***********************************************************************/
bool ODBConn::ExecuteSQL(void)
int ODBConn::ExecuteSQL(bool x)
{
RETCODE rc;
PGLOBAL& g = m_G;
SWORD ncol = 0;
RETCODE rc;
SQLLEN afrw = -1;
try {
rc = SQLExecute(m_hstmt);
do {
rc = SQLExecute(m_hstmt);
} while (rc == SQL_STILL_EXECUTING);
if (!Check(rc))
ThrowDBX(rc, "SQLExecute", m_hstmt);
if (!Check(SQLNumResultCols(m_hstmt, &ncol)))
ThrowDBX(rc, "SQLNumResultCols", m_hstmt);
if (ncol) {
if (x) {
afrw = ncol;
strcpy(g->Message, "Result set column number");
} else {
// This should never happen while inserting
strcpy(g->Message, "Logical error while inserting");
} // endif ncol
} else {
// Insert, Update or Delete statement
if (!Check(SQLRowCount(m_hstmt, &afrw)))
ThrowDBX(rc, "SQLRowCount", m_hstmt);
if (x)
strcpy(g->Message, "Affected rows");
} // endif ncol
} catch(DBX *x) {
strcpy(m_G->Message, x->GetErrorMessage(0));
SQLCancel(m_hstmt);
rc = SQLFreeStmt(m_hstmt, SQL_DROP);
m_hstmt = NULL;
return true;
if (m_Transact) {
rc = SQLEndTran(SQL_HANDLE_DBC, m_hdbc, SQL_ROLLBACK);
m_Transact = false;
} // endif m_Transact
} // end try/catch
return false;
return (int)afrw;
} // end of ExecuteSQL
/***********************************************************************/
@@ -1541,6 +1640,132 @@ bool ODBConn::BindParam(ODBCCOL *colp)
return false;
} // end of BindParam
/**************************************************************************/
/* GetMetaData: constructs the result blocks containing the */
/* description of all the columns of an SQL command. */
/**************************************************************************/
PQRYRES ODBConn::GetMetaData(PGLOBAL g, char *dsn, char *src)
{
static int buftyp[] = {TYPE_STRING, TYPE_SHORT, TYPE_INT,
TYPE_SHORT, TYPE_SHORT};
static XFLD fldtyp[] = {FLD_NAME, FLD_TYPE, FLD_PREC,
FLD_SCALE, FLD_NULL};
static unsigned int length[] = {0, 6, 10, 6, 6};
unsigned char cn[60];
int qcol = 5;
short nl, type, prec, nul, cns = (short)sizeof(cn);
PQRYRES qrp = NULL;
PCOLRES crp;
USHORT i;
ULONG n;
SWORD ncol;
RETCODE rc;
HSTMT hstmt;
if (Open(dsn, 2) < 1) // 2 is openReadOnly
return NULL;
try {
rc = SQLAllocStmt(m_hdbc, &hstmt);
if (!Check(rc))
ThrowDBX(SQL_INVALID_HANDLE, "SQLAllocStmt");
OnSetOptions(hstmt);
do {
rc = SQLPrepare(hstmt, (PUCHAR)src, SQL_NTS);
// rc = SQLExecDirect(hstmt, (PUCHAR)src, SQL_NTS);
} while (rc == SQL_STILL_EXECUTING);
if (!Check(rc))
ThrowDBX(rc, "SQLExecDirect", hstmt);
do {
rc = SQLNumResultCols(hstmt, &ncol);
} while (rc == SQL_STILL_EXECUTING);
if (!Check(rc))
ThrowDBX(rc, "SQLNumResultCols", hstmt);
if (ncol) for (i = 1; i <= ncol; i++) {
do {
rc = SQLDescribeCol(hstmt, i, NULL, 0, &nl, NULL, NULL, NULL, NULL);
} while (rc == SQL_STILL_EXECUTING);
if (!Check(rc))
ThrowDBX(rc, "SQLDescribeCol", hstmt);
length[0] = max(length[0], (UINT)nl);
} // endfor i
} catch(DBX *x) {
strcpy(g->Message, x->GetErrorMessage(0));
goto err;
} // end try/catch
if (!ncol) {
strcpy(g->Message, "Invalid Srcdef");
goto err;
} // endif ncol
/************************************************************************/
/* Allocate the structures used to refer to the result set. */
/************************************************************************/
qrp = PlgAllocResult(g, qcol, ncol, IDS_COLUMNS + 3,
buftyp, fldtyp, length, false, true);
// Some columns must be renamed
for (i = 0, crp = qrp->Colresp; crp; crp = crp->Next)
switch (++i) {
case 3: crp->Name = "Precision"; break;
case 4: crp->Name = "Scale"; break;
case 5: crp->Name = "Nullable"; break;
} // endswitch i
/************************************************************************/
/* Now get the results into blocks. */
/************************************************************************/
try {
for (i = 0; i < ncol; i++) {
do {
rc = SQLDescribeCol(hstmt, i+1, cn, cns, &nl, &type, &n, &prec, &nul);
} while (rc == SQL_STILL_EXECUTING);
if (!Check(rc))
ThrowDBX(rc, "SQLDescribeCol", hstmt);
else
qrp->Nblin++;
crp = qrp->Colresp; // Column_Name
crp->Kdata->SetValue((char*)cn, i);
crp = crp->Next; // Data_Type
crp->Kdata->SetValue(type, i);
crp = crp->Next; // Precision (length)
crp->Kdata->SetValue((int)n, i);
crp = crp->Next; // Scale
crp->Kdata->SetValue(prec, i);
crp = crp->Next; // Nullable
crp->Kdata->SetValue(nul, i);
} // endfor i
} catch(DBX *x) {
strcpy(g->Message, x->GetErrorMessage(0));
qrp = NULL;
} // end try/catch
/* Cleanup */
err:
SQLCancel(hstmt);
rc = SQLFreeStmt(hstmt, SQL_DROP);
Close();
/************************************************************************/
/* Return the result pointer for use by GetData routines. */
/************************************************************************/
return qrp;
} // end of GetMetaData
/***********************************************************************/
/* Get the list of Data Sources and set it in qrp. */
/***********************************************************************/
@@ -1844,6 +2069,11 @@ void ODBConn::Close()
} // endif m_hstmt
if (m_hdbc != SQL_NULL_HDBC) {
if (m_Transact) {
rc = SQLEndTran(SQL_HANDLE_DBC, m_hdbc, SQL_COMMIT);
m_Transact = false;
} // endif m_Transact
rc = SQLDisconnect(m_hdbc);
if (trace && rc != SQL_SUCCESS)