diff options
Diffstat (limited to 'storage/connect/tabodbc.cpp')
-rw-r--r-- | storage/connect/tabodbc.cpp | 469 |
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. |