summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOlivier Bertrand <bertrandop@gmail.com>2015-02-08 18:17:29 +0100
committerOlivier Bertrand <bertrandop@gmail.com>2015-02-08 18:17:29 +0100
commit96ba1f1473ef2ff52e88728e481a29d821485ab1 (patch)
tree8ae3ec634116d51833f9005c600bcaaae84c126b
parent35548d577c77c1bb7cecbadafb9a8519cc0f3710 (diff)
downloadmariadb-git-96ba1f1473ef2ff52e88728e481a29d821485ab1.tar.gz
- Handle the use of date/time values when making queries for MYSQL or
ODBC. Was raised by 7549. modified: storage/connect/ha_connect.cc storage/connect/odbconn.cpp storage/connect/tabodbc.cpp
-rw-r--r--storage/connect/ha_connect.cc73
-rw-r--r--storage/connect/odbconn.cpp2
-rw-r--r--storage/connect/tabodbc.cpp31
3 files changed, 92 insertions, 14 deletions
diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc
index 5879203e163..44c91c5c6d1 100644
--- a/storage/connect/ha_connect.cc
+++ b/storage/connect/ha_connect.cc
@@ -2519,6 +2519,8 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, AMT tty, Item *cond)
char *body= filp->Body;
unsigned int i;
bool ismul= false, x= (tty == TYPE_AM_MYX || tty == TYPE_AM_XDBC);
+ bool nonul= (tty == TYPE_AM_ODBC && (tdbp->GetMode() == MODE_INSERT ||
+ tdbp->GetMode() == MODE_DELETE));
OPVAL vop= OP_XX;
if (!cond)
@@ -2536,7 +2538,7 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, AMT tty, Item *cond)
if (trace)
htrc("Cond: Ftype=%d name=%s\n", cond_item->functype(),
- cond_item->func_name());
+ cond_item->func_name());
switch (cond_item->functype()) {
case Item_func::COND_AND_FUNC: vop= OP_AND; break;
@@ -2555,7 +2557,7 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, AMT tty, Item *cond)
for (i= 0; i < arglist->elements; i++)
if ((subitem= li++)) {
if (!CheckCond(g, filp, tty, subitem)) {
- if (vop == OP_OR)
+ if (vop == OP_OR || nonul)
return NULL;
else
*p2= 0;
@@ -2651,6 +2653,8 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, AMT tty, Item *cond)
if (trace) {
htrc("Field index=%d\n", pField->field->field_index);
htrc("Field name=%s\n", pField->field->field_name);
+ htrc("Field type=%d\n", pField->field->type());
+ htrc("Field_type=%d\n", args[i]->field_type());
} // endif trace
// IN and BETWEEN clauses should be col VOP list
@@ -2670,8 +2674,9 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, AMT tty, Item *cond)
char buff[256];
String *res, tmp(buff, sizeof(buff), &my_charset_bin);
Item_basic_constant *pval= (Item_basic_constant *)args[i];
+ Item::Type type= args[i]->real_type();
- switch (args[i]->real_type()) {
+ switch (type) {
case COND::STRING_ITEM:
case COND::INT_ITEM:
case COND::REAL_ITEM:
@@ -2696,10 +2701,64 @@ PCFIL ha_connect::CheckCond(PGLOBAL g, PCFIL filp, AMT tty, Item *cond)
if (!x) {
// Append the value to the filter
- if (args[i]->field_type() == MYSQL_TYPE_VARCHAR)
- strcat(strncat(strcat(body, "'"), res->ptr(), res->length()), "'");
- else
- strncat(body, res->ptr(), res->length());
+ switch (args[i]->field_type()) {
+ case MYSQL_TYPE_TIMESTAMP:
+ case MYSQL_TYPE_DATETIME:
+ if (tty == TYPE_AM_ODBC) {
+ strcat(body, "{ts '");
+ strcat(strncat(body, res->ptr(), res->length()), "'}");
+ break;
+ } // endif ODBC
+
+ case MYSQL_TYPE_DATE:
+ if (tty == TYPE_AM_ODBC) {
+ strcat(body, "{d '");
+ strcat(strncat(body, res->ptr(), res->length()), "'}");
+ break;
+ } // endif ODBC
+
+ case MYSQL_TYPE_TIME:
+ if (tty == TYPE_AM_ODBC) {
+ strcat(body, "{t '");
+ strcat(strncat(body, res->ptr(), res->length()), "'}");
+ break;
+ } // endif ODBC
+
+ case MYSQL_TYPE_VARCHAR:
+ if (tty == TYPE_AM_ODBC && i) {
+ switch (args[0]->field_type()) {
+ case MYSQL_TYPE_TIMESTAMP:
+ case MYSQL_TYPE_DATETIME:
+ strcat(body, "{ts '");
+ strncat(body, res->ptr(), res->length());
+ strcat(body, "'}");
+ break;
+ case MYSQL_TYPE_DATE:
+ strcat(body, "{d '");
+ strncat(body, res->ptr(), res->length());
+ strcat(body, "'}");
+ break;
+ case MYSQL_TYPE_TIME:
+ strcat(body, "{t '");
+ strncat(body, res->ptr(), res->length());
+ strcat(body, "'}");
+ break;
+ default:
+ strcat(body, "'");
+ strncat(body, res->ptr(), res->length());
+ strcat(body, "'");
+ } // endswitch field type
+
+ } else {
+ strcat(body, "'");
+ strncat(body, res->ptr(), res->length());
+ strcat(body, "'");
+ } // endif tty
+
+ break;
+ default:
+ strncat(body, res->ptr(), res->length());
+ } // endswitch field type
} else {
if (args[i]->field_type() == MYSQL_TYPE_VARCHAR) {
diff --git a/storage/connect/odbconn.cpp b/storage/connect/odbconn.cpp
index 59cd2b0d157..fec14820ef6 100644
--- a/storage/connect/odbconn.cpp
+++ b/storage/connect/odbconn.cpp
@@ -1740,6 +1740,8 @@ bool ODBConn::BindParam(ODBCCOL *colp)
strcpy(m_G->Message, x->GetErrorMessage(0));
colsize = colp->GetPrecision();
sqlt = GetSQLType(buftype);
+ dec = IsTypeChar(buftype) ? 0 : colp->GetScale();
+ nul = SQL_NULLABLE_UNKNOWN;
} // end try/catch
buf = colp->GetBuffer(0);
diff --git a/storage/connect/tabodbc.cpp b/storage/connect/tabodbc.cpp
index 9e56a6f4b43..cb18870bc55 100644
--- a/storage/connect/tabodbc.cpp
+++ b/storage/connect/tabodbc.cpp
@@ -573,8 +573,7 @@ bool TDBODBC::BindParameters(PGLOBAL g)
/***********************************************************************/
char *TDBODBC::MakeCommand(PGLOBAL g)
{
- char *p, name[68], *qc = Ocp->GetQuoteChar();
- char *stmt = (char*)PlugSubAlloc(g, NULL, strlen(Qrystr) + 64);
+ 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;
@@ -585,6 +584,15 @@ char *TDBODBC::MakeCommand(PGLOBAL g)
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), " "));
@@ -612,6 +620,9 @@ char *TDBODBC::MakeCommand(PGLOBAL g)
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");
@@ -774,7 +785,7 @@ int TDBODBC::GetProgMax(PGLOBAL g)
/***********************************************************************/
bool TDBODBC::OpenDB(PGLOBAL g)
{
- bool rc = false;
+ bool rc = true;
if (g->Trace)
htrc("ODBC OpenDB: tdbp=%p tdb=R%d use=%dmode=%d\n",
@@ -849,12 +860,12 @@ bool TDBODBC::OpenDB(PGLOBAL g)
} // endif Query
- } else if (Mode == MODE_UPDATE || Mode == MODE_DELETE)
- Query = MakeCommand(g);
- else
+ } else if (Mode == MODE_UPDATE || Mode == MODE_DELETE) {
+ rc = false; // wait for CheckCond before calling MakeCommand(g);
+ } else
sprintf(g->Message, "Invalid mode %d", Mode);
- if (!Query || rc) {
+ if (rc) {
Ocp->Close();
return true;
} // endif rc
@@ -886,6 +897,9 @@ int TDBODBC::ReadDB(PGLOBAL g)
GetTdb_No(), Mode, To_Key_Col, To_Link, To_Kindex);
if (Mode == MODE_UPDATE || Mode == MODE_DELETE) {
+ if (!Query && !(Query = MakeCommand(g)))
+ return RC_FX;
+
// Send the UPDATE/DELETE command to the remote table
if (!Ocp->ExecSQLcommand(Query)) {
sprintf(g->Message, "%s: %d affected rows", TableName, AftRows);
@@ -955,6 +969,9 @@ int TDBODBC::WriteDB(PGLOBAL g)
int TDBODBC::DeleteDB(PGLOBAL g, int irc)
{
if (irc == RC_FX) {
+ if (!Query && !(Query = MakeCommand(g)))
+ return RC_FX;
+
// Send the DELETE (all) command to the remote table
if (!Ocp->ExecSQLcommand(Query)) {
sprintf(g->Message, "%s: %d affected rows", TableName, AftRows);