summaryrefslogtreecommitdiff
path: root/storage/connect/tabodbc.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'storage/connect/tabodbc.cpp')
-rw-r--r--storage/connect/tabodbc.cpp469
1 files changed, 28 insertions, 441 deletions
diff --git a/storage/connect/tabodbc.cpp b/storage/connect/tabodbc.cpp
index 488acdd330d..34711d584f1 100644
--- a/storage/connect/tabodbc.cpp
+++ b/storage/connect/tabodbc.cpp
@@ -1,11 +1,11 @@
/************* Tabodbc C++ Program Source Code File (.CPP) *************/
/* PROGRAM NAME: TABODBC */
/* ------------- */
-/* Version 3.1 */
+/* Version 3.2 */
/* */
/* COPYRIGHT: */
/* ---------- */
-/* (C) Copyright to the author Olivier BERTRAND 2000-2016 */
+/* (C) Copyright to the author Olivier BERTRAND 2000-2017 */
/* */
/* WHAT THIS PROGRAM DOES: */
/* ----------------------- */
@@ -116,47 +116,12 @@ bool ODBCDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
if (EXTDEF::DefineAM(g, am, poff))
return true;
- // Tabname = GetStringCatInfo(g, "Name",
- // (Catfunc & (FNC_TABLE | FNC_COL)) ? NULL : Name);
- // Tabname = GetStringCatInfo(g, "Tabname", Tabname);
- // Tabschema = GetStringCatInfo(g, "Dbname", NULL);
- // Tabschema = GetStringCatInfo(g, "Schema", Tabschema);
- // Tabcat = GetStringCatInfo(g, "Qualifier", NULL);
- // Tabcat = GetStringCatInfo(g, "Catalog", Tabcat);
- //Username = GetStringCatInfo(g, "User", NULL);
- // Password = GetStringCatInfo(g, "Password", NULL);
-
- // if ((Srcdef = GetStringCatInfo(g, "Srcdef", NULL)))
- // Read_Only = true;
-
- // Qrystr = GetStringCatInfo(g, "Query_String", "?");
- // Sep = GetStringCatInfo(g, "Separator", NULL);
Catver = GetIntCatInfo("Catver", 2);
- //Xsrc = GetBoolCatInfo("Execsrc", FALSE);
- //Maxerr = GetIntCatInfo("Maxerr", 0);
- //Maxres = GetIntCatInfo("Maxres", 0);
- //Quoted = GetIntCatInfo("Quoted", 0);
Options = ODBConn::noOdbcDialog;
//Options = ODBConn::noOdbcDialog | ODBConn::useCursorLib;
Cto= GetIntCatInfo("ConnectTimeout", DEFAULT_LOGIN_TIMEOUT);
Qto= GetIntCatInfo("QueryTimeout", DEFAULT_QUERY_TIMEOUT);
-
- //if ((Scrollable = GetBoolCatInfo("Scrollable", false)) && !Elemt)
- // Elemt = 1; // Cannot merge SQLFetch and SQLExtendedFetch
-
- //if (Catfunc == FNC_COL)
- // Colpat = GetStringCatInfo(g, "Colpat", NULL);
-
- //if (Catfunc == FNC_TABLE)
- // Tabtyp = GetStringCatInfo(g, "Tabtype", NULL);
-
UseCnc = GetBoolCatInfo("UseDSN", 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
@@ -210,59 +175,22 @@ TDBODBC::TDBODBC(PODEF tdp) : TDBEXT(tdp)
if (tdp) {
Connect = tdp->Connect;
- //TableName = tdp->Tabname;
- //Schema = tdp->Tabschema;
Ops.User = tdp->Username;
Ops.Pwd = tdp->Password;
- //Catalog = tdp->Tabcat;
- //Srcdef = tdp->Srcdef;
- //Qrystr = tdp->Qrystr;
- //Sep = tdp->GetSep();
- //Options = tdp->Options;
Ops.Cto = tdp->Cto;
Ops.Qto = tdp->Qto;
- //Quoted = MY_MAX(0, tdp->GetQuoted());
- //Rows = tdp->GetElemt();
Catver = tdp->Catver;
- //Memory = tdp->Memory;
- //Scrollable = tdp->Scrollable;
Ops.UseCnc = tdp->UseCnc;
} else {
Connect = NULL;
- //TableName = NULL;
- //Schema = NULL;
Ops.User = NULL;
Ops.Pwd = NULL;
- //Catalog = NULL;
- //Srcdef = NULL;
- //Qrystr = NULL;
- //Sep = 0;
- //Options = 0;
Ops.Cto = DEFAULT_LOGIN_TIMEOUT;
Ops.Qto = DEFAULT_QUERY_TIMEOUT;
- //Quoted = 0;
- //Rows = 0;
Catver = 0;
- //Memory = 0;
- //Scrollable = false;
Ops.UseCnc = false;
} // endif tdp
- //Quote = NULL;
- //Query = NULL;
- //Count = NULL;
-//Where = NULL;
- //MulConn = NULL;
- //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) : TDBEXT(tdbp)
@@ -270,32 +198,7 @@ TDBODBC::TDBODBC(PTDBODBC tdbp) : TDBEXT(tdbp)
Ocp = tdbp->Ocp; // is that right ?
Cnp = tdbp->Cnp;
Connect = tdbp->Connect;
- //TableName = tdbp->TableName;
- //Schema = tdbp->Schema;
Ops = tdbp->Ops;
- //Catalog = tdbp->Catalog;
- //Srcdef = tdbp->Srcdef;
- //Qrystr = tdbp->Qrystr;
- //Memory = tdbp->Memory;
- //Scrollable = tdbp->Scrollable;
- //Quote = tdbp->Quote;
- //Query = tdbp->Query;
- //Count = tdbp->Count;
-//Where = tdbp->Where;
- //MulConn = tdbp->MulConn;
- //DBQ = tdbp->DBQ;
- //Options = tdbp->Options;
- //Quoted = tdbp->Quoted;
- //Rows = tdbp->Rows;
- //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
@@ -328,7 +231,7 @@ PCOL TDBODBC::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
/* This used for Multiple(1) tables. Also prepare a connect string */
/* with a place holder to be used by SetFile. */
/***********************************************************************/
-PSZ TDBODBC::GetFile(PGLOBAL g)
+PCSZ TDBODBC::GetFile(PGLOBAL g)
{
if (Connect) {
char *p1, *p2;
@@ -389,152 +292,15 @@ void TDBODBC::SetFile(PGLOBAL g, PSZ fn)
DBQ = fn;
} // end of SetFile
-#if 0
-/******************************************************************/
-/* Convert an UTF-8 string to latin characters. */
-/******************************************************************/
-int TDBODBC::Decode(char *txt, char *buf, size_t n)
-{
- uint dummy_errors;
- uint32 len= copy_and_convert(buf, n, &my_charset_latin1,
- txt, strlen(txt),
- &my_charset_utf8_general_ci,
- &dummy_errors);
- buf[len]= '\0';
- return 0;
-} // end of Decode
-
-/***********************************************************************/
-/* MakeSQL: make the SQL statement use with ODBC connection. */
-/* Note: when implementing EOM filtering, column only used in local */
-/* filter should be removed from column list. */
-/***********************************************************************/
-bool TDBODBC::MakeSQL(PGLOBAL g, bool cnt)
- {
- char *schmp = NULL, *catp = NULL, buf[NAM_LEN * 3];
- int len;
- bool oom = false, first = true;
- PTABLE tablep = To_Table;
- PCOL colp;
-
- if (Srcdef) {
- if (strstr(Srcdef, "%s")) {
- char *fil;
-
- fil = (To_CondFil) ? To_CondFil->Body : PlugDup(g, "1=1");
- Query = new(g)STRING(g, strlen(Srcdef) + strlen(fil));
- Query->SetLength(sprintf(Query->GetStr(), Srcdef, fil));
- } else
- Query = new(g)STRING(g, 0, Srcdef);
-
- return false;
- } // endif Srcdef
-
- // Allocate the string used to contain the Query
- Query = new(g)STRING(g, 1023, "SELECT ");
-
- if (!cnt) {
- if (Columns) {
- // Normal SQL statement to retrieve results
- for (colp = Columns; colp; colp = colp->GetNext())
- if (!colp->IsSpecial()) {
- if (!first)
- oom |= Query->Append(", ");
- else
- first = false;
-
- // Column name can be encoded in UTF-8
- Decode(colp->GetName(), buf, sizeof(buf));
-
- if (Quote) {
- // Put column name between identifier quotes in case in contains blanks
- oom |= Query->Append(Quote);
- oom |= Query->Append(buf);
- oom |= Query->Append(Quote);
- } else
- oom |= Query->Append(buf);
-
- ((PEXTCOL)colp)->SetRank(++Ncol);
- } // endif colp
-
- } else
- // !Columns can occur for queries such that sql count(*) from...
- // for which we will count the rows from sql * from...
- oom |= Query->Append('*');
-
- } else
- // SQL statement used to retrieve the size of the result
- oom |= Query->Append("count(*)");
-
- oom |= Query->Append(" FROM ");
-
- if (Catalog && *Catalog)
- catp = Catalog;
-
- //if (tablep->GetSchema())
- // schmp = (char*)tablep->GetSchema();
- //else
- if (Schema && *Schema)
- schmp = Schema;
-
- if (catp) {
- oom |= Query->Append(catp);
-
- if (schmp) {
- oom |= Query->Append('.');
- oom |= Query->Append(schmp);
- } // endif schmp
-
- oom |= Query->Append('.');
- } else if (schmp) {
- oom |= Query->Append(schmp);
- oom |= Query->Append('.');
- } // endif schmp
-
- // Table name can be encoded in UTF-8
- Decode(TableName, buf, sizeof(buf));
-
- if (Quote) {
- // Put table name between identifier quotes in case in contains blanks
- oom |= Query->Append(Quote);
- oom |= Query->Append(buf);
- oom |= Query->Append(Quote);
- } else
- oom |= Query->Append(buf);
-
- len = Query->GetLength();
-
- if (To_CondFil) {
- if (Mode == MODE_READ) {
- oom |= Query->Append(" WHERE ");
- oom |= Query->Append(To_CondFil->Body);
- len = Query->GetLength() + 1;
- } else
- len += (strlen(To_CondFil->Body) + 256);
-
- } else
- len += ((Mode == MODE_READX) ? 256 : 1);
-
- if (oom || Query->Resize(len)) {
- strcpy(g->Message, "MakeSQL: Out of memory");
- return true;
- } // endif oom
-
- if (trace)
- htrc("Query=%s\n", Query->GetStr());
-
- return false;
- } // end of MakeSQL
-#endif // 0
-
/***********************************************************************/
/* MakeInsert: make the Insert statement used with ODBC connection. */
/***********************************************************************/
bool TDBODBC::MakeInsert(PGLOBAL g)
{
- char *schmp = NULL, *catp = NULL, buf[NAM_LEN * 3];
+ PCSZ schmp = NULL;
+ char *catp = NULL, buf[NAM_LEN * 3];
int len = 0;
- bool b = false, oom = false;
+ bool oom, b = false;
PTABLE tablep = To_Table;
PCOL colp;
@@ -571,32 +337,32 @@ bool TDBODBC::MakeInsert(PGLOBAL g)
Query = new(g) STRING(g, len, "INSERT INTO ");
if (catp) {
- oom |= Query->Append(catp);
+ Query->Append(catp);
if (schmp) {
- oom |= Query->Append('.');
- oom |= Query->Append(schmp);
+ Query->Append('.');
+ Query->Append(schmp);
} // endif schmp
- oom |= Query->Append('.');
+ Query->Append('.');
} else if (schmp) {
- oom |= Query->Append(schmp);
- oom |= Query->Append('.');
+ Query->Append(schmp);
+ Query->Append('.');
} // endif schmp
if (Quote) {
// Put table name between identifier quotes in case in contains blanks
- oom |= Query->Append(Quote);
- oom |= Query->Append(buf);
- oom |= Query->Append(Quote);
+ Query->Append(Quote);
+ Query->Append(buf);
+ Query->Append(Quote);
} else
- oom |= Query->Append(buf);
+ Query->Append(buf);
- oom |= Query->Append('(');
+ Query->Append('(');
for (colp = Columns; colp; colp = colp->GetNext()) {
if (b)
- oom |= Query->Append(", ");
+ Query->Append(", ");
else
b = true;
@@ -605,20 +371,20 @@ bool TDBODBC::MakeInsert(PGLOBAL g)
if (Quote) {
// Put column name between identifier quotes in case in contains blanks
- oom |= Query->Append(Quote);
- oom |= Query->Append(buf);
- oom |= Query->Append(Quote);
+ Query->Append(Quote);
+ Query->Append(buf);
+ Query->Append(Quote);
} else
- oom |= Query->Append(buf);
+ Query->Append(buf);
} // endfor colp
- oom |= Query->Append(") VALUES (");
+ Query->Append(") VALUES (");
for (int i = 0; i < Nparm; i++)
- oom |= Query->Append("?,");
+ Query->Append("?,");
- if (oom)
+ if ((oom = Query->IsTruncated()))
strcpy(g->Message, "MakeInsert: Out of memory");
else
Query->RepLast(')');
@@ -646,73 +412,6 @@ bool TDBODBC::BindParameters(PGLOBAL g)
#if 0
/***********************************************************************/
-/* MakeCommand: make the Update or Delete statement to send to the */
-/* MySQL server. Limited to remote values and filtering. */
-/***********************************************************************/
-bool TDBODBC::MakeCommand(PGLOBAL g)
- {
- char *p, *stmt, name[68], *body = NULL, *qc = Ocp->GetQuoteChar();
- char *qrystr = (char*)PlugSubAlloc(g, NULL, strlen(Qrystr) + 1);
- bool qtd = Quoted > 0;
- int i = 0, k = 0;
-
- // Make a lower case copy of the originale query and change
- // back ticks to the data source identifier quoting character
- do {
- qrystr[i] = (Qrystr[i] == '`') ? *qc : tolower(Qrystr[i]);
- } while (Qrystr[i++]);
-
- if (To_CondFil && (p = strstr(qrystr, " where "))) {
- p[7] = 0; // Remove where clause
- Qrystr[(p - qrystr) + 7] = 0;
- body = To_CondFil->Body;
- stmt = (char*)PlugSubAlloc(g, NULL, strlen(qrystr)
- + strlen(body) + 64);
- } else
- stmt = (char*)PlugSubAlloc(g, NULL, strlen(Qrystr) + 64);
-
- // Check whether the table name is equal to a keyword
- // If so, it must be quoted in the original query
- strlwr(strcat(strcat(strcpy(name, " "), Name), " "));
-
- if (strstr(" update delete low_priority ignore quick from ", name)) {
- strlwr(strcat(strcat(strcpy(name, qc), Name), qc));
- k += 2;
- } else
- strlwr(strcpy(name, Name)); // Not a keyword
-
- if ((p = strstr(qrystr, name))) {
- for (i = 0; i < p - qrystr; i++)
- stmt[i] = (Qrystr[i] == '`') ? *qc : Qrystr[i];
-
- stmt[i] = 0;
- k += i + (int)strlen(Name);
-
- if (qtd && *(p - 1) == ' ')
- strcat(strcat(strcat(stmt, qc), TableName), qc);
- else
- strcat(stmt, TableName);
-
- i = (int)strlen(stmt);
-
- do {
- stmt[i++] = (Qrystr[k] == '`') ? *qc : Qrystr[k];
- } while (Qrystr[k++]);
-
- if (body)
- strcat(stmt, body);
-
- } else {
- sprintf(g->Message, "Cannot use this %s command",
- (Mode == MODE_UPDATE) ? "UPDATE" : "DELETE");
- return true;
- } // endif p
-
- Query = new(g) STRING(g, 0, stmt);
- return (!Query->GetSize());
- } // end of MakeCommand
-
-/***********************************************************************/
/* MakeUpdate: make the SQL statement to send to ODBC connection. */
/***********************************************************************/
char *TDBODBC::MakeUpdate(PGLOBAL g)
@@ -829,35 +528,6 @@ int TDBODBC::Cardinality(PGLOBAL g)
return Cardinal;
} // end of Cardinality
-#if 0
-/***********************************************************************/
-/* ODBC GetMaxSize: returns table size estimate in number of lines. */
-/***********************************************************************/
-int TDBODBC::GetMaxSize(PGLOBAL g)
- {
- if (MaxSize < 0) {
- if (Mode == MODE_DELETE)
- // Return 0 in mode DELETE in case of delete all.
- MaxSize = 0;
- else if (!Cardinality(NULL))
- MaxSize = 10; // To make MySQL happy
- else if ((MaxSize = Cardinality(g)) < 0)
- MaxSize = 12; // So we can see an error occurred
-
- } // endif MaxSize
-
- return MaxSize;
- } // end of GetMaxSize
-
-/***********************************************************************/
-/* Return max size value. */
-/***********************************************************************/
-int TDBODBC::GetProgMax(PGLOBAL g)
- {
- return GetMaxSize(g);
- } // end of GetProgMax
-#endif // 0
-
/***********************************************************************/
/* ODBC Access Method opening routine. */
/* New method now that this routine is called recursively (last table */
@@ -1064,7 +734,7 @@ bool TDBODBC::ReadKey(PGLOBAL g, OPVAL op, const key_range *kr)
To_CondFil->Body= (char*)PlugSubAlloc(g, NULL, 0);
*To_CondFil->Body= 0;
- if ((To_CondFil = hc->CheckCond(g, To_CondFil, To_CondFil->Cond)))
+ if ((To_CondFil = hc->CheckCond(g, To_CondFil, Cond)))
PlugSubAlloc(g, NULL, strlen(To_CondFil->Body) + 1);
} // endif active_index
@@ -1097,8 +767,6 @@ int TDBODBC::ReadDB(PGLOBAL g)
if (trace > 1)
htrc("ODBC ReadDB: R%d Mode=%d\n", GetTdb_No(), Mode);
- //htrc("ODBC ReadDB: R%d Mode=%d key=%p link=%p Kindex=%p\n",
- // GetTdb_No(), Mode, To_Key_Col, To_Link, To_Kindex);
if (Mode == MODE_UPDATE || Mode == MODE_DELETE) {
if (!Query && MakeCommand(g))
@@ -1118,12 +786,6 @@ int TDBODBC::ReadDB(PGLOBAL g)
} // endif Mode
- //if (To_Kindex) {
- // // Direct access of ODBC tables is not implemented yet
- // strcpy(g->Message, MSG(NO_ODBC_DIRECT));
- // return RC_FX;
- // } // endif To_Kindex
-
/*********************************************************************/
/* Now start the reading process. */
/* Here is the place to fetch the line(s). */
@@ -1208,11 +870,6 @@ int TDBODBC::DeleteDB(PGLOBAL g, int irc)
/***********************************************************************/
void TDBODBC::CloseDB(PGLOBAL g)
{
-//if (To_Kindex) {
-// To_Kindex->Close();
-// To_Kindex = NULL;
-// } // endif
-
if (Ocp)
Ocp->Close();
@@ -1227,20 +884,13 @@ void TDBODBC::CloseDB(PGLOBAL g)
/***********************************************************************/
/* ODBCCOL public constructor. */
/***********************************************************************/
-ODBCCOL::ODBCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am)
+ODBCCOL::ODBCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am)
: EXTCOL(cdp, tdbp, cprec, i, am)
{
// Set additional ODBC access method information for column.
-//Crp = NULL;
-//Long = Precision;
-//strcpy(F_Date, cdp->F_Date);
-//To_Val = NULL;
Slen = 0;
StrLen = &Slen;
Sqlbuf = NULL;
-//Bufp = NULL;
-//Blkp = NULL;
-//Rank = 0; // Not known yet
} // end of ODBCCOL constructor
/***********************************************************************/
@@ -1248,17 +898,9 @@ ODBCCOL::ODBCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am)
/***********************************************************************/
ODBCCOL::ODBCCOL(void) : EXTCOL()
{
-//Crp = NULL;
-//Buf_Type = TYPE_INT; // This is a count(*) column
-//// Set additional Dos access method information for column.
-//Long = sizeof(int);
-//To_Val = NULL;
Slen = 0;
StrLen = &Slen;
Sqlbuf = NULL;
-//Bufp = NULL;
-//Blkp = NULL;
-//Rank = 1;
} // end of ODBCCOL constructor
/***********************************************************************/
@@ -1267,66 +909,11 @@ ODBCCOL::ODBCCOL(void) : EXTCOL()
/***********************************************************************/
ODBCCOL::ODBCCOL(ODBCCOL *col1, PTDB tdbp) : EXTCOL(col1, tdbp)
{
-//Crp = col1->Crp;
-//Long = col1->Long;
-//strcpy(F_Date, col1->F_Date);
-//To_Val = col1->To_Val;
Slen = col1->Slen;
StrLen = col1->StrLen;
Sqlbuf = col1->Sqlbuf;
-//Bufp = col1->Bufp;
-//Blkp = col1->Blkp;
-//Rank = col1->Rank;
} // end of ODBCCOL copy constructor
-#if 0
-/***********************************************************************/
-/* SetBuffer: prepare a column block for write operation. */
-/***********************************************************************/
-bool ODBCCOL::SetBuffer(PGLOBAL g, PVAL value, bool ok, bool check)
- {
- if (!(To_Val = value)) {
- sprintf(g->Message, MSG(VALUE_ERROR), Name);
- return true;
- } else if (Buf_Type == value->GetType()) {
- // Values are of the (good) column type
- if (Buf_Type == TYPE_DATE) {
- // If any of the date values is formatted
- // output format must be set for the receiving table
- if (GetDomain() || ((DTVAL *)value)->IsFormatted())
- goto newval; // This will make a new value;
-
- } else if (Buf_Type == TYPE_DOUBLE)
- // Float values must be written with the correct (column) precision
- // Note: maybe this should be forced by ShowValue instead of this ?
- value->SetPrec(GetScale());
-
- Value = value; // Directly access the external value
- } else {
- // Values are not of the (good) column type
- if (check) {
- sprintf(g->Message, MSG(TYPE_VALUE_ERR), Name,
- GetTypeName(Buf_Type), GetTypeName(value->GetType()));
- return true;
- } // endif check
-
- newval:
- if (InitValue(g)) // Allocate the matching value block
- return true;
-
- } // endif's Value, Buf_Type
-
- // Because Colblk's have been made from a copy of the original TDB in
- // case of Update, we must reset them to point to the original one.
- if (To_Tdb->GetOrig())
- To_Tdb = (PTDB)To_Tdb->GetOrig();
-
- // Set the Column
- Status = (ok) ? BUF_EMPTY : BUF_NO;
- return false;
- } // end of SetBuffer
-#endif // 0
-
/***********************************************************************/
/* ReadColumn: when SQLFetch is used there is nothing to do as the */
/* column buffer was bind to the record set. This is also the case */
@@ -1715,7 +1302,7 @@ int TDBXDBC::DeleteDB(PGLOBAL g, int irc)
/***********************************************************************/
/* XSRCCOL public constructor. */
/***********************************************************************/
-XSRCCOL::XSRCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am)
+XSRCCOL::XSRCCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PCSZ am)
: ODBCCOL(cdp, tdbp, cprec, i, am)
{
// Set additional ODBC access method information for column.