diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index b3bafa5a7d9..4fecbe9be84 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -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 diff --git a/storage/connect/mysql-test/connect/t/mysql.test b/storage/connect/mysql-test/connect/t/mysql.test index bb4b2e78e56..271e3f07465 100644 --- a/storage/connect/mysql-test/connect/t/mysql.test +++ b/storage/connect/mysql-test/connect/t/mysql.test @@ -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' diff --git a/storage/connect/mysql-test/connect/t/mysql_grant.test b/storage/connect/mysql-test/connect/t/mysql_grant.test index e825e70a84b..8eb6a90c917 100644 --- a/storage/connect/mysql-test/connect/t/mysql_grant.test +++ b/storage/connect/mysql-test/connect/t/mysql_grant.test @@ -1,78 +1,78 @@ --- 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 # + diff --git a/storage/connect/tabmysql.cpp b/storage/connect/tabmysql.cpp index 28da47d2d33..f37cb6d349e 100644 --- a/storage/connect/tabmysql.cpp +++ b/storage/connect/tabmysql.cpp @@ -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 diff --git a/storage/connect/tabmysql.h b/storage/connect/tabmysql.h index f4a234526ff..bcac10dcaa7 100644 --- a/storage/connect/tabmysql.h +++ b/storage/connect/tabmysql.h @@ -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: