Commit bb597a76 authored by Olivier Bertrand's avatar Olivier Bertrand

- Add test on MYSQL table self reference during CREATE TABLE

  Fix option other ignored when parsing URL

modified:
  storage/connect/ha_connect.cc
  storage/connect/mysql-test/connect/t/mysql.test
  storage/connect/mysql-test/connect/t/mysql_grant.test
  storage/connect/tabmysql.cpp
  storage/connect/tabmysql.h
parent 0f6bcf73
......@@ -3722,6 +3722,25 @@ static void add_option(THD* thd, HA_CREATE_INFO *create_info,
#endif // NEW_WAY
} // end of add_option
// Used to check whether a MYSQL table is created on itself
static bool CheckSelf(PGLOBAL g, TABLE_SHARE *s, const char *host,
const char *db, char *tab, const char *src, int port)
{
if (src)
return false;
else if (host && stricmp(host, "localhost") && strcmp(host, "127.0.0.1"))
return false;
else if (db && stricmp(db, s->db.str))
return false;
else if (tab && stricmp(tab, s->table_name.str))
return false;
else if (port && port != GetDefaultPort())
return false;
strcpy(g->Message, "This MySQL table is defined on itself");
return true;
} // end of CheckSelf
/**
@brief
connect_assisted_discovery() is called when creating a table with no columns.
......@@ -3740,7 +3759,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
{
char spc= ',', qch= 0;
const char *fncn= "?";
const char *user, *fn, *db, *host, *pwd, *prt, *sep, *tbl, *src;
const char *user, *fn, *db, *host, *pwd, *sep, *tbl, *src;
const char *col, *ocl, *rnk, *pic, *fcl;
char *tab, *dsn;
#if defined(WIN32)
......@@ -3767,7 +3786,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
if (!g)
return HA_ERR_INTERNAL_ERROR;
user= host= pwd= prt= tbl= src= col= ocl= pic= fcl= rnk= dsn= NULL;
user= host= pwd= tbl= src= col= ocl= pic= fcl= rnk= dsn= NULL;
// Get the useful create options
ttp= GetTypeID(topt->type);
......@@ -3795,14 +3814,13 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
fcl= GetListOption(g, "fnccol", topt->oplist, NULL);
rnk= GetListOption(g, "rankcol", topt->oplist, NULL);
pwd= GetListOption(g, "password", topt->oplist);
prt= GetListOption(g, "port", topt->oplist);
port= (prt) ? atoi(prt) : 0;
#if defined(WIN32)
nsp= GetListOption(g, "namespace", topt->oplist);
cls= GetListOption(g, "class", topt->oplist);
#endif // WIN32
port= atoi(GetListOption(g, "port", topt->oplist, "0"));
mxr= atoi(GetListOption(g,"maxerr", topt->oplist, "0"));
cop= atoi(GetListOption(g, "createopt", topt->oplist, "0"));
cop= atoi(GetListOption(g, "checkdsn", topt->oplist, "0"));
} else {
host= "localhost";
user= "root";
......@@ -3848,7 +3866,7 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
} // endif p
} else if (ttp != TAB_ODBC || !(fnc & (FNC_TABLE | FNC_COL)))
tab= (char*)create_info->alias;
tab= table_s->table_name.str; // Default value
#if defined(NEW_WAY)
add_option(thd, create_info, "tabname", tab);
......@@ -3863,12 +3881,10 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
if (fnc & (FNC_DSN | FNC_DRIVER))
ok= true;
else if (!stricmp(thd->main_security_ctx.host, "localhost")
&& cop != 2) {
&& cop == 1) {
if ((dsn = ODBCCheckConnection(g, dsn, cop)) != NULL) {
create_info->connect_string.str= dsn;
create_info->connect_string.length= strlen(dsn);
thd->make_lex_string(&create_info->connect_string, dsn, strlen(dsn));
ok= true;
} // endif dsn
} else if (!dsn)
......@@ -3893,31 +3909,46 @@ static int connect_assisted_discovery(handlerton *hton, THD* thd,
case TAB_MYSQL:
ok= true;
if ((dsn= create_info->connect_string.str)) {
if (create_info->connect_string.str) {
int len= create_info->connect_string.length;
PMYDEF mydef= new(g) MYSQLDEF();
PDBUSER dup= PlgGetUser(g);
PCATLG cat= (dup) ? dup->Catalog : NULL;
dsn= (char*)PlugSubAlloc(g, NULL, strlen(dsn) + 1);
strncpy(dsn, create_info->connect_string.str,
create_info->connect_string.length);
dsn[create_info->connect_string.length]= 0;
dsn= (char*)PlugSubAlloc(g, NULL, len + 1);
strncpy(dsn, create_info->connect_string.str, len);
dsn[len]= 0;
mydef->SetName(create_info->alias);
mydef->SetCat(cat);
if (!mydef->ParseURL(g, dsn)) {
host= mydef->GetHostname();
user= mydef->GetUsername();
pwd= mydef->GetPassword();
db= mydef->GetDatabase();
tab= mydef->GetTabname();
port= mydef->GetPortnumber();
if (!mydef->ParseURL(g, dsn, false)) {
if (mydef->GetHostname())
host= mydef->GetHostname();
if (mydef->GetUsername())
user= mydef->GetUsername();
if (mydef->GetPassword())
pwd= mydef->GetPassword();
if (mydef->GetDatabase())
db= mydef->GetDatabase();
if (mydef->GetTabname())
tab= mydef->GetTabname();
if (mydef->GetPortnumber())
port= mydef->GetPortnumber();
} else
ok= false;
} else if (!user)
user= "root";
if (CheckSelf(g, table_s, host, db, tab, src, port))
ok= false;
break;
#endif // MYSQL_SUPPORT
#if defined(WIN32)
......@@ -4276,6 +4307,54 @@ int ha_connect::create(const char *name, TABLE *table_arg,
DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
} // endif tabname
case TAB_MYSQL:
{const char *src= options->srcdef;
char *host, *db, *tab= (char*)options->tabname;
int port;
host= GetListOption(g, "host", options->oplist, NULL);
db= GetListOption(g, "database", options->oplist, NULL);
port= atoi(GetListOption(g, "port", options->oplist, "0"));
if (create_info->connect_string.str) {
char *dsn;
int len= create_info->connect_string.length;
PMYDEF mydef= new(g) MYSQLDEF();
PDBUSER dup= PlgGetUser(g);
PCATLG cat= (dup) ? dup->Catalog : NULL;
dsn= (char*)PlugSubAlloc(g, NULL, len + 1);
strncpy(dsn, create_info->connect_string.str, len);
dsn[len]= 0;
mydef->SetName(create_info->alias);
mydef->SetCat(cat);
if (!mydef->ParseURL(g, dsn, false)) {
if (mydef->GetHostname())
host= mydef->GetHostname();
if (mydef->GetDatabase())
db= mydef->GetDatabase();
if (mydef->GetTabname())
tab= mydef->GetTabname();
if (mydef->GetPortnumber())
port= mydef->GetPortnumber();
} else {
my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
} // endif ParseURL
} // endif connect_string
if (CheckSelf(g, table_arg->s, host, db, tab, src, port)) {
my_message(ER_UNKNOWN_ERROR, g->Message, MYF(0));
DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
} // endif CheckSelf
}break;
default: /* do nothing */;
break;
} // endswitch ttp
......
......@@ -10,7 +10,7 @@ let $PORT= `select @@port`;
--disable_query_log
--replace_result $PORT PORT
--error 0,ER_UNKNOWN_ERROR
--eval CREATE TABLE t1 (a INT) ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT'
--eval CREATE TABLE t1 (a INT) ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='tx1' OPTION_LIST='host=localhost,user=root,port=$PORT'
if (!`SELECT count(*) FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA='test' AND TABLE_NAME='t1'
AND ENGINE='CONNECT'
......
-- source include/not_embedded.inc
let $PORT= `select @@port`;
--disable_query_log
--replace_result $PORT PORT
--error 0,ER_UNKNOWN_ERROR
--eval CREATE TABLE t1 (a INT) ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='t1' OPTION_LIST='host=localhost,user=root,port=$PORT'
if (!`SELECT count(*) FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA='test' AND TABLE_NAME='t1'
AND ENGINE='CONNECT'
AND CREATE_OPTIONS LIKE '%`table_type`=MySQL%'`)
{
Skip Need MySQL support;
}
DROP TABLE t1;
--enable_query_log
--echo #
--echo # Testing FILE privilege
--echo #
GRANT ALL PRIVILEGES ON *.* TO user@localhost;
REVOKE FILE ON *.* FROM user@localhost;
--connect(user,localhost,user,,)
--connection user
SELECT user();
--replace_result $PORT PORT
--error ER_ACCESS_DENIED_ERROR
--eval CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=MySQL OPTION_LIST='host=localhost,user=root1,port=$PORT'
--connection default
SELECT user();
CREATE TABLE t1remote (a INT NOT NULL);
INSERT INTO t1remote VALUES (10),(20),(30);
--replace_result $PORT PORT
--eval CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=MySQL TABNAME=t1remote OPTION_LIST='host=localhost,user=root,port=$PORT'
SELECT * FROM t1;
--connection user
SELECT user();
--error ER_ACCESS_DENIED_ERROR
SELECT * FROM t1;
--error ER_ACCESS_DENIED_ERROR
INSERT INTO t1 VALUES ('xxx');
--error ER_ACCESS_DENIED_ERROR
DELETE FROM t1 WHERE a='xxx';
--error ER_ACCESS_DENIED_ERROR
UPDATE t1 SET a='yyy' WHERE a='xxx';
--error ER_ACCESS_DENIED_ERROR
TRUNCATE TABLE t1;
--error ER_ACCESS_DENIED_ERROR
ALTER TABLE t1 READONLY=1;
--error ER_ACCESS_DENIED_ERROR
CREATE VIEW v1 AS SELECT * FROM t1;
--echo # Testing a VIEW created with FILE privileges but accessed with no FILE
--connection default
SELECT user();
CREATE VIEW v1 AS SELECT * FROM t1;
--connection user
SELECT user();
--error ER_ACCESS_DENIED_ERROR
SELECT * FROM v1;
--error ER_ACCESS_DENIED_ERROR
INSERT INTO v1 VALUES (2);
--error ER_ACCESS_DENIED_ERROR
UPDATE v1 SET a=123;
--error ER_ACCESS_DENIED_ERROR
DELETE FROM v1;
--disconnect user
--connection default
SELECT user();
DROP VIEW v1;
DROP TABLE t1, t1remote;
DROP USER user@localhost;
--echo #
--echo # Testing FILE privileges done
--echo #
-- source include/not_embedded.inc
let $PORT= `select @@port`;
--disable_query_log
--replace_result $PORT PORT
--error 0,ER_UNKNOWN_ERROR
--eval CREATE TABLE t1 (a INT) ENGINE=CONNECT TABLE_TYPE=MYSQL TABNAME='tx1' OPTION_LIST='host=localhost,user=root,port=$PORT'
if (!`SELECT count(*) FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA='test' AND TABLE_NAME='t1'
AND ENGINE='CONNECT'
AND CREATE_OPTIONS LIKE '%`table_type`=MySQL%'`)
{
Skip Need MySQL support;
}
DROP TABLE t1;
--enable_query_log
--echo #
--echo # Testing FILE privilege
--echo #
GRANT ALL PRIVILEGES ON *.* TO user@localhost;
REVOKE FILE ON *.* FROM user@localhost;
--connect(user,localhost,user,,)
--connection user
SELECT user();
--replace_result $PORT PORT
--error ER_ACCESS_DENIED_ERROR
--eval CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=MySQL OPTION_LIST='host=localhost,user=root1,port=$PORT'
--connection default
SELECT user();
CREATE TABLE t1remote (a INT NOT NULL);
INSERT INTO t1remote VALUES (10),(20),(30);
--replace_result $PORT PORT
--eval CREATE TABLE t1 (a INT NOT NULL) ENGINE=CONNECT TABLE_TYPE=MySQL TABNAME=t1remote OPTION_LIST='host=localhost,user=root,port=$PORT'
SELECT * FROM t1;
--connection user
SELECT user();
--error ER_ACCESS_DENIED_ERROR
SELECT * FROM t1;
--error ER_ACCESS_DENIED_ERROR
INSERT INTO t1 VALUES ('xxx');
--error ER_ACCESS_DENIED_ERROR
DELETE FROM t1 WHERE a='xxx';
--error ER_ACCESS_DENIED_ERROR
UPDATE t1 SET a='yyy' WHERE a='xxx';
--error ER_ACCESS_DENIED_ERROR
TRUNCATE TABLE t1;
--error ER_ACCESS_DENIED_ERROR
ALTER TABLE t1 READONLY=1;
--error ER_ACCESS_DENIED_ERROR
CREATE VIEW v1 AS SELECT * FROM t1;
--echo # Testing a VIEW created with FILE privileges but accessed with no FILE
--connection default
SELECT user();
CREATE VIEW v1 AS SELECT * FROM t1;
--connection user
SELECT user();
--error ER_ACCESS_DENIED_ERROR
SELECT * FROM v1;
--error ER_ACCESS_DENIED_ERROR
INSERT INTO v1 VALUES (2);
--error ER_ACCESS_DENIED_ERROR
UPDATE v1 SET a=123;
--error ER_ACCESS_DENIED_ERROR
DELETE FROM v1;
--disconnect user
--connection default
SELECT user();
DROP VIEW v1;
DROP TABLE t1, t1remote;
DROP USER user@localhost;
--echo #
--echo # Testing FILE privileges done
--echo #
......@@ -172,7 +172,7 @@ bool MYSQLDEF::GetServerInfo(PGLOBAL g, const char *server_name)
/* true error */
/* */
/***********************************************************************/
bool MYSQLDEF::ParseURL(PGLOBAL g, char *url)
bool MYSQLDEF::ParseURL(PGLOBAL g, char *url, bool b)
{
if ((!strstr(url, "://") && (!strchr(url, '@')))) {
// No :// or @ in connection string. Must be a straight
......@@ -249,34 +249,41 @@ bool MYSQLDEF::ParseURL(PGLOBAL g, char *url)
if ((Database = strchr(Hostname, '/'))) {
*Database++ = 0;
if ((Tabname = strchr(Database, '/')))
if ((Tabname = strchr(Database, '/'))) {
*Tabname++ = 0;
// Make sure there's not an extra /
if ((strchr(Tabname, '/'))) {
strcpy(g->Message, "Syntax error in URL");
return true;
} // endif /
// Make sure there's not an extra /
if ((strchr(Tabname, '/'))) {
strcpy(g->Message, "Syntax error in URL");
return true;
} // endif /
} // endif Tabname
} // endif database
if ((sport = strchr(Hostname, ':')))
*sport++ = 0;
Portnumber = (sport && sport[0]) ? atoi(sport) : GetDefaultPort();
// For unspecified values, get the values of old style options
// but only if called from MYSQLDEF, else set them to NULL
Portnumber = (sport && sport[0]) ? atoi(sport)
: (b) ? Cat->GetIntCatInfo("Port", GetDefaultPort()) : 0;
if (Username[0] == 0)
Username = Cat->GetStringCatInfo(g, "User", "*");
Username = (b) ? Cat->GetStringCatInfo(g, "User", "*") : NULL;
if (Hostname[0] == 0)
Hostname = Cat->GetStringCatInfo(g, "Host", "localhost");
Hostname = (b) ? Cat->GetStringCatInfo(g, "Host", "localhost") : NULL;
if (!Database || !*Database)
Database = Cat->GetStringCatInfo(g, "Database", "*");
Database = (b) ? Cat->GetStringCatInfo(g, "Database", "*") : NULL;
if (!Tabname || !*Tabname)
Tabname = Name;
Tabname = (b) ? Cat->GetStringCatInfo(g, "Tabname", Name) : NULL;
if (!Password)
Password = (b) ? Cat->GetStringCatInfo(g, "Password", NULL) : NULL;
} // endif URL
#if 0
......
......@@ -40,7 +40,7 @@ class MYSQLDEF : public TABDEF {/* Logical table description */
// Methods
virtual bool DefineAM(PGLOBAL g, LPCSTR am, int poff);
virtual PTDB GetTable(PGLOBAL g, MODE m);
bool ParseURL(PGLOBAL g, char *url);
bool ParseURL(PGLOBAL g, char *url, bool b = true);
bool GetServerInfo(PGLOBAL g, const char *server_name);
protected:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment