mirror of
https://github.com/MariaDB/server.git
synced 2025-08-08 11:22:35 +03:00
- Allowing views and queries as parameters for PROXY base tables
NOTE: Checking for looping references cannot be done when using views as parameters. This should not be allowed on production servers and should be dependant on a system variable and/or on speciel grant. modified: storage/connect/CMakeLists.txt storage/connect/connect.cc storage/connect/ha_connect.cc storage/connect/myconn.cpp storage/connect/myconn.h storage/connect/mysql-test/connect/r/fmt.result storage/connect/mysql-test/connect/r/pivot.result storage/connect/mysql-test/connect/t/fmt.test storage/connect/mysql-test/connect/t/pivot.test storage/connect/plgdbsem.h storage/connect/plugutil.c storage/connect/tabcol.cpp storage/connect/tabcol.h storage/connect/tabfmt.cpp storage/connect/tabmysql.cpp storage/connect/tabmysql.h storage/connect/taboccur.cpp storage/connect/taboccur.h storage/connect/tabpivot.cpp storage/connect/tabpivot.h storage/connect/tabtbl.cpp storage/connect/tabutil.cpp storage/connect/tabutil.h storage/connect/xtable.h
This commit is contained in:
@@ -79,9 +79,11 @@ MYSQLDEF::MYSQLDEF(void)
|
||||
Hostname = NULL;
|
||||
Database = NULL;
|
||||
Tabname = NULL;
|
||||
Srcdef = NULL;
|
||||
Username = NULL;
|
||||
Password = NULL;
|
||||
Portnumber = 0;
|
||||
Isview = FALSE;
|
||||
Bind = FALSE;
|
||||
Delayed = FALSE;
|
||||
} // end of MYSQLDEF constructor
|
||||
@@ -302,8 +304,8 @@ bool MYSQLDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
|
||||
} else {
|
||||
// MYSQL access from a PROXY table, not using URL
|
||||
Database = Cat->GetStringCatInfo(g, "Database", "*");
|
||||
Tabname = Cat->GetStringCatInfo(g, "Name", Name); // Deprecated
|
||||
Tabname = Cat->GetStringCatInfo(g, "Tabname", Tabname);
|
||||
Tabname = Name;
|
||||
Isview = Cat->GetBoolCatInfo("View", FALSE);
|
||||
|
||||
// We must get connection parms from the calling table
|
||||
Remove_tshp(Cat);
|
||||
@@ -313,6 +315,9 @@ bool MYSQLDEF::DefineAM(PGLOBAL g, LPCSTR am, int poff)
|
||||
Portnumber = Cat->GetIntCatInfo("Port", mysqld_port);
|
||||
} // endif am
|
||||
|
||||
if ((Srcdef = Cat->GetStringCatInfo(g, "Srcdef", NULL)))
|
||||
Isview = TRUE;
|
||||
|
||||
return FALSE;
|
||||
} // end of DefineAM
|
||||
|
||||
@@ -339,18 +344,22 @@ TDBMYSQL::TDBMYSQL(PMYDEF tdp) : TDBASE(tdp)
|
||||
Host = tdp->GetHostname();
|
||||
Database = tdp->GetDatabase();
|
||||
Tabname = tdp->GetTabname();
|
||||
Srcdef = tdp->GetSrcdef();
|
||||
User = tdp->GetUsername();
|
||||
Pwd = tdp->GetPassword();
|
||||
Port = tdp->GetPortnumber();
|
||||
Isview = tdp->Isview;
|
||||
Prep = tdp->Bind;
|
||||
Delayed = tdp->Delayed;
|
||||
} else {
|
||||
Host = NULL;
|
||||
Database = NULL;
|
||||
Tabname = NULL;
|
||||
Srcdef = NULL;
|
||||
User = NULL;
|
||||
Pwd = NULL;
|
||||
Port = 0;
|
||||
Isview = FALSE;
|
||||
Prep = FALSE;
|
||||
Delayed = FALSE;
|
||||
} // endif tdp
|
||||
@@ -370,9 +379,11 @@ TDBMYSQL::TDBMYSQL(PGLOBAL g, PTDBMY tdbp) : TDBASE(tdbp)
|
||||
Host = tdbp->Host;
|
||||
Database = tdbp->Database;
|
||||
Tabname = tdbp->Tabname;
|
||||
Srcdef = tdbp->Srcdef;
|
||||
User = tdbp->User;
|
||||
Pwd = tdbp->Pwd;
|
||||
Port = tdbp->Port;
|
||||
Isview = tdbp->Isview;
|
||||
Prep = tdbp->Prep;
|
||||
Delayed = tdbp->Delayed;
|
||||
Bind = NULL;
|
||||
@@ -418,55 +429,54 @@ PCOL TDBMYSQL::MakeCol(PGLOBAL g, PCOLDEF cdp, PCOL cprec, int n)
|
||||
/***********************************************************************/
|
||||
bool TDBMYSQL::MakeSelect(PGLOBAL g)
|
||||
{
|
||||
char *colist;
|
||||
char *tk = "`";
|
||||
int len = 0, ncol = 0, rank = 0;
|
||||
int rank = 0;
|
||||
bool b = FALSE;
|
||||
PCOL colp;
|
||||
PDBUSER dup = PlgGetUser(g);
|
||||
//PDBUSER dup = PlgGetUser(g);
|
||||
|
||||
if (Query)
|
||||
return FALSE; // already done
|
||||
|
||||
for (colp = Columns; colp; colp = colp->GetNext())
|
||||
ncol++;
|
||||
if (Srcdef) {
|
||||
Query = Srcdef;
|
||||
return false;
|
||||
} // endif Srcdef
|
||||
|
||||
if (ncol) {
|
||||
colist = (char*)PlugSubAlloc(g, NULL, (NAM_LEN + 4) * ncol);
|
||||
*colist = '\0';
|
||||
//Find the address of the suballocated query
|
||||
Query = (char*)PlugSubAlloc(g, NULL, 0);
|
||||
strcpy(Query, "SELECT ");
|
||||
|
||||
if (Columns) {
|
||||
for (colp = Columns; colp; colp = colp->GetNext())
|
||||
if (colp->IsSpecial()) {
|
||||
strcpy(g->Message, MSG(NO_SPEC_COL));
|
||||
return TRUE;
|
||||
} else {
|
||||
if (b)
|
||||
strcat(colist, ", ");
|
||||
strcat(Query, ", ");
|
||||
else
|
||||
b = TRUE;
|
||||
|
||||
strcat(strcat(strcat(colist, tk), colp->GetName()), tk);
|
||||
strcat(strcat(strcat(Query, tk), colp->GetName()), tk);
|
||||
((PMYCOL)colp)->Rank = rank++;
|
||||
} // endif colp
|
||||
|
||||
} else {
|
||||
// ncol == 0 can occur for queries such as Query count(*) from...
|
||||
// for which we will count the rows from Query '*' from...
|
||||
// ncol == 0 can occur for views or queries such as
|
||||
// Query count(*) from... for which we will count the rows from
|
||||
// Query '*' from...
|
||||
// (the use of a char constant minimize the result storage)
|
||||
colist = (char*)PlugSubAlloc(g, NULL, 2);
|
||||
strcpy(colist, "'*'");
|
||||
strcat(Query, (Isview) ? "*" : "'*'");
|
||||
} // endif ncol
|
||||
|
||||
// Below 32 is space to contain extra stuff
|
||||
len += (strlen(colist) + strlen(Tabname) + 32);
|
||||
len += (To_Filter ? strlen(To_Filter) + 7 : 0);
|
||||
Query = (char*)PlugSubAlloc(g, NULL, len);
|
||||
strcat(strcpy(Query, "SELECT "), colist);
|
||||
strcat(strcat(strcat(strcat(Query, " FROM "), tk), Tabname), tk);
|
||||
|
||||
if (To_Filter)
|
||||
strcat(strcat(Query, " WHERE "), To_Filter);
|
||||
|
||||
// Now we know how much to suballocate
|
||||
PlugSubAlloc(g, NULL, strlen(Query) + 1);
|
||||
return FALSE;
|
||||
} // end of MakeSelect
|
||||
|
||||
@@ -751,7 +761,7 @@ bool TDBMYSQL::OpenDB(PGLOBAL g)
|
||||
/* Table already open, just replace it at its beginning. */
|
||||
/*******************************************************************/
|
||||
Myc.Rewind();
|
||||
return FALSE;
|
||||
return false;
|
||||
} // endif use
|
||||
|
||||
/*********************************************************************/
|
||||
@@ -763,7 +773,7 @@ bool TDBMYSQL::OpenDB(PGLOBAL g)
|
||||
/*********************************************************************/
|
||||
if (!Myc.Connected()) {
|
||||
if (Myc.Open(g, Host, Database, User, Pwd, Port))
|
||||
return TRUE;
|
||||
return true;
|
||||
|
||||
} // endif Connected
|
||||
|
||||
@@ -774,7 +784,24 @@ bool TDBMYSQL::OpenDB(PGLOBAL g)
|
||||
if (!MakeSelect(g))
|
||||
m_Rc = Myc.ExecSQL(g, Query);
|
||||
|
||||
#if 0
|
||||
if (!Myc.m_Res || !Myc.m_Fields) {
|
||||
sprintf(g->Message, "%s result", (Myc.m_Res) ? "Void" : "No");
|
||||
Myc.Close();
|
||||
return true;
|
||||
} // endif m_Res
|
||||
#endif // 0
|
||||
|
||||
if (Srcdef)
|
||||
if (SetColumnRanks(g))
|
||||
return true;
|
||||
|
||||
} else if (Mode == MODE_INSERT) {
|
||||
if (Srcdef) {
|
||||
strcpy(g->Message, "No insert into anonym views");
|
||||
return true;
|
||||
} // endif Srcdef
|
||||
|
||||
if (!MakeInsert(g)) {
|
||||
#if defined(MYSQL_PREPARED_STATEMENTS)
|
||||
int n = (Prep) ? Myc.PrepareSQL(g, Query) : Nparm;
|
||||
@@ -826,6 +853,55 @@ bool TDBMYSQL::OpenDB(PGLOBAL g)
|
||||
return FALSE;
|
||||
} // end of OpenDB
|
||||
|
||||
/***********************************************************************/
|
||||
/* Set the rank of columns in the result set. */
|
||||
/***********************************************************************/
|
||||
bool TDBMYSQL::SetColumnRanks(PGLOBAL g)
|
||||
{
|
||||
for (PCOL colp = Columns; colp; colp = colp->GetNext())
|
||||
if (((PMYCOL)colp)->FindRank(g))
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
} // end of SetColumnRanks
|
||||
|
||||
/***********************************************************************/
|
||||
/* Called by Parent table to make the columns of a View. */
|
||||
/***********************************************************************/
|
||||
PCOL TDBMYSQL::MakeFieldColumn(PGLOBAL g, char *name)
|
||||
{
|
||||
int n;
|
||||
MYSQL_FIELD *fld;
|
||||
PCOL cp, colp = NULL;
|
||||
|
||||
for (n = 0; n < Myc.m_Fields; n++) {
|
||||
fld = &Myc.m_Res->fields[n];
|
||||
|
||||
if (!stricmp(name, fld->name)) {
|
||||
colp = new(g) MYSQLCOL(fld, this, n);
|
||||
|
||||
if (colp->InitValue(g))
|
||||
return NULL;
|
||||
|
||||
if (!Columns)
|
||||
Columns = colp;
|
||||
else for (cp = Columns; cp; cp = cp->GetNext())
|
||||
if (!cp->GetNext()) {
|
||||
cp->SetNext(colp);
|
||||
break;
|
||||
} // endif Next
|
||||
|
||||
break;
|
||||
} // endif name
|
||||
|
||||
} // endfor n
|
||||
|
||||
if (!colp)
|
||||
sprintf(g->Message, "Column %s is not in view", name);
|
||||
|
||||
return colp;
|
||||
} // end of MakeFieldColumn
|
||||
|
||||
/***********************************************************************/
|
||||
/* Data Base read routine for MYSQL access method. */
|
||||
/***********************************************************************/
|
||||
@@ -939,7 +1015,7 @@ MYSQLCOL::MYSQLCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am)
|
||||
tdbp->SetColumns(this);
|
||||
} // endif cprec
|
||||
|
||||
// Set additional Dos access method information for column.
|
||||
// Set additional MySQL access method information for column.
|
||||
Long = cdp->GetLong();
|
||||
Bind = NULL;
|
||||
To_Val = NULL;
|
||||
@@ -951,6 +1027,33 @@ MYSQLCOL::MYSQLCOL(PCOLDEF cdp, PTDB tdbp, PCOL cprec, int i, PSZ am)
|
||||
|
||||
} // end of MYSQLCOL constructor
|
||||
|
||||
/***********************************************************************/
|
||||
/* MYSQLCOL public constructor. */
|
||||
/***********************************************************************/
|
||||
MYSQLCOL::MYSQLCOL(MYSQL_FIELD *fld, PTDB tdbp, int i, PSZ am)
|
||||
: COLBLK(NULL, tdbp, i)
|
||||
{
|
||||
Name = fld->name;
|
||||
Opt = 0;
|
||||
Long = fld->length;
|
||||
Buf_Type = MYSQLtoPLG(fld->type);
|
||||
strcpy(Format.Type, GetFormatType(Buf_Type));
|
||||
Format.Length = Long;
|
||||
Format.Prec = fld->decimals;
|
||||
ColUse = U_P;
|
||||
Nullable = !IS_NOT_NULL(fld->flags);
|
||||
|
||||
// Set additional MySQL access method information for column.
|
||||
Bind = NULL;
|
||||
To_Val = NULL;
|
||||
Slen = 0;
|
||||
Rank = i;
|
||||
|
||||
if (trace)
|
||||
htrc(" making new %sCOL C%d %s at %p\n", am, Index, Name, this);
|
||||
|
||||
} // end of MYSQLCOL constructor
|
||||
|
||||
/***********************************************************************/
|
||||
/* MYSQLCOL constructor used for copying columns. */
|
||||
/* tdbp is the pointer to the new table descriptor. */
|
||||
@@ -964,6 +1067,24 @@ MYSQLCOL::MYSQLCOL(MYSQLCOL *col1, PTDB tdbp) : COLBLK(col1, tdbp)
|
||||
Rank = col1->Rank;
|
||||
} // end of MYSQLCOL copy constructor
|
||||
|
||||
/***********************************************************************/
|
||||
/* FindRank: Find the rank of this column in the result set. */
|
||||
/***********************************************************************/
|
||||
bool MYSQLCOL::FindRank(PGLOBAL g)
|
||||
{
|
||||
int n;
|
||||
MYSQLC myc = ((PTDBMY)To_Tdb)->Myc;
|
||||
|
||||
for (n = 0; n < myc.m_Fields; n++)
|
||||
if (!stricmp(Name, myc.m_Res->fields[n].name)) {
|
||||
Rank = n;
|
||||
return false;
|
||||
} // endif Name
|
||||
|
||||
sprintf(g->Message, "Column %s not in result set", Name);
|
||||
return true;
|
||||
} // end of FindRank
|
||||
|
||||
/***********************************************************************/
|
||||
/* SetBuffer: prepare a column block for write operation. */
|
||||
/***********************************************************************/
|
||||
@@ -1049,11 +1170,6 @@ void MYSQLCOL::ReadColumn(PGLOBAL g)
|
||||
int rc;
|
||||
PTDBMY tdbp = (PTDBMY)To_Tdb;
|
||||
|
||||
if (trace)
|
||||
htrc("MySQL ReadColumn: name=%s\n", Name);
|
||||
|
||||
assert (Rank >= 0);
|
||||
|
||||
/*********************************************************************/
|
||||
/* If physical fetching of the line was deferred, do it now. */
|
||||
/*********************************************************************/
|
||||
@@ -1066,14 +1182,17 @@ void MYSQLCOL::ReadColumn(PGLOBAL g)
|
||||
} else
|
||||
tdbp->Fetched = TRUE;
|
||||
|
||||
if ((buf = ((PTDBMY)To_Tdb)->Myc.GetCharField(Rank)))
|
||||
if ((buf = ((PTDBMY)To_Tdb)->Myc.GetCharField(Rank))) {
|
||||
if (trace)
|
||||
htrc("MySQL ReadColumn: name=%s buf=%s\n", Name, buf);
|
||||
|
||||
Value->SetValue_char(buf, Long);
|
||||
else {
|
||||
} else {
|
||||
if (Nullable)
|
||||
Value->SetNull(true);
|
||||
|
||||
Value->Reset(); // Null value
|
||||
} // endelse
|
||||
} // endif buf
|
||||
|
||||
} // end of ReadColumn
|
||||
|
||||
@@ -1121,5 +1240,5 @@ TDBMCL::TDBMCL(PMYDEF tdp) : TDBCAT(tdp)
|
||||
/***********************************************************************/
|
||||
PQRYRES TDBMCL::GetResult(PGLOBAL g)
|
||||
{
|
||||
return MyColumns(g, Host, Db, User, Pwd, Tab, NULL, Port, false, false);
|
||||
return MyColumns(g, Host, Db, User, Pwd, Tab, NULL, Port, false);
|
||||
} // end of GetResult
|
||||
|
Reference in New Issue
Block a user