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

1) Handling string memory allocation with a new STRING class. This is only

the beginning. Defining the STRING class and begining to use it (MYSQL)

2) Change the xtrace, use_tempfile and exact_info connect variables from
   GLOBAL to SESSION. Remaining GLOBAL variables have been made readonly.

3) Take care of LEX_STRING variables. The .str should not be regarded as
   allways being 0 terminated. This is handled by the Strz functions that
   make sure to return 0 terminated strings.

Bug fix:
- When inserting in MYSQL table with special column(s) a query such as:
insert into t2 values(0,4,'new04'),(0,5,'new05');
failed saying: column id (the special column) not found in t2.
It is now accepted but must be counted in values (these 0 are ignored)
- ROWID was returning row numbers based 0. Now it is from base 1.

modified:
  storage/connect/array.cpp
  storage/connect/blkfil.cpp
  storage/connect/colblk.cpp
  storage/connect/connect.cc
  storage/connect/filamap.cpp
  storage/connect/filamdbf.cpp
  storage/connect/filamfix.cpp
  storage/connect/filamtxt.cpp
  storage/connect/filamvct.cpp
  storage/connect/filamzip.cpp
  storage/connect/filamzip.h
  storage/connect/filter.cpp
  storage/connect/global.h
  storage/connect/ha_connect.cc
  storage/connect/ha_connect.h
  storage/connect/libdoc.cpp
  storage/connect/mycat.cc
  storage/connect/myconn.cpp
  storage/connect/odbconn.cpp
  storage/connect/plgdbutl.cpp
  storage/connect/plugutil.c
  storage/connect/reldef.cpp
  storage/connect/tabcol.cpp
  storage/connect/tabdos.cpp
  storage/connect/tabfix.cpp
  storage/connect/tabfmt.cpp
  storage/connect/table.cpp
  storage/connect/tabmul.cpp
  storage/connect/tabmysql.cpp
  storage/connect/tabmysql.h
  storage/connect/taboccur.cpp
  storage/connect/tabodbc.cpp
  storage/connect/tabpivot.cpp
  storage/connect/tabsys.cpp
  storage/connect/tabtbl.cpp
  storage/connect/tabutil.cpp
  storage/connect/tabvct.cpp
  storage/connect/tabwmi.cpp
  storage/connect/tabwmi.h
  storage/connect/tabxcl.cpp
  storage/connect/tabxml.cpp
  storage/connect/user_connect.cc
  storage/connect/valblk.cpp
  storage/connect/value.cpp
  storage/connect/value.h
  storage/connect/xindex.cpp
  storage/connect/xobject.cpp
  storage/connect/xobject.h
  storage/connect/xtable.h
This commit is contained in:
Olivier Bertrand
2014-10-21 17:29:51 +02:00
parent c65a9fb4c6
commit 56e2771321
49 changed files with 1354 additions and 1235 deletions

View File

@@ -67,13 +67,15 @@
void PrintResult(PGLOBAL, PSEM, PQRYRES);
#endif // _CONSOLE
extern "C" int trace;
extern bool xinfo;
// Used to check whether a MYSQL table is created on itself
bool CheckSelf(PGLOBAL g, TABLE_SHARE *s, const char *host,
const char *db, char *tab, const char *src, int port);
/***********************************************************************/
/* External function. */
/***********************************************************************/
bool ExactInfo(void);
/* -------------- Implementation of the MYSQLDEF class --------------- */
/***********************************************************************/
@@ -430,7 +432,6 @@ TDBMYSQL::TDBMYSQL(PMYDEF tdp) : TDBASE(tdp)
Bind = NULL;
Query = NULL;
Qbuf = NULL;
Fetched = false;
m_Rc = RC_FX;
AftRows = 0;
@@ -454,7 +455,6 @@ TDBMYSQL::TDBMYSQL(PGLOBAL g, PTDBMY tdbp) : TDBASE(tdbp)
Delayed = tdbp->Delayed;
Bind = NULL;
Query = tdbp->Query;
Qbuf = NULL;
Fetched = tdbp->Fetched;
m_Rc = tdbp->m_Rc;
AftRows = tdbp->AftRows;
@@ -495,9 +495,10 @@ PCOL TDBMYSQL::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
/***********************************************************************/
bool TDBMYSQL::MakeSelect(PGLOBAL g, bool mx)
{
char *tk = "`";
//char *tk = "`";
char tk = '`';
int len = 0, rank = 0;
bool b = false;
bool b = false, oom = false;
PCOL colp;
//PDBUSER dup = PlgGetUser(g);
@@ -505,27 +506,24 @@ bool TDBMYSQL::MakeSelect(PGLOBAL g, bool mx)
return false; // already done
if (Srcdef) {
Query = Srcdef;
Query = new(g)STRING(g, 0, Srcdef);
return false;
} // endif Srcdef
//Find the address of the suballocated query
Query = (char*)PlugSubAlloc(g, NULL, 0);
strcpy(Query, "SELECT ");
// Allocate the string used to contain Query
Query = new(g) STRING(g, 1023, "SELECT ");
if (Columns) {
for (colp = Columns; colp; colp = colp->GetNext())
if (!colp->IsSpecial()) {
// if (colp->IsSpecial()) {
// strcpy(g->Message, MSG(NO_SPEC_COL));
// return true;
// } else {
if (b)
strcat(Query, ", ");
oom |= Query->Append(", ");
else
b = true;
strcat(strcat(strcat(Query, tk), colp->GetName()), tk);
oom |= Query->Append(tk);
oom |= Query->Append(colp->GetName());
oom |= Query->Append(tk);
((PMYCOL)colp)->Rank = rank++;
} // endif colp
@@ -534,27 +532,38 @@ bool TDBMYSQL::MakeSelect(PGLOBAL g, bool mx)
// Query count(*) from... for which we will count the rows from
// Query '*' from...
// (the use of a char constant minimize the result storage)
strcat(Query, (Isview) ? "*" : "'*'");
if (Isview)
oom |= Query->Append('*');
else
oom |= Query->Append("'*'");
} // endif ncol
strcat(strcat(strcat(strcat(Query, " FROM "), tk), Tabname), tk);
len = strlen(Query);
oom |= Query->Append(" FROM ");
oom |= Query->Append(tk);
oom |= Query->Append(Tabname);
oom |= Query->Append(tk);
len = Query->GetLength();
if (To_CondFil) {
if (!mx) {
strcat(strcat(Query, " WHERE "), To_CondFil->Body);
len = strlen(Query) + 1;
oom |= Query->Append(" WHERE ");
oom |= Query->Append(To_CondFil->Body);
len = Query->GetLength() + 1;
} else
len += (strlen(To_CondFil->Body) + 256);
} else
len += (mx ? 256 : 1);
if (trace)
htrc("Query=%s\n", Query);
if (oom || Query->Resize(len)) {
strcpy(g->Message, "MakeSelect: Out of memory");
return true;
} // endif oom
if (trace)
htrc("Query=%s\n", Query->GetStr());
// Now we know how much to suballocate
PlugSubAlloc(g, NULL, len);
return false;
} // end of MakeSelect
@@ -563,81 +572,82 @@ bool TDBMYSQL::MakeSelect(PGLOBAL g, bool mx)
/***********************************************************************/
bool TDBMYSQL::MakeInsert(PGLOBAL g)
{
char *colist, *valist = NULL;
char *tk = "`";
int len = 0, qlen = 0;
bool b = false;
uint len = 0;
bool b = false, oom;
PCOL colp;
if (Query)
return false; // already done
for (colp = Columns; colp; colp = colp->GetNext())
if (!colp->IsSpecial()) {
// if (colp->IsSpecial()) {
// strcpy(g->Message, MSG(NO_SPEC_COL));
// return true;
// } else {
len += (strlen(colp->GetName()) + 4);
((PMYCOL)colp)->Rank = Nparm++;
} // endif colp
colist = (char*)PlugSubAlloc(g, NULL, len);
*colist = '\0';
if (Prep) {
#if defined(MYSQL_PREPARED_STATEMENTS)
valist = (char*)PlugSubAlloc(g, NULL, 2 * Nparm);
*valist = '\0';
#else // !MYSQL_PREPARED_STATEMENTS
#if !defined(MYSQL_PREPARED_STATEMENTS)
strcpy(g->Message, "Prepared statements not used (not supported)");
PushWarning(g, this);
Prep = false;
#endif // !MYSQL_PREPARED_STATEMENTS
} // endif Prep
for (colp = Columns; colp; colp = colp->GetNext()) {
if (b) {
strcat(colist, ", ");
if (Prep) strcat(valist, ",");
} else
b = true;
for (colp = Columns; colp; colp = colp->GetNext())
if (colp->IsSpecial()) {
strcpy(g->Message, MSG(NO_SPEC_COL));
return true;
} else {
len += (strlen(colp->GetName()) + 4);
strcat(strcat(strcat(colist, tk), colp->GetName()), tk);
// Parameter marker
if (!Prep) {
if (colp->GetResultType() == TYPE_DATE)
len += 20;
else
len += colp->GetLength();
} else
len += 2;
// Parameter marker
if (!Prep) {
if (colp->GetResultType() == TYPE_DATE)
qlen += 20;
else
qlen += colp->GetLength();
} else // Prep
strcat(valist, "?");
} // endfor colp
((PMYCOL)colp)->Rank = Nparm++;
} // endif colp
// Below 40 is enough to contain the fixed part of the query
len = (strlen(Tabname) + strlen(colist)
+ ((Prep) ? strlen(valist) : 0) + 40);
Query = (char*)PlugSubAlloc(g, NULL, len);
len += (strlen(Tabname) + 40);
Query = new(g) STRING(g, len);
if (Delayed)
strcpy(Query, "INSERT DELAYED INTO ");
oom = Query->Set("INSERT DELAYED INTO ");
else
strcpy(Query, "INSERT INTO ");
oom = Query->Set("INSERT INTO ");
strcat(strcat(strcat(Query, tk), Tabname), tk);
strcat(strcat(strcat(Query, " ("), colist), ") VALUES (");
oom |= Query->Append(tk);
oom |= Query->Append(Tabname);
oom |= Query->Append("` (");
if (Prep)
strcat(strcat(Query, valist), ")");
else {
qlen += (strlen(Query) + Nparm);
Qbuf = (char *)PlugSubAlloc(g, NULL, qlen);
} // endelse Prep
for (colp = Columns; colp; colp = colp->GetNext()) {
if (b)
oom |= Query->Append(", ");
else
b = true;
oom |= Query->Append(tk);
oom |= Query->Append(colp->GetName());
oom |= Query->Append(tk);
} // endfor colp
return false;
oom |= Query->Append(") VALUES (");
#if defined(MYSQL_PREPARED_STATEMENTS)
if (Prep) {
for (int i = 0; i < Nparm; i++)
oom |= Query->Append("?,");
Query->RepLast(')');
Query->Trim();
} // endif Prep
#endif // MYSQL_PREPARED_STATEMENTS
if (oom)
strcpy(g->Message, "MakeInsert: Out of memory");
return oom;
} // end of MakeInsert
/***********************************************************************/
@@ -646,7 +656,7 @@ bool TDBMYSQL::MakeInsert(PGLOBAL g)
/***********************************************************************/
int TDBMYSQL::MakeCommand(PGLOBAL g)
{
Query = (char*)PlugSubAlloc(g, NULL, strlen(Qrystr) + 64);
Query = new(g) STRING(g, strlen(Qrystr) + 64);
if (Quoted > 0 || stricmp(Name, Tabname)) {
char *p, *qrystr, name[68];
@@ -665,16 +675,23 @@ int TDBMYSQL::MakeCommand(PGLOBAL g)
strlwr(strcpy(name, Name)); // Not a keyword
if ((p = strstr(qrystr, name))) {
memcpy(Query, Qrystr, p - qrystr);
Query[p - qrystr] = 0;
bool oom = Query->Set(Qrystr, p - qrystr);
if (qtd && *(p-1) == ' ')
strcat(strcat(strcat(Query, "`"), Tabname), "`");
else
strcat(Query, Tabname);
if (qtd && *(p-1) == ' ') {
oom |= Query->Append('`');
oom |= Query->Append(Tabname);
oom |= Query->Append('`');
} else
oom |= Query->Append(Tabname);
oom |= Query->Append(Qrystr + (p - qrystr) + strlen(name));
if (oom) {
strcpy(g->Message, "MakeCommand: Out of memory");
return RC_FX;
} else
strlwr(strcpy(qrystr, Query->GetStr()));
strcat(Query, Qrystr + (p - qrystr) + strlen(name));
strlwr(strcpy(qrystr, Query));
} else {
sprintf(g->Message, "Cannot use this %s command",
(Mode == MODE_UPDATE) ? "UPDATE" : "DELETE");
@@ -682,7 +699,7 @@ int TDBMYSQL::MakeCommand(PGLOBAL g)
} // endif p
} else
strcpy(Query, Qrystr);
(void)Query->Set(Qrystr);
return RC_OK;
} // end of MakeCommand
@@ -755,7 +772,7 @@ int TDBMYSQL::Cardinality(PGLOBAL g)
if (!g)
return (Mode == MODE_ANY && !Srcdef) ? 1 : 0;
if (Cardinal < 0 && Mode == MODE_ANY && !Srcdef && xinfo) {
if (Cardinal < 0 && Mode == MODE_ANY && !Srcdef && ExactInfo()) {
// Info command, we must return the exact table row number
char query[96];
MYSQLC myc;
@@ -802,7 +819,7 @@ int TDBMYSQL::GetMaxSize(PGLOBAL g)
/***********************************************************************/
int TDBMYSQL::RowNumber(PGLOBAL g, bool b)
{
return N;
return N + 1;
} // end of RowNumber
/***********************************************************************/
@@ -871,7 +888,8 @@ bool TDBMYSQL::OpenDB(PGLOBAL g)
/*********************************************************************/
if (Mode == MODE_READ || Mode == MODE_READX) {
MakeSelect(g, Mode == MODE_READX);
m_Rc = (Mode == MODE_READ) ? Myc.ExecSQL(g, Query) : RC_OK;
m_Rc = (Mode == MODE_READ)
? Myc.ExecSQL(g, Query->GetStr()) : RC_OK;
#if 0
if (!Myc.m_Res || !Myc.m_Fields) {
@@ -894,7 +912,8 @@ bool TDBMYSQL::OpenDB(PGLOBAL g)
if (!MakeInsert(g)) {
#if defined(MYSQL_PREPARED_STATEMENTS)
int n = (Prep) ? Myc.PrepareSQL(g, Query) : Nparm;
int n = (Prep)
? Myc.PrepareSQL(g, Query->GetCharValue()) : Nparm;
if (Nparm != n) {
if (n >= 0) // Other errors return negative values
@@ -1007,7 +1026,7 @@ int TDBMYSQL::SendCommand(PGLOBAL g)
{
int w;
if (Myc.ExecSQLcmd(g, Query, &w) == RC_NF) {
if (Myc.ExecSQLcmd(g, Query->GetStr(), &w) == RC_NF) {
AftRows = Myc.m_Afrw;
sprintf(g->Message, "%s: %d affected rows", Tabname, AftRows);
PushWarning(g, this, 0); // 0 means a Note
@@ -1037,28 +1056,45 @@ int TDBMYSQL::SendCommand(PGLOBAL g)
/***********************************************************************/
bool TDBMYSQL::ReadKey(PGLOBAL g, OPVAL op, const void *key, int len)
{
int oldlen = strlen(Query);
bool oom;
int oldlen = Query->GetLength();
if (!key || op == OP_NEXT ||
Mode == MODE_UPDATE || Mode == MODE_DELETE)
return false;
else if (op == OP_FIRST) {
if (To_CondFil)
strcat(strcat(Query, " WHERE "), To_CondFil->Body);
if (To_CondFil) {
oom = Query->Append(" WHERE ");
if ((oom |= Query->Append(To_CondFil->Body))) {
strcpy(g->Message, "Readkey: Out of memory");
return true;
} // endif oom
} // endif To_Condfil
} else {
if (Myc.m_Res)
Myc.FreeResult();
To_Def->GetHandler()->MakeKeyWhere(g, Query, op, "`", key, len);
To_Def->GetHandler()->MakeKeyWhere(g, Query->GetStr(),
op, "`", key, len);
if (To_CondFil)
strcat(strcat(strcat(Query, " AND ("), To_CondFil->Body), ")");
if (To_CondFil) {
oom = Query->Append(" AND (");
oom |= Query->Append(To_CondFil->Body);
if ((oom |= Query->Append(')'))) {
strcpy(g->Message, "Readkey: Out of memory");
return true;
} // endif oom
} // endif To_Condfil
} // endif's op
m_Rc = Myc.ExecSQL(g, Query);
Query[oldlen] = 0;
m_Rc = Myc.ExecSQL(g, Query->GetStr());
Query->Truncate(oldlen);
return (m_Rc == RC_FX) ? true : false;
} // end of ReadKey
@@ -1102,31 +1138,38 @@ int TDBMYSQL::WriteDB(PGLOBAL g)
// Statement was not prepared, we must construct and execute
// an insert query for each line to insert
int rc;
uint len = Query->GetLength();
char buf[64];
strcpy(Qbuf, Query);
bool b, oom = false;
// Make the Insert command value list
for (PCOL colp = Columns; colp; colp = colp->GetNext()) {
if (!colp->GetValue()->IsNull()) {
if (colp->GetResultType() == TYPE_STRING ||
colp->GetResultType() == TYPE_DATE)
strcat(Qbuf, "'");
strcat(Qbuf, colp->GetValue()->GetCharString(buf));
if (colp->GetResultType() == TYPE_STRING ||
colp->GetResultType() == TYPE_DATE)
strcat(Qbuf, "'");
if ((b = colp->GetResultType() == TYPE_STRING ||
colp->GetResultType() == TYPE_DATE))
oom |= Query->Append('\'');
oom |= Query->Append(colp->GetValue()->GetCharString(buf));
if (b)
oom |= Query->Append('\'');
} else
strcat(Qbuf, "NULL");
strcat(Qbuf, (colp->GetNext()) ? "," : ")");
oom |= Query->Append("NULL");
oom |= Query->Append(',');
} // endfor colp
Myc.m_Rows = -1; // To execute the query
rc = Myc.ExecSQL(g, Qbuf);
if (unlikely(oom)) {
strcpy(g->Message, "WriteDB: Out of memory");
rc = RC_FX;
} else {
Query->RepLast(')');
Myc.m_Rows = -1; // To execute the query
rc = Myc.ExecSQL(g, Query->GetStr());
Query->Truncate(len); // Restore query
} // endif oom
return (rc == RC_NF) ? RC_OK : rc; // RC_NF is Ok
} // end of WriteDB
@@ -1531,7 +1574,7 @@ bool TDBMYEXC::OpenDB(PGLOBAL g)
if (!(Cmdlist = MakeCMD(g))) {
Myc.Close();
return true;
} // endif Query
} // endif Cmdlist
return false;
} // end of OpenDB
@@ -1559,9 +1602,12 @@ int TDBMYEXC::ReadDB(PGLOBAL g)
int rc;
do {
Query = Cmdlist->Cmd;
if (Query)
Query->Set(Cmdlist->Cmd);
else
Query = new(g) STRING(g, 0, Cmdlist->Cmd);
switch (rc = Myc.ExecSQLcmd(g, Query, &Warnings)) {
switch (rc = Myc.ExecSQLcmd(g, Query->GetStr(), &Warnings)) {
case RC_NF:
AftRows = Myc.m_Afrw;
strcpy(g->Message, "Affected rows");
@@ -1650,11 +1696,11 @@ void MYXCOL::ReadColumn(PGLOBAL g)
} else
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;
case 3: Value->SetValue(tdbp->Warnings); break;
default: Value->SetValue_psz("Invalid Flag"); break;
case 0: Value->SetValue_psz(tdbp->Query->GetStr()); break;
case 1: Value->SetValue(tdbp->AftRows); break;
case 2: Value->SetValue_psz(g->Message); break;
case 3: Value->SetValue(tdbp->Warnings); break;
default: Value->SetValue_psz("Invalid Flag"); break;
} // endswitch Flag
} // end of ReadColumn