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:
@@ -1133,13 +1133,14 @@ bool ha_connect::OpenTable(PGLOBAL g, bool del)
|
|||||||
break;
|
break;
|
||||||
} // endswitch xmode
|
} // endswitch xmode
|
||||||
|
|
||||||
if (xmod != MODE_INSERT) {
|
if (xmod != MODE_INSERT || tdbp->GetAmType() == TYPE_AM_ODBC
|
||||||
|
|| tdbp->GetAmType() == TYPE_AM_MYSQL) {
|
||||||
// Get the list of used fields (columns)
|
// Get the list of used fields (columns)
|
||||||
char *p;
|
char *p;
|
||||||
unsigned int k1, k2, n1, n2;
|
unsigned int k1, k2, n1, n2;
|
||||||
Field* *field;
|
Field* *field;
|
||||||
Field* fp;
|
Field* fp;
|
||||||
MY_BITMAP *map= table->read_set;
|
MY_BITMAP *map= (xmod == MODE_INSERT) ? table->write_set : table->read_set;
|
||||||
MY_BITMAP *ump= (xmod == MODE_UPDATE) ? table->write_set : NULL;
|
MY_BITMAP *ump= (xmod == MODE_UPDATE) ? table->write_set : NULL;
|
||||||
|
|
||||||
k1= k2= 0;
|
k1= k2= 0;
|
||||||
@@ -1374,7 +1375,8 @@ int ha_connect::ScanRecord(PGLOBAL g, uchar *buf)
|
|||||||
fp->option_struct->special)
|
fp->option_struct->special)
|
||||||
continue; // Is a virtual column possible here ???
|
continue; // Is a virtual column possible here ???
|
||||||
|
|
||||||
if (xmod == MODE_INSERT ||
|
if ((xmod == MODE_INSERT && tdbp->GetAmType() != TYPE_AM_MYSQL
|
||||||
|
&& tdbp->GetAmType() != TYPE_AM_ODBC) ||
|
||||||
bitmap_is_set(table->write_set, fp->field_index)) {
|
bitmap_is_set(table->write_set, fp->field_index)) {
|
||||||
for (colp= tp->GetSetCols(); colp; colp= colp->GetNext())
|
for (colp= tp->GetSetCols(); colp; colp= colp->GetNext())
|
||||||
if (!stricmp(colp->GetName(), fp->field_name))
|
if (!stricmp(colp->GetName(), fp->field_name))
|
||||||
@@ -3464,7 +3466,7 @@ static bool add_field(String *sql, const char *field_name, int typ, int len,
|
|||||||
{
|
{
|
||||||
bool error= false;
|
bool error= false;
|
||||||
const char *type= PLGtoMYSQLtype(typ, dbf);
|
const char *type= PLGtoMYSQLtype(typ, dbf);
|
||||||
type= PLGtoMYSQLtype(typ, true);
|
// type= PLGtoMYSQLtype(typ, true); ?????
|
||||||
|
|
||||||
error|= sql->append('`');
|
error|= sql->append('`');
|
||||||
error|= sql->append(field_name);
|
error|= sql->append(field_name);
|
||||||
@@ -3948,7 +3950,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
|
|||||||
else
|
else
|
||||||
return HA_ERR_INTERNAL_ERROR; // Should never happen
|
return HA_ERR_INTERNAL_ERROR; // Should never happen
|
||||||
|
|
||||||
if (src && ttp != TAB_PIVOT) {
|
if (src && ttp != TAB_PIVOT && ttp != TAB_ODBC) {
|
||||||
qrp= SrcColumns(g, host, db, user, pwd, src, port);
|
qrp= SrcColumns(g, host, db, user, pwd, src, port);
|
||||||
|
|
||||||
if (qrp && ttp == TAB_OCCUR)
|
if (qrp && ttp == TAB_OCCUR)
|
||||||
@@ -3966,7 +3968,12 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
|
|||||||
switch (fnc) {
|
switch (fnc) {
|
||||||
case FNC_NO:
|
case FNC_NO:
|
||||||
case FNC_COL:
|
case FNC_COL:
|
||||||
|
if (src) {
|
||||||
|
qrp= ODBCSrcCols(g, dsn, (char*)src);
|
||||||
|
src= NULL; // for next tests
|
||||||
|
} else
|
||||||
qrp= ODBCColumns(g, dsn, (char *) tab, NULL, fnc == FNC_COL);
|
qrp= ODBCColumns(g, dsn, (char *) tab, NULL, fnc == FNC_COL);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case FNC_TABLE:
|
case FNC_TABLE:
|
||||||
qrp= ODBCTables(g, dsn, (char *) tab, true);
|
qrp= ODBCTables(g, dsn, (char *) tab, true);
|
||||||
|
@@ -4,5 +4,6 @@
|
|||||||
PQRYRES ODBCDataSources(PGLOBAL g, bool info);
|
PQRYRES ODBCDataSources(PGLOBAL g, bool info);
|
||||||
PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *table,
|
PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *table,
|
||||||
char *colpat, bool info);
|
char *colpat, bool info);
|
||||||
|
PQRYRES ODBCSrcCols(PGLOBAL g, char *dsn, char *src);
|
||||||
PQRYRES ODBCTables(PGLOBAL g, char *dsn, char *tabpat, bool info);
|
PQRYRES ODBCTables(PGLOBAL g, char *dsn, char *tabpat, bool info);
|
||||||
PQRYRES ODBCDrivers(PGLOBAL g, bool info);
|
PQRYRES ODBCDrivers(PGLOBAL g, bool info);
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/************ Odbconn C++ Functions Source Code File (.CPP) ************/
|
/************ 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 */
|
/* (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 */
|
/* ODBCColumns: constructs the result blocks containing all columns */
|
||||||
/* of an ODBC table that will be retrieved by GetData commands. */
|
/* 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,
|
PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *table,
|
||||||
char *colpat, bool info)
|
char *colpat, bool info)
|
||||||
@@ -318,6 +317,17 @@ PQRYRES ODBCColumns(PGLOBAL g, char *dsn, char *table,
|
|||||||
return qrp;
|
return qrp;
|
||||||
} // end of ODBCColumns
|
} // 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
|
#if 0
|
||||||
/**************************************************************************/
|
/**************************************************************************/
|
||||||
/* MyODBCCols: returns column info as required by ha_connect::pre_create. */
|
/* 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
|
} // 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. */
|
/* ODBConn construction/destruction. */
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
@@ -822,7 +843,7 @@ ODBConn::ODBConn(PGLOBAL g, TDBODBC *tdbp)
|
|||||||
m_Catver = (tdbp) ? tdbp->Catver : 0;
|
m_Catver = (tdbp) ? tdbp->Catver : 0;
|
||||||
m_Connect = NULL;
|
m_Connect = NULL;
|
||||||
m_Updatable = true;
|
m_Updatable = true;
|
||||||
//m_Transactions = false;
|
m_Transact = false;
|
||||||
m_IDQuoteChar = '\'';
|
m_IDQuoteChar = '\'';
|
||||||
//*m_ErrMsg = '\0';
|
//*m_ErrMsg = '\0';
|
||||||
} // end of ODBConn
|
} // end of ODBConn
|
||||||
@@ -1208,8 +1229,7 @@ int ODBConn::ExecDirectSQL(char *sql, ODBCCOL *tocols)
|
|||||||
void *buffer;
|
void *buffer;
|
||||||
bool b;
|
bool b;
|
||||||
UWORD n;
|
UWORD n;
|
||||||
SWORD ncol, len, tp;
|
SWORD len, tp, ncol = 0;
|
||||||
SQLLEN afrw;
|
|
||||||
ODBCCOL *colp;
|
ODBCCOL *colp;
|
||||||
RETCODE rc;
|
RETCODE rc;
|
||||||
HSTMT hstmt;
|
HSTMT hstmt;
|
||||||
@@ -1244,6 +1264,32 @@ int ODBConn::ExecDirectSQL(char *sql, ODBCCOL *tocols)
|
|||||||
if (trace)
|
if (trace)
|
||||||
htrc("ExecDirect hstmt=%p %.64s\n", hstmt, sql);
|
htrc("ExecDirect hstmt=%p %.64s\n", hstmt, sql);
|
||||||
|
|
||||||
|
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, "SQLPrepare", hstmt);
|
||||||
|
|
||||||
|
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 {
|
do {
|
||||||
rc = SQLExecDirect(hstmt, (PUCHAR)sql, SQL_NTS);
|
rc = SQLExecDirect(hstmt, (PUCHAR)sql, SQL_NTS);
|
||||||
} while (rc == SQL_STILL_EXECUTING);
|
} while (rc == SQL_STILL_EXECUTING);
|
||||||
@@ -1255,15 +1301,7 @@ int ODBConn::ExecDirectSQL(char *sql, ODBCCOL *tocols)
|
|||||||
rc = SQLNumResultCols(hstmt, &ncol);
|
rc = SQLNumResultCols(hstmt, &ncol);
|
||||||
} while (rc == SQL_STILL_EXECUTING);
|
} while (rc == SQL_STILL_EXECUTING);
|
||||||
|
|
||||||
if (ncol == 0) {
|
} // endif Srcdef
|
||||||
// Update or Delete statement
|
|
||||||
rc = SQLRowCount(hstmt, &afrw);
|
|
||||||
|
|
||||||
if (!Check(rc))
|
|
||||||
ThrowDBX(rc, "SQLRowCount", hstmt);
|
|
||||||
|
|
||||||
return afrw;
|
|
||||||
} // endif ncol
|
|
||||||
|
|
||||||
for (n = 0, colp = tocols; colp; colp = (PODBCCOL)colp->GetNext())
|
for (n = 0, colp = tocols; colp; colp = (PODBCCOL)colp->GetNext())
|
||||||
if (!colp->IsSpecial())
|
if (!colp->IsSpecial())
|
||||||
@@ -1411,10 +1449,33 @@ int ODBConn::PrepareSQL(char *sql)
|
|||||||
{
|
{
|
||||||
PGLOBAL& g = m_G;
|
PGLOBAL& g = m_G;
|
||||||
bool b;
|
bool b;
|
||||||
|
UINT txn = 0;
|
||||||
SWORD nparm;
|
SWORD nparm;
|
||||||
RETCODE rc;
|
RETCODE rc;
|
||||||
HSTMT hstmt;
|
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 {
|
try {
|
||||||
b = false;
|
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++)
|
for (int i = 0; i < MAX_NUM_OF_MSG && x->m_ErrMsg[i]; i++)
|
||||||
htrc(x->m_ErrMsg[i]);
|
htrc(x->m_ErrMsg[i]);
|
||||||
|
|
||||||
strcpy(m_G->Message, x->GetErrorMessage(0));
|
strcpy(g->Message, x->GetErrorMessage(0));
|
||||||
|
|
||||||
if (b)
|
if (b)
|
||||||
SQLCancel(hstmt);
|
SQLCancel(hstmt);
|
||||||
|
|
||||||
rc = SQLFreeStmt(hstmt, SQL_DROP);
|
rc = SQLFreeStmt(hstmt, SQL_DROP);
|
||||||
m_hstmt = NULL;
|
m_hstmt = NULL;
|
||||||
|
|
||||||
|
if (m_Transact) {
|
||||||
|
rc = SQLEndTran(SQL_HANDLE_DBC, m_hdbc, SQL_ROLLBACK);
|
||||||
|
m_Transact = false;
|
||||||
|
} // endif m_Transact
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
} // end try/catch
|
} // end try/catch
|
||||||
|
|
||||||
@@ -1469,27 +1536,59 @@ int ODBConn::PrepareSQL(char *sql)
|
|||||||
} // end of PrepareSQL
|
} // end of PrepareSQL
|
||||||
|
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
/* Bind a parameter for inserting. */
|
/* Execute a prepared statement. */
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
bool ODBConn::ExecuteSQL(void)
|
int ODBConn::ExecuteSQL(bool x)
|
||||||
{
|
{
|
||||||
|
PGLOBAL& g = m_G;
|
||||||
|
SWORD ncol = 0;
|
||||||
RETCODE rc;
|
RETCODE rc;
|
||||||
|
SQLLEN afrw = -1;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
do {
|
||||||
rc = SQLExecute(m_hstmt);
|
rc = SQLExecute(m_hstmt);
|
||||||
|
} while (rc == SQL_STILL_EXECUTING);
|
||||||
|
|
||||||
if (!Check(rc))
|
if (!Check(rc))
|
||||||
ThrowDBX(rc, "SQLExecute", m_hstmt);
|
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) {
|
} catch(DBX *x) {
|
||||||
strcpy(m_G->Message, x->GetErrorMessage(0));
|
strcpy(m_G->Message, x->GetErrorMessage(0));
|
||||||
SQLCancel(m_hstmt);
|
SQLCancel(m_hstmt);
|
||||||
rc = SQLFreeStmt(m_hstmt, SQL_DROP);
|
rc = SQLFreeStmt(m_hstmt, SQL_DROP);
|
||||||
m_hstmt = NULL;
|
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
|
} // end try/catch
|
||||||
|
|
||||||
return false;
|
return (int)afrw;
|
||||||
} // end of ExecuteSQL
|
} // end of ExecuteSQL
|
||||||
|
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
@@ -1541,6 +1640,132 @@ bool ODBConn::BindParam(ODBCCOL *colp)
|
|||||||
return false;
|
return false;
|
||||||
} // end of BindParam
|
} // 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. */
|
/* Get the list of Data Sources and set it in qrp. */
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
@@ -1844,6 +2069,11 @@ void ODBConn::Close()
|
|||||||
} // endif m_hstmt
|
} // endif m_hstmt
|
||||||
|
|
||||||
if (m_hdbc != SQL_NULL_HDBC) {
|
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);
|
rc = SQLDisconnect(m_hdbc);
|
||||||
|
|
||||||
if (trace && rc != SQL_SUCCESS)
|
if (trace && rc != SQL_SUCCESS)
|
||||||
|
@@ -91,8 +91,7 @@ class DBX : public BLOCK {
|
|||||||
// Implementation (use ThrowDBX to create)
|
// Implementation (use ThrowDBX to create)
|
||||||
RETCODE GetRC(void) {return m_RC;}
|
RETCODE GetRC(void) {return m_RC;}
|
||||||
PSZ GetMsg(void) {return m_Msg;}
|
PSZ GetMsg(void) {return m_Msg;}
|
||||||
const char *GetErrorMessage(int i)
|
const char *GetErrorMessage(int i);
|
||||||
{return (i >=0 && i < MAX_NUM_OF_MSG) ? m_ErrMsg[i] : "No ODBC error";}
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void BuildErrorMessage(ODBConn* pdb, HSTMT hstmt = SQL_NULL_HSTMT);
|
void BuildErrorMessage(ODBConn* pdb, HSTMT hstmt = SQL_NULL_HSTMT);
|
||||||
@@ -107,6 +106,7 @@ class DBX : public BLOCK {
|
|||||||
/* ODBConn class. */
|
/* ODBConn class. */
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
class ODBConn : public BLOCK {
|
class ODBConn : public BLOCK {
|
||||||
|
friend class TDBODBC;
|
||||||
friend class DBX;
|
friend class DBX;
|
||||||
friend PQRYRES GetColumnInfo(PGLOBAL, char*&, char *, int, PVBLK&);
|
friend PQRYRES GetColumnInfo(PGLOBAL, char*&, char *, int, PVBLK&);
|
||||||
private:
|
private:
|
||||||
@@ -142,11 +142,12 @@ class ODBConn : public BLOCK {
|
|||||||
int ExecDirectSQL(char *sql, ODBCCOL *tocols);
|
int ExecDirectSQL(char *sql, ODBCCOL *tocols);
|
||||||
int Fetch(void);
|
int Fetch(void);
|
||||||
int PrepareSQL(char *sql);
|
int PrepareSQL(char *sql);
|
||||||
bool ExecuteSQL(void);
|
int ExecuteSQL(bool x);
|
||||||
bool BindParam(ODBCCOL *colp);
|
bool BindParam(ODBCCOL *colp);
|
||||||
int GetCatInfo(CATPARM *cap);
|
int GetCatInfo(CATPARM *cap);
|
||||||
bool GetDataSources(PQRYRES qrp);
|
bool GetDataSources(PQRYRES qrp);
|
||||||
bool GetDrivers(PQRYRES qrp);
|
bool GetDrivers(PQRYRES qrp);
|
||||||
|
PQRYRES GetMetaData(PGLOBAL g, char *dsn, char *src);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Set special options
|
// Set special options
|
||||||
@@ -185,5 +186,6 @@ class ODBConn : public BLOCK {
|
|||||||
int m_Catver;
|
int m_Catver;
|
||||||
PSZ m_Connect;
|
PSZ m_Connect;
|
||||||
bool m_Updatable;
|
bool m_Updatable;
|
||||||
|
bool m_Transact;
|
||||||
char m_IDQuoteChar;
|
char m_IDQuoteChar;
|
||||||
}; // end of ODBConn class definition
|
}; // end of ODBConn class definition
|
||||||
|
@@ -884,9 +884,11 @@ void TDBDIR::CloseDB(PGLOBAL g)
|
|||||||
_findclose(Hsearch);
|
_findclose(Hsearch);
|
||||||
Hsearch = -1;
|
Hsearch = -1;
|
||||||
#else // !WIN32
|
#else // !WIN32
|
||||||
// Close the DIR handle.
|
// Close the DIR handle
|
||||||
|
if (dir) {
|
||||||
closedir(Dir);
|
closedir(Dir);
|
||||||
Dir = NULL;
|
Dir = NULL;
|
||||||
|
} // endif dir
|
||||||
#endif // !WIN32
|
#endif // !WIN32
|
||||||
iFile = 0;
|
iFile = 0;
|
||||||
} // end of CloseDB
|
} // end of CloseDB
|
||||||
|
@@ -1043,6 +1043,7 @@ int TDBMYSQL::DeleteDB(PGLOBAL g, int irc)
|
|||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
void TDBMYSQL::CloseDB(PGLOBAL g)
|
void TDBMYSQL::CloseDB(PGLOBAL g)
|
||||||
{
|
{
|
||||||
|
if (Myc.Connected()) {
|
||||||
if (Mode == MODE_INSERT) {
|
if (Mode == MODE_INSERT) {
|
||||||
char cmd[64];
|
char cmd[64];
|
||||||
int w;
|
int w;
|
||||||
@@ -1055,6 +1056,7 @@ void TDBMYSQL::CloseDB(PGLOBAL g)
|
|||||||
} // endif m_Rc
|
} // endif m_Rc
|
||||||
|
|
||||||
Myc.Close();
|
Myc.Close();
|
||||||
|
} // endif Myc
|
||||||
|
|
||||||
if (trace)
|
if (trace)
|
||||||
htrc("MySQL CloseDB: closing %s rc=%d\n", Name, m_Rc);
|
htrc("MySQL CloseDB: closing %s rc=%d\n", Name, m_Rc);
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
/************* Tabodbc C++ Program Source Code File (.CPP) *************/
|
/************* Tabodbc C++ Program Source Code File (.CPP) *************/
|
||||||
/* PROGRAM NAME: TABODBC */
|
/* PROGRAM NAME: TABODBC */
|
||||||
/* ------------- */
|
/* ------------- */
|
||||||
/* Version 2.5 */
|
/* Version 2.6 */
|
||||||
/* */
|
/* */
|
||||||
/* COPYRIGHT: */
|
/* COPYRIGHT: */
|
||||||
/* ---------- */
|
/* ---------- */
|
||||||
@@ -90,8 +90,9 @@ extern int num_read, num_there, num_eq[2]; // Statistics
|
|||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
ODBCDEF::ODBCDEF(void)
|
ODBCDEF::ODBCDEF(void)
|
||||||
{
|
{
|
||||||
Connect = Tabname = Tabowner = Tabqual = Qchar = NULL;
|
Connect = Tabname = Tabowner = Tabqual = Srcdef = Qchar = NULL;
|
||||||
Catver = Options = 0;
|
Catver = Options = 0;
|
||||||
|
Xsrc = false;
|
||||||
} // end of ODBCDEF constructor
|
} // end of ODBCDEF constructor
|
||||||
|
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
@@ -107,9 +108,11 @@ bool ODBCDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
|
|||||||
Tabname = Cat->GetStringCatInfo(g, "Tabname", Tabname);
|
Tabname = Cat->GetStringCatInfo(g, "Tabname", Tabname);
|
||||||
Tabowner = Cat->GetStringCatInfo(g, "Owner", "");
|
Tabowner = Cat->GetStringCatInfo(g, "Owner", "");
|
||||||
Tabqual = Cat->GetStringCatInfo(g, "Qualifier", "");
|
Tabqual = Cat->GetStringCatInfo(g, "Qualifier", "");
|
||||||
|
Srcdef = Cat->GetStringCatInfo(g, "Srcdef", NULL);
|
||||||
Qchar = Cat->GetStringCatInfo(g, "Qchar", "");
|
Qchar = Cat->GetStringCatInfo(g, "Qchar", "");
|
||||||
Catver = Cat->GetIntCatInfo("Catver", 2);
|
Catver = Cat->GetIntCatInfo("Catver", 2);
|
||||||
Options = Cat->GetIntCatInfo("Options", dop);
|
Options = Cat->GetIntCatInfo("Options", dop);
|
||||||
|
Xsrc = Cat->GetBoolCatInfo("Execsrc", FALSE);
|
||||||
Pseudo = 2; // FILID is Ok but not ROWID
|
Pseudo = 2; // FILID is Ok but not ROWID
|
||||||
return false;
|
return false;
|
||||||
} // end of DefineAM
|
} // end of DefineAM
|
||||||
@@ -125,7 +128,9 @@ PTDB ODBCDEF::GetTable(PGLOBAL g, MODE m)
|
|||||||
/* Allocate a TDB of the proper type. */
|
/* Allocate a TDB of the proper type. */
|
||||||
/* Column blocks will be allocated only when needed. */
|
/* Column blocks will be allocated only when needed. */
|
||||||
/*********************************************************************/
|
/*********************************************************************/
|
||||||
switch (Catfunc) {
|
if (Xsrc)
|
||||||
|
tdbp = new(g) TDBXDBC(this);
|
||||||
|
else switch (Catfunc) {
|
||||||
case FNC_COL:
|
case FNC_COL:
|
||||||
tdbp = new(g) TDBOCL(this);
|
tdbp = new(g) TDBOCL(this);
|
||||||
break;
|
break;
|
||||||
@@ -161,19 +166,21 @@ TDBODBC::TDBODBC(PODEF tdp) : TDBASE(tdp)
|
|||||||
Cnp = NULL;
|
Cnp = NULL;
|
||||||
|
|
||||||
if (tdp) {
|
if (tdp) {
|
||||||
Connect = tdp->GetConnect();
|
Connect = tdp->Connect;
|
||||||
TableName = tdp->GetTabname();
|
TableName = tdp->Tabname;
|
||||||
Owner = tdp->GetTabowner();
|
Owner = tdp->Tabowner;
|
||||||
Qualifier = tdp->GetTabqual();
|
Qualifier = tdp->Tabqual;
|
||||||
|
Srcdef = tdp->Srcdef;
|
||||||
Quote = tdp->GetQchar();
|
Quote = tdp->GetQchar();
|
||||||
Options = tdp->GetOptions();
|
Options = tdp->Options;
|
||||||
Rows = tdp->GetElemt();
|
Rows = tdp->GetElemt();
|
||||||
Catver = tdp->GetCatver();
|
Catver = tdp->Catver;
|
||||||
} else {
|
} else {
|
||||||
Connect = NULL;
|
Connect = NULL;
|
||||||
TableName = NULL;
|
TableName = NULL;
|
||||||
Owner = NULL;
|
Owner = NULL;
|
||||||
Qualifier = NULL;
|
Qualifier = NULL;
|
||||||
|
Srcdef = NULL;
|
||||||
Quote = NULL;
|
Quote = NULL;
|
||||||
Options = 0;
|
Options = 0;
|
||||||
Rows = 0;
|
Rows = 0;
|
||||||
@@ -201,6 +208,7 @@ TDBODBC::TDBODBC(PTDBODBC tdbp) : TDBASE(tdbp)
|
|||||||
TableName = tdbp->TableName;
|
TableName = tdbp->TableName;
|
||||||
Owner = tdbp->Owner;
|
Owner = tdbp->Owner;
|
||||||
Qualifier = tdbp->Qualifier;
|
Qualifier = tdbp->Qualifier;
|
||||||
|
Srcdef = tdbp->Srcdef;
|
||||||
Quote = tdbp->Quote;
|
Quote = tdbp->Quote;
|
||||||
Query = tdbp->Query;
|
Query = tdbp->Query;
|
||||||
Count = tdbp->Count;
|
Count = tdbp->Count;
|
||||||
@@ -299,7 +307,6 @@ void TDBODBC::SetFile(PGLOBAL g, PSZ fn)
|
|||||||
DBQ = fn;
|
DBQ = fn;
|
||||||
} // end of SetFile
|
} // end of SetFile
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************/
|
/******************************************************************/
|
||||||
/* Convert an UTF-8 string to latin characters. */
|
/* Convert an UTF-8 string to latin characters. */
|
||||||
/******************************************************************/
|
/******************************************************************/
|
||||||
@@ -314,7 +321,6 @@ int TDBODBC::Decode(char *txt, char *buf, size_t n)
|
|||||||
return 0;
|
return 0;
|
||||||
} // end of Decode
|
} // end of Decode
|
||||||
|
|
||||||
|
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
/* MakeSQL: make the SQL statement use with ODBC connection. */
|
/* MakeSQL: make the SQL statement use with ODBC connection. */
|
||||||
/* Note: when implementing EOM filtering, column only used in local */
|
/* Note: when implementing EOM filtering, column only used in local */
|
||||||
@@ -329,6 +335,9 @@ char *TDBODBC::MakeSQL(PGLOBAL g, bool cnt)
|
|||||||
PTABLE tablep = To_Table;
|
PTABLE tablep = To_Table;
|
||||||
PCOL colp;
|
PCOL colp;
|
||||||
|
|
||||||
|
if (Srcdef)
|
||||||
|
return Srcdef;
|
||||||
|
|
||||||
if (!cnt) {
|
if (!cnt) {
|
||||||
// Normal SQL statement to retrieve results
|
// Normal SQL statement to retrieve results
|
||||||
for (colp = Columns; colp; colp = colp->GetNext())
|
for (colp = Columns; colp; colp = colp->GetNext())
|
||||||
@@ -430,6 +439,83 @@ char *TDBODBC::MakeSQL(PGLOBAL g, bool cnt)
|
|||||||
return sql;
|
return sql;
|
||||||
} // end of MakeSQL
|
} // end of MakeSQL
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
/* MakeInsert: make the Insert statement used with ODBC connection. */
|
||||||
|
/***********************************************************************/
|
||||||
|
bool TDBODBC::MakeInsert(PGLOBAL g)
|
||||||
|
{
|
||||||
|
char *colist, *valist;
|
||||||
|
// char *tk = "`";
|
||||||
|
int len = 0;
|
||||||
|
bool b = FALSE;
|
||||||
|
PCOL colp;
|
||||||
|
|
||||||
|
if (Query)
|
||||||
|
return false; // already done
|
||||||
|
|
||||||
|
for (colp = Columns; colp; colp = colp->GetNext())
|
||||||
|
if (colp->IsSpecial()) {
|
||||||
|
strcpy(g->Message, MSG(NO_ODBC_SPECOL));
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
len += (strlen(colp->GetName()) + 4);
|
||||||
|
((PODBCCOL)colp)->Rank = ++Nparm;
|
||||||
|
} // endif colp
|
||||||
|
|
||||||
|
colist = (char*)PlugSubAlloc(g, NULL, len);
|
||||||
|
*colist = '\0';
|
||||||
|
valist = (char*)PlugSubAlloc(g, NULL, 2 * Nparm);
|
||||||
|
*valist = '\0';
|
||||||
|
|
||||||
|
for (colp = Columns; colp; colp = colp->GetNext()) {
|
||||||
|
if (b) {
|
||||||
|
strcat(colist, ", ");
|
||||||
|
strcat(valist, ",");
|
||||||
|
} else
|
||||||
|
b = true;
|
||||||
|
|
||||||
|
if (Quote)
|
||||||
|
strcat(strcat(strcat(colist, Quote), colp->GetName()), Quote);
|
||||||
|
else
|
||||||
|
strcat(colist, colp->GetName());
|
||||||
|
|
||||||
|
strcat(valist, "?"); // Parameter marker
|
||||||
|
} // endfor colp
|
||||||
|
|
||||||
|
// Below 32 is enough to contain the fixed part of the query
|
||||||
|
len = (strlen(TableName) + strlen(colist) + strlen(valist) + 32);
|
||||||
|
Query = (char*)PlugSubAlloc(g, NULL, len);
|
||||||
|
strcpy(Query, "INSERT INTO ");
|
||||||
|
|
||||||
|
if (Quote)
|
||||||
|
strcat(strcat(strcat(Query, Quote), TableName), Quote);
|
||||||
|
else
|
||||||
|
strcat(Query, TableName);
|
||||||
|
|
||||||
|
strcat(strcat(strcat(Query, " ("), colist), ") VALUES (");
|
||||||
|
strcat(strcat(Query, valist), ")");
|
||||||
|
|
||||||
|
return false;
|
||||||
|
} // end of MakeInsert
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
/* ODBC Bind Parameter function. */
|
||||||
|
/***********************************************************************/
|
||||||
|
bool TDBODBC::BindParameters(PGLOBAL g)
|
||||||
|
{
|
||||||
|
PODBCCOL colp;
|
||||||
|
|
||||||
|
for (colp = (PODBCCOL)Columns; colp; colp = (PODBCCOL)colp->Next) {
|
||||||
|
colp->AllocateBuffers(g, 0);
|
||||||
|
|
||||||
|
if (Ocp->BindParam(colp))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
} // endfor colp
|
||||||
|
|
||||||
|
return false;
|
||||||
|
} // end of BindParameters
|
||||||
|
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
/* ResetSize: call by TDBMUL when calculating size estimate. */
|
/* ResetSize: call by TDBMUL when calculating size estimate. */
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
@@ -448,6 +534,12 @@ void TDBODBC::ResetSize(void)
|
|||||||
int TDBODBC::GetMaxSize(PGLOBAL g)
|
int TDBODBC::GetMaxSize(PGLOBAL g)
|
||||||
{
|
{
|
||||||
if (MaxSize < 0) {
|
if (MaxSize < 0) {
|
||||||
|
if (Srcdef) {
|
||||||
|
// Give a reasonable guess
|
||||||
|
MaxSize = 100;
|
||||||
|
return MaxSize;
|
||||||
|
} // endif Srcdef
|
||||||
|
|
||||||
if (!Ocp)
|
if (!Ocp)
|
||||||
Ocp = new(g) ODBConn(g, this);
|
Ocp = new(g) ODBConn(g, this);
|
||||||
|
|
||||||
@@ -473,12 +565,11 @@ int TDBODBC::GetMaxSize(PGLOBAL g)
|
|||||||
} // end of GetMaxSize
|
} // end of GetMaxSize
|
||||||
|
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
/* Return 0 in mode DELETE or UPDATE to tell that it is done. */
|
/* Return max size value. */
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
int TDBODBC::GetProgMax(PGLOBAL g)
|
int TDBODBC::GetProgMax(PGLOBAL g)
|
||||||
{
|
{
|
||||||
return (Mode == MODE_DELETE || Mode == MODE_UPDATE) ? 0
|
return GetMaxSize(g);
|
||||||
: GetMaxSize(g);
|
|
||||||
} // end of GetProgMax
|
} // end of GetProgMax
|
||||||
|
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
@@ -546,14 +637,24 @@ bool TDBODBC::OpenDB(PGLOBAL g)
|
|||||||
if (!colp->IsSpecial())
|
if (!colp->IsSpecial())
|
||||||
colp->AllocateBuffers(g, Rows);
|
colp->AllocateBuffers(g, Rows);
|
||||||
|
|
||||||
} else
|
} else {
|
||||||
rc = true;
|
Ocp->Close();
|
||||||
|
return true;
|
||||||
|
} // endif Query
|
||||||
|
|
||||||
if (!rc)
|
if (!rc)
|
||||||
rc = ((Rows = Ocp->ExecDirectSQL(Query, (PODBCCOL)Columns)) < 0);
|
rc = ((Rows = Ocp->ExecDirectSQL(Query, (PODBCCOL)Columns)) < 0);
|
||||||
|
|
||||||
|
} else if (Mode == MODE_INSERT) {
|
||||||
|
if (!(rc = MakeInsert(g)))
|
||||||
|
if (Nparm != Ocp->PrepareSQL(Query)) {
|
||||||
|
strcpy(g->Message, MSG(PARM_CNT_MISS));
|
||||||
|
rc = true;
|
||||||
|
} else
|
||||||
|
rc = BindParameters(g);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
strcpy(g->Message, "ODBC tables are read only in this version");
|
strcpy(g->Message, "No DELETE/UPDATE of ODBC tablesd");
|
||||||
return true;
|
return true;
|
||||||
} // endelse
|
} // endelse
|
||||||
|
|
||||||
@@ -592,30 +693,6 @@ int TDBODBC::ReadDB(PGLOBAL g)
|
|||||||
// Direct access of ODBC tables is not implemented yet
|
// Direct access of ODBC tables is not implemented yet
|
||||||
strcpy(g->Message, MSG(NO_ODBC_DIRECT));
|
strcpy(g->Message, MSG(NO_ODBC_DIRECT));
|
||||||
longjmp(g->jumper[g->jump_level], GetAmType());
|
longjmp(g->jumper[g->jump_level], GetAmType());
|
||||||
|
|
||||||
#if 0
|
|
||||||
/*******************************************************************/
|
|
||||||
/* Reading is by an index table. */
|
|
||||||
/*******************************************************************/
|
|
||||||
int recpos = To_Kindex->Fetch(g);
|
|
||||||
|
|
||||||
switch (recpos) {
|
|
||||||
case -1: // End of file reached
|
|
||||||
return RC_EF;
|
|
||||||
case -2: // No match for join
|
|
||||||
return RC_NF;
|
|
||||||
case -3: // Same record as current one
|
|
||||||
num_there++;
|
|
||||||
return RC_OK;
|
|
||||||
default:
|
|
||||||
/***************************************************************/
|
|
||||||
/* Set the cursor position according to record to read. */
|
|
||||||
/***************************************************************/
|
|
||||||
//--------------------------------- TODO --------------------------------
|
|
||||||
break;
|
|
||||||
} // endswitch recpos
|
|
||||||
#endif // 0
|
|
||||||
|
|
||||||
} // endif To_Kindex
|
} // endif To_Kindex
|
||||||
|
|
||||||
/*********************************************************************/
|
/*********************************************************************/
|
||||||
@@ -641,8 +718,15 @@ int TDBODBC::ReadDB(PGLOBAL g)
|
|||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
int TDBODBC::WriteDB(PGLOBAL g)
|
int TDBODBC::WriteDB(PGLOBAL g)
|
||||||
{
|
{
|
||||||
strcpy(g->Message, "ODBC tables are read only");
|
int n = Ocp->ExecuteSQL(false);
|
||||||
|
|
||||||
|
if (n < 0) {
|
||||||
|
AftRows = n;
|
||||||
return RC_FX;
|
return RC_FX;
|
||||||
|
} else
|
||||||
|
AftRows += n;
|
||||||
|
|
||||||
|
return RC_OK;
|
||||||
} // end of WriteDB
|
} // end of WriteDB
|
||||||
|
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
@@ -664,6 +748,7 @@ void TDBODBC::CloseDB(PGLOBAL g)
|
|||||||
// To_Kindex = NULL;
|
// To_Kindex = NULL;
|
||||||
// } // endif
|
// } // endif
|
||||||
|
|
||||||
|
if (Ocp)
|
||||||
Ocp->Close();
|
Ocp->Close();
|
||||||
|
|
||||||
if (trace)
|
if (trace)
|
||||||
@@ -892,7 +977,7 @@ void ODBCCOL::WriteColumn(PGLOBAL g)
|
|||||||
/* Do convert the column value if necessary. */
|
/* Do convert the column value if necessary. */
|
||||||
/*********************************************************************/
|
/*********************************************************************/
|
||||||
if (Value != To_Val)
|
if (Value != To_Val)
|
||||||
Value->SetValue_pval(To_Val, false); // Convert the inserted value
|
Value->SetValue_pval(To_Val, FALSE); // Convert the inserted value
|
||||||
|
|
||||||
if (Buf_Type == TYPE_DATE) {
|
if (Buf_Type == TYPE_DATE) {
|
||||||
struct tm tm, *dbtime = ((DTVAL*)Value)->GetGmTime(&tm);
|
struct tm tm, *dbtime = ((DTVAL*)Value)->GetGmTime(&tm);
|
||||||
@@ -903,8 +988,242 @@ void ODBCCOL::WriteColumn(PGLOBAL g)
|
|||||||
Sqlbuf->day = dbtime->tm_mday;
|
Sqlbuf->day = dbtime->tm_mday;
|
||||||
Sqlbuf->month = dbtime->tm_mon + 1;
|
Sqlbuf->month = dbtime->tm_mon + 1;
|
||||||
Sqlbuf->year = dbtime->tm_year + 1900;
|
Sqlbuf->year = dbtime->tm_year + 1900;
|
||||||
|
Sqlbuf->fraction = 0;
|
||||||
} // endif Buf_Type
|
} // endif Buf_Type
|
||||||
|
|
||||||
|
if (Nullable)
|
||||||
|
*StrLen = (Value->IsNull()) ? SQL_NULL_DATA :
|
||||||
|
(IsTypeNum(Buf_Type)) ? 0 : SQL_NTS;
|
||||||
|
|
||||||
|
} // end of WriteColumn
|
||||||
|
|
||||||
|
/* -------------------------- Class TDBXDBC -------------------------- */
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
/* Implementation of the TDBODBC class. */
|
||||||
|
/***********************************************************************/
|
||||||
|
PTDB TDBXDBC::CopyOne(PTABS t)
|
||||||
|
{
|
||||||
|
PTDB tp;
|
||||||
|
PXSRCCOL cp1, cp2;
|
||||||
|
PGLOBAL g = t->G; // Is this really useful ???
|
||||||
|
|
||||||
|
tp = new(g) TDBXDBC(this);
|
||||||
|
|
||||||
|
for (cp1 = (PXSRCCOL)Columns; cp1; cp1 = (PXSRCCOL)cp1->GetNext()) {
|
||||||
|
cp2 = new(g) XSRCCOL(cp1, tp); // Make a copy
|
||||||
|
NewPointer(t, cp1, cp2);
|
||||||
|
} // endfor cp1
|
||||||
|
|
||||||
|
return tp;
|
||||||
|
} // end of CopyOne
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
/* Allocate XSRC column description block. */
|
||||||
|
/***********************************************************************/
|
||||||
|
PCOL TDBXDBC::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
|
||||||
|
{
|
||||||
|
PXSRCCOL colp = new(g) XSRCCOL(cdp, this, cprec, n);
|
||||||
|
|
||||||
|
if (!colp->Flag)
|
||||||
|
Cmdcol = colp->GetName();
|
||||||
|
|
||||||
|
return colp;
|
||||||
|
} // end of MakeCol
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
/* MakeCMD: make the SQL statement to send to ODBC connection. */
|
||||||
|
/***********************************************************************/
|
||||||
|
char *TDBXDBC::MakeCMD(PGLOBAL g)
|
||||||
|
{
|
||||||
|
char *xcmd = NULL;
|
||||||
|
|
||||||
|
if (To_Filter) {
|
||||||
|
if (Cmdcol) {
|
||||||
|
char col[128], cmd[1024];
|
||||||
|
int n = sscanf(To_Filter, "%s = '%[^\0]", col, cmd);
|
||||||
|
|
||||||
|
if (n == 2 && !stricmp(col, Cmdcol)) {
|
||||||
|
xcmd = (char*)PlugSubAlloc(g, NULL, strlen(cmd) + 1);
|
||||||
|
|
||||||
|
strcpy(xcmd, cmd);
|
||||||
|
xcmd[strlen(xcmd) - 1] = 0;
|
||||||
|
} else
|
||||||
|
strcpy(g->Message, "Invalid command specification filter");
|
||||||
|
|
||||||
|
} else
|
||||||
|
strcpy(g->Message, "No command column in select list");
|
||||||
|
|
||||||
|
} else if (!Srcdef)
|
||||||
|
strcpy(g->Message, "No Srcdef default command");
|
||||||
|
else
|
||||||
|
xcmd = Srcdef;
|
||||||
|
|
||||||
|
return xcmd;
|
||||||
|
} // end of MakeCMD
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/***********************************************************************/
|
||||||
|
/* ODBC Bind Parameter function. */
|
||||||
|
/***********************************************************************/
|
||||||
|
bool TDBXDBC::BindParameters(PGLOBAL g)
|
||||||
|
{
|
||||||
|
PODBCCOL colp;
|
||||||
|
|
||||||
|
for (colp = (PODBCCOL)Columns; colp; colp = (PODBCCOL)colp->Next) {
|
||||||
|
colp->AllocateBuffers(g, 0);
|
||||||
|
|
||||||
|
if (Ocp->BindParam(colp))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
} // endfor colp
|
||||||
|
|
||||||
|
return false;
|
||||||
|
} // end of BindParameters
|
||||||
|
#endif // 0
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
/* XDBC GetMaxSize: returns table size (always one row). */
|
||||||
|
/***********************************************************************/
|
||||||
|
int TDBXDBC::GetMaxSize(PGLOBAL g)
|
||||||
|
{
|
||||||
|
if (MaxSize < 0)
|
||||||
|
MaxSize = 1;
|
||||||
|
|
||||||
|
return MaxSize;
|
||||||
|
} // end of GetMaxSize
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
/* ODBC Access Method opening routine. */
|
||||||
|
/* New method now that this routine is called recursively (last table */
|
||||||
|
/* first in reverse order): index blocks are immediately linked to */
|
||||||
|
/* join block of next table if it exists or else are discarted. */
|
||||||
|
/***********************************************************************/
|
||||||
|
bool TDBXDBC::OpenDB(PGLOBAL g)
|
||||||
|
{
|
||||||
|
bool rc = false;
|
||||||
|
|
||||||
|
if (g->Trace)
|
||||||
|
htrc("ODBC OpenDB: tdbp=%p tdb=R%d use=%dmode=%d\n",
|
||||||
|
this, Tdb_No, Use, Mode);
|
||||||
|
|
||||||
|
if (Use == USE_OPEN) {
|
||||||
|
strcpy(g->Message, "Multiple execution is not allowed");
|
||||||
|
return true;
|
||||||
|
} // endif use
|
||||||
|
|
||||||
|
/*********************************************************************/
|
||||||
|
/* Open an ODBC connection for this table. */
|
||||||
|
/* Note: this may not be the proper way to do. Perhaps it is better */
|
||||||
|
/* to test whether a connection is already open for this datasource */
|
||||||
|
/* and if so to allocate just a new result set. But this only for */
|
||||||
|
/* drivers allowing concurency in getting results ??? */
|
||||||
|
/*********************************************************************/
|
||||||
|
if (!Ocp)
|
||||||
|
Ocp = new(g) ODBConn(g, this);
|
||||||
|
else if (Ocp->IsOpen())
|
||||||
|
Ocp->Close();
|
||||||
|
|
||||||
|
if (Ocp->Open(Connect, Options) < 1)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
Use = USE_OPEN; // Do it now in case we are recursively called
|
||||||
|
|
||||||
|
if (Mode != MODE_READ) {
|
||||||
|
strcpy(g->Message, "No INSERT/DELETE/UPDATE of XDBC tables");
|
||||||
|
return true;
|
||||||
|
} // endif Mode
|
||||||
|
|
||||||
|
/*********************************************************************/
|
||||||
|
/* Get the command to execute. */
|
||||||
|
/*********************************************************************/
|
||||||
|
if (!(Query = MakeCMD(g))) {
|
||||||
|
Ocp->Close();
|
||||||
|
return true;
|
||||||
|
} // endif Query
|
||||||
|
|
||||||
|
Rows = 1;
|
||||||
|
|
||||||
|
if (Ocp->PrepareSQL(Query)) {
|
||||||
|
strcpy(g->Message, "Parameters not supported");
|
||||||
|
AftRows = -1;
|
||||||
|
} else
|
||||||
|
AftRows = 0;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
} // end of OpenDB
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
/* ReadDB: Data Base read routine for xdbc access method. */
|
||||||
|
/***********************************************************************/
|
||||||
|
int TDBXDBC::ReadDB(PGLOBAL g)
|
||||||
|
{
|
||||||
|
if (trace)
|
||||||
|
htrc("XDBC ReadDB: query=%s\n", SVP(Query));
|
||||||
|
|
||||||
|
if (Rows--) {
|
||||||
|
if (!AftRows)
|
||||||
|
AftRows = Ocp->ExecuteSQL(true);
|
||||||
|
|
||||||
|
} else
|
||||||
|
return RC_EF;
|
||||||
|
|
||||||
|
Fpos++; // Used for progress info
|
||||||
|
return RC_OK;
|
||||||
|
} // end of ReadDB
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
/* Data Base delete line routine for ODBC access method. */
|
||||||
|
/***********************************************************************/
|
||||||
|
int TDBXDBC::WriteDB(PGLOBAL g)
|
||||||
|
{
|
||||||
|
strcpy(g->Message, "Execsrc tables are read only");
|
||||||
|
return RC_FX;
|
||||||
|
} // end of DeleteDB
|
||||||
|
|
||||||
|
/* --------------------------- XSRCCOL ------------------------------- */
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
/* XSRCCOL public constructor. */
|
||||||
|
/***********************************************************************/
|
||||||
|
XSRCCOL::XSRCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am)
|
||||||
|
: ODBCCOL(cdp, tdbp, cprec, i, am)
|
||||||
|
{
|
||||||
|
// Set additional ODBC access method information for column.
|
||||||
|
Flag = cdp->GetOffset();
|
||||||
|
} // end of XSRCCOL constructor
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
/* XSRCCOL constructor used for copying columns. */
|
||||||
|
/* tdbp is the pointer to the new table descriptor. */
|
||||||
|
/***********************************************************************/
|
||||||
|
XSRCCOL::XSRCCOL(XSRCCOL *col1, PTDB tdbp) : ODBCCOL(col1, tdbp)
|
||||||
|
{
|
||||||
|
Flag = col1->Flag;
|
||||||
|
} // end of XSRCCOL copy constructor
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
/* ReadColumn: set column value according to Flag. */
|
||||||
|
/***********************************************************************/
|
||||||
|
void XSRCCOL::ReadColumn(PGLOBAL g)
|
||||||
|
{
|
||||||
|
PTDBXDBC tdbp = (PTDBXDBC)To_Tdb;
|
||||||
|
|
||||||
|
switch (Flag) {
|
||||||
|
case 0: Value->SetValue_psz(tdbp->Query); break;
|
||||||
|
case 1: Value->SetValue(tdbp->AftRows); break;
|
||||||
|
case 2: Value->SetValue_psz(g->Message); break;
|
||||||
|
default: Value->SetValue_psz("Invalid Flag"); break;
|
||||||
|
} // endswitch Flag
|
||||||
|
|
||||||
|
} // end of ReadColumn
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
/* WriteColumn: Should never be called. */
|
||||||
|
/***********************************************************************/
|
||||||
|
void XSRCCOL::WriteColumn(PGLOBAL g)
|
||||||
|
{
|
||||||
|
// Should never be called
|
||||||
} // end of WriteColumn
|
} // end of WriteColumn
|
||||||
|
|
||||||
/* ---------------------------TDBSRC class --------------------------- */
|
/* ---------------------------TDBSRC class --------------------------- */
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*************** Tabodbc H Declares Source Code File (.H) **************/
|
/*************** Tabodbc H Declares Source Code File (.H) **************/
|
||||||
/* Name: TABODBC.H Version 1.5 */
|
/* Name: TABODBC.H Version 1.6 */
|
||||||
/* */
|
/* */
|
||||||
/* (C) Copyright to the author Olivier BERTRAND 2000-2013 */
|
/* (C) Copyright to the author Olivier BERTRAND 2000-2013 */
|
||||||
/* */
|
/* */
|
||||||
@@ -11,6 +11,8 @@
|
|||||||
typedef class ODBCDEF *PODEF;
|
typedef class ODBCDEF *PODEF;
|
||||||
typedef class TDBODBC *PTDBODBC;
|
typedef class TDBODBC *PTDBODBC;
|
||||||
typedef class ODBCCOL *PODBCCOL;
|
typedef class ODBCCOL *PODBCCOL;
|
||||||
|
typedef class TDBXDBC *PTDBXDBC;
|
||||||
|
typedef class XSRCCOL *PXSRCCOL;
|
||||||
typedef class TDBOIF *PTDBOIF;
|
typedef class TDBOIF *PTDBOIF;
|
||||||
typedef class OIFCOL *POIFCOL;
|
typedef class OIFCOL *POIFCOL;
|
||||||
typedef class TDBSRC *PTDBSRC;
|
typedef class TDBSRC *PTDBSRC;
|
||||||
@@ -19,6 +21,8 @@ typedef class TDBSRC *PTDBSRC;
|
|||||||
/* ODBC table. */
|
/* ODBC table. */
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
class DllExport ODBCDEF : public TABDEF { /* Logical table description */
|
class DllExport ODBCDEF : public TABDEF { /* Logical table description */
|
||||||
|
friend class TDBODBC;
|
||||||
|
friend class TDBXDBC;
|
||||||
public:
|
public:
|
||||||
// Constructor
|
// Constructor
|
||||||
ODBCDEF(void);
|
ODBCDEF(void);
|
||||||
@@ -29,6 +33,7 @@ class DllExport ODBCDEF : public TABDEF { /* Logical table description */
|
|||||||
PSZ GetTabname(void) {return Tabname;}
|
PSZ GetTabname(void) {return Tabname;}
|
||||||
PSZ GetTabowner(void) {return Tabowner;}
|
PSZ GetTabowner(void) {return Tabowner;}
|
||||||
PSZ GetTabqual(void) {return Tabqual;}
|
PSZ GetTabqual(void) {return Tabqual;}
|
||||||
|
PSZ GetSrcdef(void) {return Srcdef;}
|
||||||
PSZ GetQchar(void) {return (Qchar && *Qchar) ? Qchar : NULL;}
|
PSZ GetQchar(void) {return (Qchar && *Qchar) ? Qchar : NULL;}
|
||||||
int GetCatver(void) {return Catver;}
|
int GetCatver(void) {return Catver;}
|
||||||
int GetOptions(void) {return Options;}
|
int GetOptions(void) {return Options;}
|
||||||
@@ -43,9 +48,11 @@ class DllExport ODBCDEF : public TABDEF { /* Logical table description */
|
|||||||
PSZ Tabname; /* External table name */
|
PSZ Tabname; /* External table name */
|
||||||
PSZ Tabowner; /* External table owner */
|
PSZ Tabowner; /* External table owner */
|
||||||
PSZ Tabqual; /* External table qualifier */
|
PSZ Tabqual; /* External table qualifier */
|
||||||
|
PSZ Srcdef; /* The source table SQL definition */
|
||||||
PSZ Qchar; /* Identifier quoting character */
|
PSZ Qchar; /* Identifier quoting character */
|
||||||
int Catver; /* ODBC version for catalog functions */
|
int Catver; /* ODBC version for catalog functions */
|
||||||
int Options; /* Open connection options */
|
int Options; /* Open connection options */
|
||||||
|
bool Xsrc; /* Execution type */
|
||||||
}; // end of ODBCDEF
|
}; // end of ODBCDEF
|
||||||
|
|
||||||
#if !defined(NODBC)
|
#if !defined(NODBC)
|
||||||
@@ -92,10 +99,10 @@ class TDBODBC : public TDBASE {
|
|||||||
int Decode(char *utf, char *buf, size_t n);
|
int Decode(char *utf, char *buf, size_t n);
|
||||||
char *MakeSQL(PGLOBAL g, bool cnt);
|
char *MakeSQL(PGLOBAL g, bool cnt);
|
||||||
//bool MakeUpdate(PGLOBAL g, PSELECT selist);
|
//bool MakeUpdate(PGLOBAL g, PSELECT selist);
|
||||||
//bool MakeInsert(PGLOBAL g);
|
bool MakeInsert(PGLOBAL g);
|
||||||
//bool MakeDelete(PGLOBAL g);
|
//bool MakeDelete(PGLOBAL g);
|
||||||
//bool MakeFilter(PGLOBAL g, bool c);
|
//bool MakeFilter(PGLOBAL g, bool c);
|
||||||
//bool BindParameters(PGLOBAL g);
|
bool BindParameters(PGLOBAL g);
|
||||||
|
|
||||||
// Members
|
// Members
|
||||||
ODBConn *Ocp; // Points to an ODBC connection class
|
ODBConn *Ocp; // Points to an ODBC connection class
|
||||||
@@ -104,6 +111,7 @@ class TDBODBC : public TDBASE {
|
|||||||
char *TableName; // Points to ODBC table name
|
char *TableName; // Points to ODBC table name
|
||||||
char *Owner; // Points to ODBC table Owner
|
char *Owner; // Points to ODBC table Owner
|
||||||
char *Qualifier; // Points to ODBC table Qualifier
|
char *Qualifier; // Points to ODBC table Qualifier
|
||||||
|
char *Srcdef; // The source table SQL definition
|
||||||
char *Query; // Points to SQL statement
|
char *Query; // Points to SQL statement
|
||||||
char *Count; // Points to count(*) SQL statement
|
char *Count; // Points to count(*) SQL statement
|
||||||
//char *Where; // Points to local where clause
|
//char *Where; // Points to local where clause
|
||||||
@@ -122,7 +130,7 @@ class TDBODBC : public TDBASE {
|
|||||||
}; // end of class TDBODBC
|
}; // end of class TDBODBC
|
||||||
|
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
/* Class ODBCCOL: DOS access method column descriptor. */
|
/* Class ODBCCOL: ODBC access method column descriptor. */
|
||||||
/* This A.M. is used for ODBC tables. */
|
/* This A.M. is used for ODBC tables. */
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
class ODBCCOL : public COLBLK {
|
class ODBCCOL : public COLBLK {
|
||||||
@@ -163,6 +171,75 @@ class ODBCCOL : public COLBLK {
|
|||||||
int Rank; // Rank (position) number in the query
|
int Rank; // Rank (position) number in the query
|
||||||
}; // end of class ODBCCOL
|
}; // end of class ODBCCOL
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
/* This is the ODBC Access Method class declaration that send */
|
||||||
|
/* commands to be executed by other DB ODBC drivers. */
|
||||||
|
/***********************************************************************/
|
||||||
|
class TDBXDBC : public TDBODBC {
|
||||||
|
friend class XSRCCOL;
|
||||||
|
friend class ODBConn;
|
||||||
|
public:
|
||||||
|
// Constructor
|
||||||
|
TDBXDBC(PODEF tdp = NULL) : TDBODBC(tdp) {Cmdcol = NULL;}
|
||||||
|
TDBXDBC(PTDBXDBC tdbp) : TDBODBC(tdbp) {Cmdcol = tdbp->Cmdcol;}
|
||||||
|
|
||||||
|
// Implementation
|
||||||
|
//virtual AMT GetAmType(void) {return TYPE_AM_ODBC;}
|
||||||
|
virtual PTDB Duplicate(PGLOBAL g)
|
||||||
|
{return (PTDB)new(g) TDBXDBC(this);}
|
||||||
|
|
||||||
|
// Methods
|
||||||
|
virtual PTDB CopyOne(PTABS t);
|
||||||
|
//virtual int GetRecpos(void);
|
||||||
|
//virtual PSZ GetFile(PGLOBAL g);
|
||||||
|
//virtual void SetFile(PGLOBAL g, PSZ fn);
|
||||||
|
//virtual void ResetSize(void);
|
||||||
|
//virtual int GetAffectedRows(void) {return AftRows;}
|
||||||
|
//virtual PSZ GetServer(void) {return "ODBC";}
|
||||||
|
|
||||||
|
// Database routines
|
||||||
|
virtual PCOL MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n);
|
||||||
|
//virtual int GetProgMax(PGLOBAL g);
|
||||||
|
virtual int GetMaxSize(PGLOBAL g);
|
||||||
|
virtual bool OpenDB(PGLOBAL g);
|
||||||
|
virtual int ReadDB(PGLOBAL g);
|
||||||
|
virtual int WriteDB(PGLOBAL g);
|
||||||
|
//virtual int DeleteDB(PGLOBAL g, int irc);
|
||||||
|
//virtual void CloseDB(PGLOBAL g);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// Internal functions
|
||||||
|
char *MakeCMD(PGLOBAL g);
|
||||||
|
//bool BindParameters(PGLOBAL g);
|
||||||
|
|
||||||
|
// Members
|
||||||
|
char *Cmdcol; // The name of the Xsrc command column
|
||||||
|
}; // end of class TDBXDBC
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
/* Used by table in source execute mode. */
|
||||||
|
/***********************************************************************/
|
||||||
|
class XSRCCOL : public ODBCCOL {
|
||||||
|
friend class TDBXDBC;
|
||||||
|
public:
|
||||||
|
// Constructors
|
||||||
|
XSRCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am = "ODBC");
|
||||||
|
XSRCCOL(XSRCCOL *colp, PTDB tdbp); // Constructor used in copy process
|
||||||
|
|
||||||
|
// Implementation
|
||||||
|
//virtual int GetAmType(void) {return TYPE_AM_ODBC;}
|
||||||
|
|
||||||
|
// Methods
|
||||||
|
virtual void ReadColumn(PGLOBAL g);
|
||||||
|
virtual void WriteColumn(PGLOBAL g);
|
||||||
|
// void Print(PGLOBAL g, FILE *, uint);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// Members
|
||||||
|
char *Buffer; // To get returned message
|
||||||
|
int Flag; // Column content desc
|
||||||
|
}; // end of class XSRCCOL
|
||||||
|
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
/* This is the class declaration for the Data Sources catalog table. */
|
/* This is the class declaration for the Data Sources catalog table. */
|
||||||
/***********************************************************************/
|
/***********************************************************************/
|
||||||
|
Reference in New Issue
Block a user