#At file:///opt/local/work/mysql-6.0-runtime/
2745 Konstantin Osipov 2008-11-13
Commit to be able to patch.
modified:
libmysql/libmysql.c
mysql-test/suite/backup/r/backup.result
mysql-test/suite/backup/r/backup_db_grants.result
mysql-test/suite/backup/r/backup_errors.result
mysql-test/suite/backup/r/backup_views.result
mysql-test/suite/backup/t/backup_db_grants.test
mysql-test/suite/backup/t/backup_errors.test
mysql-test/suite/backup/t/backup_views.test
sql/backup/backup_aux.h
sql/backup/backup_info.cc
sql/backup/backup_info.h
sql/backup/backup_test.cc
sql/backup/image_info.h
sql/backup/kernel.cc
sql/backup/logger.cc
sql/ddl_blocker.cc
sql/ddl_blocker.h
sql/log.cc
sql/mysql_priv.h
sql/protocol.cc
sql/protocol.h
sql/share/errmsg.txt
sql/si_objects.cc
sql/si_objects.h
sql/sql_class.cc
sql/sql_error.cc
sql/sql_error.h
sql/sql_lex.cc
sql/sql_lex.h
sql/sql_parse.cc
sql/sql_prepare.cc
sql/sql_yacc.yy
=== modified file 'libmysql/libmysql.c'
--- a/libmysql/libmysql.c 2008-10-22 11:51:28 +0000
+++ b/libmysql/libmysql.c 2008-11-13 19:34:18 +0000
@@ -4863,7 +4863,10 @@ int STDCALL mysql_stmt_next_result(MYSQL
rc= mysql_next_result(mysql);
if (rc)
+ {
+ set_stmt_errmsg(stmt, &mysql->net);
DBUG_RETURN(rc);
+ }
stmt->state= MYSQL_STMT_EXECUTE_DONE;
stmt->bind_result_done= FALSE;
=== modified file 'mysql-test/suite/backup/r/backup.result'
--- a/mysql-test/suite/backup/r/backup.result 2008-10-07 17:15:44 +0000
+++ b/mysql-test/suite/backup/r/backup.result 2008-11-13 19:34:18 +0000
@@ -51,10 +51,6 @@ id #
command Daemon
state MyISAM backup: holding table locks
info MyISAM driver locking thread
-id #
-command Query
-state debug sync point: myisam_locking_thread_added
-info BACKUP DATABASE db1,db2 TO 'test.ba'
breakpoints: Sending finish signal to wake BACKUP.
SET DEBUG_SYNC= 'now SIGNAL finish';
backup_id
=== modified file 'mysql-test/suite/backup/r/backup_db_grants.result'
--- a/mysql-test/suite/backup/r/backup_db_grants.result 2008-10-07 17:15:44 +0000
+++ b/mysql-test/suite/backup/r/backup_db_grants.result 2008-11-13 19:34:18 +0000
@@ -63,10 +63,31 @@ GRANT USAGE ON *.* TO 'bup_user2'@'%'
SHOW GRANTS FOR 'bup_user3'@'%';
Grants for bup_user3@%
GRANT USAGE ON *.* TO 'bup_user3'@'%'
+SHOW GRANTS FOR 'no_user'@'%';
+ERROR 42000: There is no such grant defined for user 'no_user' on host '%'
Run Restore
RESTORE FROM 'bup_db_grants.bak';
backup_id
#
+Warnings:
+# 1737 The grant 'ALTER ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
+# 1737 The grant 'ALTER ROUTINE ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
+# 1737 The grant 'CREATE ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
+# 1737 The grant 'CREATE ROUTINE ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
+# 1737 The grant 'CREATE TEMPORARY TABLES ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
+# 1737 The grant 'CREATE VIEW ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
+# 1737 The grant 'DELETE ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
+# 1737 The grant 'DROP ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
+# 1737 The grant 'EVENT ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
+# 1737 The grant 'EXECUTE ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
+# 1737 The grant 'INDEX ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
+# 1737 The grant 'INSERT ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
+# 1737 The grant 'LOCK TABLES ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
+# 1737 The grant 'REFERENCES ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
+# 1737 The grant 'SELECT ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
+# 1737 The grant 'SHOW VIEW ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
+# 1737 The grant 'TRIGGER ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
+# 1737 The grant 'UPDATE ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
SHOW TABLES FROM bup_db_grants;
Tables_in_bup_db_grants
s1
@@ -99,6 +120,28 @@ Run Restore
RESTORE FROM 'bup_db_grants.bak';
backup_id
#
+Warnings:
+# 1737 The grant 'INSERT ON bup_db_grants.*' for the user 'bup_user2'@'%' was skipped because the user does not exist.
+# 1737 The grant 'INSERT(b) ON bup_db_grants.s1' for the user 'bup_user2'@'%' was skipped because the user does not exist.
+# 1737 The grant 'SELECT(b) ON bup_db_grants.s1' for the user 'bup_user2'@'%' was skipped because the user does not exist.
+# 1737 The grant 'ALTER ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
+# 1737 The grant 'ALTER ROUTINE ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
+# 1737 The grant 'CREATE ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
+# 1737 The grant 'CREATE ROUTINE ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
+# 1737 The grant 'CREATE TEMPORARY TABLES ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
+# 1737 The grant 'CREATE VIEW ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
+# 1737 The grant 'DELETE ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
+# 1737 The grant 'DROP ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
+# 1737 The grant 'EVENT ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
+# 1737 The grant 'EXECUTE ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
+# 1737 The grant 'INDEX ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
+# 1737 The grant 'INSERT ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
+# 1737 The grant 'LOCK TABLES ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
+# 1737 The grant 'REFERENCES ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
+# 1737 The grant 'SELECT ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
+# 1737 The grant 'SHOW VIEW ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
+# 1737 The grant 'TRIGGER ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
+# 1737 The grant 'UPDATE ON bup_db_grants.*' for the user 'no_user'@'%' was skipped because the user does not exist.
SHOW TABLES FROM bup_db_grants;
Tables_in_bup_db_grants
s1
=== modified file 'mysql-test/suite/backup/r/backup_errors.result'
--- a/mysql-test/suite/backup/r/backup_errors.result 2008-10-07 17:15:44 +0000
+++ b/mysql-test/suite/backup/r/backup_errors.result 2008-11-13 19:34:18 +0000
@@ -110,7 +110,7 @@ delete database files so that check_db_d
si_objects.cc @ DatabaseObj::do_serialize
SET DEBUG_SYNC='now SIGNAL db_will_fail';
Database has been deleted, backup will fail
-ERROR 42000: Unknown database 'db1'
+ERROR HY000: Failed to obtain meta-data for database `db1`
Test that backup fails with error if a table used by
a trigger cannot be opened
=== modified file 'mysql-test/suite/backup/r/backup_views.result'
--- a/mysql-test/suite/backup/r/backup_views.result 2008-10-07 17:15:44 +0000
+++ b/mysql-test/suite/backup/r/backup_views.result 2008-11-13 19:34:18 +0000
@@ -277,10 +277,14 @@ DROP DATABASE bup_db2;
Restore database.
restore database with view dependency to other, non-existing db
RESTORE FROM 'bup_objectview1.bak';
-ERROR HY000: Could not restore view `bup_db1`.`v5`. Please check the view definition for possible missing dependencies.
+backup_id
+#
DROP DATABASE bup_db1;
+DROP DATABASE bup_db2;
RESTORE FROM 'bup_objectview2.bak';
-ERROR HY000: Could not restore view `bup_db2`.`student_details`. Please check the view definition for possible missing dependencies.
+backup_id
+#
+DROP DATABASE bup_db1;
DROP DATABASE bup_db2;
RESTORE FROM 'bup_objectview.bak';
backup_id
@@ -581,10 +585,13 @@ ALTER VIEW alter1 AS SELECT 6;
Testing view selecting from altered view
+SELECT * FROM alter1;
+6
+6
SELECT * FROM alter2;
ERROR HY000: View 'bup_db1.alter2' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
BACKUP DATABASE bup_db1 TO 'bup_alterview.bak';
-ERROR HY000: View 'bup_db1.alter2' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them
+ERROR HY000: Failed to obtain meta-data for view `bup_db1`.`alter2`
*** EXIT Backup of database with altered view
=== modified file 'mysql-test/suite/backup/t/backup_db_grants.test'
--- a/mysql-test/suite/backup/t/backup_db_grants.test 2008-10-07 17:15:44 +0000
+++ b/mysql-test/suite/backup/t/backup_db_grants.test 2008-11-13 19:34:18 +0000
@@ -60,6 +60,8 @@ FLUSH PRIVILEGES;
SHOW GRANTS FOR 'bup_user1'@'%';
SHOW GRANTS FOR bup_user2;
SHOW GRANTS FOR 'bup_user3'@'%';
+--error ER_NONEXISTING_GRANT
+SHOW GRANTS FOR 'no_user'@'%';
--echo Run Restore
--replace_column 1 #
=== modified file 'mysql-test/suite/backup/t/backup_errors.test'
--- a/mysql-test/suite/backup/t/backup_errors.test 2008-10-07 17:15:44 +0000
+++ b/mysql-test/suite/backup/t/backup_errors.test 2008-11-13 19:34:18 +0000
@@ -251,7 +251,7 @@ SET DEBUG_SYNC='now SIGNAL db_will_fail'
connection con2;
--echo Database has been deleted, backup will fail
---error ER_BAD_DB_ERROR
+--error ER_BACKUP_GET_META_DB
reap;
--echo
=== modified file 'mysql-test/suite/backup/t/backup_views.test'
--- a/mysql-test/suite/backup/t/backup_views.test 2008-10-07 17:15:44 +0000
+++ b/mysql-test/suite/backup/t/backup_views.test 2008-11-13 19:34:18 +0000
@@ -205,18 +205,20 @@ DROP DATABASE bup_db2;
--echo restore database with view dependency to other, non-existing db
---error ER_BACKUP_CANT_RESTORE_VIEW
+replace_column 1 #;
RESTORE FROM 'bup_objectview1.bak';
# An incomplete bup_db1 was created by the failing restore operation.
# Remove it before trying restore of bup_db2.
DROP DATABASE bup_db1;
+DROP DATABASE bup_db2;
---error ER_BACKUP_CANT_RESTORE_VIEW
+replace_column 1 #;
RESTORE FROM 'bup_objectview2.bak';
# An incomplete bup_db2 was created by the failing restore operation.
# Remove it before reverting to the working backup image
+DROP DATABASE bup_db1;
DROP DATABASE bup_db2;
replace_column 1 #;
@@ -349,11 +351,13 @@ ALTER VIEW alter1 AS SELECT 6;
--echo Testing view selecting from altered view
--echo
+SELECT * FROM alter1;
+
--error ER_VIEW_INVALID
SELECT * FROM alter2;
#fails
---error ER_VIEW_INVALID
+--error ER_BACKUP_GET_META_VIEW
BACKUP DATABASE bup_db1 TO 'bup_alterview.bak';
--echo
=== modified file 'sql/backup/backup_aux.h'
--- a/sql/backup/backup_aux.h 2008-10-14 12:08:56 +0000
+++ b/sql/backup/backup_aux.h 2008-11-13 19:34:18 +0000
@@ -42,12 +42,6 @@ storage_engine_ref get_se_by_name(const
namespace backup {
/**
- Constants for appending uniqueness to privileges in backup catalog.
-*/
-#define UNIQUE_PRIV_KEY_LEN 9
-#define UNIQUE_PRIV_KEY_FORMAT "%08lu"
-
-/**
Local version of LEX_STRING structure.
Defines various constructors for convenience.
=== modified file 'sql/backup/backup_info.cc'
--- a/sql/backup/backup_info.cc 2008-10-27 13:06:21 +0000
+++ b/sql/backup/backup_info.cc 2008-11-13 19:34:18 +0000
@@ -532,7 +532,7 @@ backup::Image_info::Db* Backup_info::add
@returns 0 on success, error code otherwise.
*/
-int Backup_info::add_dbs(List< ::LEX_STRING > &dbs)
+int Backup_info::add_dbs(THD *thd, List< ::LEX_STRING > &dbs)
{
using namespace obs;
@@ -552,7 +552,7 @@ int Backup_info::add_dbs(List< ::LEX_STR
obs::Obj *obj= get_database(&db_name); // reports errors
- if (obj && !check_db_existence(&db_name))
+ if (obj && !check_db_existence(thd, &db_name))
{
if (!unknown_dbs.is_empty()) // we just compose unknown_dbs list
{
@@ -727,7 +727,7 @@ int Backup_info::add_db_items(Db &db)
// If this table uses a tablespace, add this tablespace to the catalogue.
- obj= get_tablespace_for_table(m_ctx.m_thd, &db.name(), &tbl->name());
+ obj= find_tablespace_for_table(m_ctx.m_thd, &db.name(), &tbl->name());
if (obj)
{
@@ -1031,8 +1031,7 @@ Backup_info::add_db_object(Db &db, const
ulong pos= db.obj_count();
DBUG_ASSERT(obj);
- String *name= (String *)obj->get_name();
- DBUG_ASSERT(name);
+ DBUG_ASSERT(obj->get_name());
switch (type) {
@@ -1052,22 +1051,6 @@ Backup_info::add_db_object(Db &db, const
}
- /*
- Generate a unique name for the privilege (grant) objects.
- Note: this name does not alter the mechanics of the
- grant objects in si_objects.cc
- */
- if (type == BSTREAM_IT_PRIVILEGE)
- {
- String new_name;
- char buff[10];
- sprintf(buff, UNIQUE_PRIV_KEY_FORMAT, pos);
- new_name.append(*name);
- new_name.append(" ");
- new_name.append(buff);
- name->copy(new_name);
- }
-
/*
Add new object to the dependency list. If it is a view, add its
dependencies first.
@@ -1078,11 +1061,11 @@ Backup_info::add_db_object(Db &db, const
// Get a dep. list node for the object.
- int res= get_dep_node(db.name(), *name, type, n);
+ int res= get_dep_node(db.name(), *obj->get_name(), type, n);
if (res == get_dep_node_res::ERROR)
{
- m_ctx.fatal_error(error, db.name().ptr(), name->ptr());
+ m_ctx.fatal_error(error, db.name().ptr(), obj->get_name()->ptr());
return NULL;
}
@@ -1097,7 +1080,7 @@ Backup_info::add_db_object(Db &db, const
if (type == BSTREAM_IT_VIEW)
if (add_view_deps(*obj))
{
- m_ctx.fatal_error(error, db.name().ptr(), name->ptr());
+ m_ctx.fatal_error(error, db.name().ptr(), obj->get_name()->ptr());
return NULL;
}
@@ -1114,11 +1097,11 @@ Backup_info::add_db_object(Db &db, const
objects.
*/
- Dbobj *o= Image_info::add_db_object(db, type, *name, pos);
+ Dbobj *o= Image_info::add_db_object(db, type, *obj->get_name(), pos);
if (!o)
{
- m_ctx.fatal_error(error, db.name().ptr(), name->ptr());
+ m_ctx.fatal_error(error, db.name().ptr(), obj->get_name()->ptr());
return NULL;
}
@@ -1134,7 +1117,7 @@ Backup_info::add_db_object(Db &db, const
n->obj= o;
DBUG_PRINT("backup",("Added object %s of type %d from database %s (pos=%lu)",
- name->ptr(), type, db.name().ptr(), pos));
+ obj->get_name()->ptr(), type, db.name().ptr(), pos));
return o;
}
=== modified file 'sql/backup/backup_info.h'
--- a/sql/backup/backup_info.h 2008-10-27 13:06:21 +0000
+++ b/sql/backup/backup_info.h 2008-11-13 19:34:18 +0000
@@ -38,7 +38,7 @@ class Backup_info: public backup::Image_
bool is_valid();
- int add_dbs(List< ::LEX_STRING >&);
+ int add_dbs(THD *thd, List< ::LEX_STRING >&);
int add_all_dbs();
int close();
=== modified file 'sql/backup/backup_test.cc'
--- a/sql/backup/backup_test.cc 2008-10-17 11:28:25 +0000
+++ b/sql/backup/backup_test.cc 2008-11-13 19:34:18 +0000
@@ -32,7 +32,7 @@ int execute_backup_test_command(THD *thd
{
String tmp_db_name("qqq", 3, system_charset_info);
- DBUG_ASSERT(obs::check_db_existence(&tmp_db_name));
+ DBUG_ASSERT(obs::check_db_existence(thd, &tmp_db_name));
}
/*
@@ -62,7 +62,7 @@ int execute_backup_test_command(THD *thd
if (is_internal_db_name(db->get_db_name()))
continue;
- DBUG_ASSERT(!obs::check_db_existence(db->get_db_name()));
+ DBUG_ASSERT(!obs::check_db_existence(thd, db->get_db_name()));
//
// List tables..
@@ -247,10 +247,7 @@ int execute_backup_test_command(THD *thd
protocol->prepare_for_resend();
protocol->store(const_cast<String*>(db->get_name()));
protocol->store(const_cast<String*>(grant->get_name()));
- String user;
- String host;
- String *user_host= (String *)grant->get_name();
- check_user_existence(thd, user_host);
+ check_user_existence(thd, grant);
protocol->store(C_STRING_WITH_LEN("GRANT"),
system_charset_info);
grant->serialize(thd, &serial);
=== modified file 'sql/backup/image_info.h'
--- a/sql/backup/image_info.h 2008-10-15 15:38:28 +0000
+++ b/sql/backup/image_info.h 2008-11-13 19:34:18 +0000
@@ -1065,16 +1065,8 @@ obs::Obj* Image_info::Dbobj::materialize
m_obj_ptr= obs::materialize_trigger(db_name, name, ver, &sdata);
break;
case BSTREAM_IT_PRIVILEGE:
- {
- /*
- Here we undo the uniqueness suffix for grants.
- */
- String new_name;
- new_name.copy(*name);
- new_name.length(new_name.length() - UNIQUE_PRIV_KEY_LEN);
- m_obj_ptr= obs::materialize_db_grant(db_name, &new_name, ver, &sdata);
+ m_obj_ptr= obs::materialize_db_grant(db_name, name, ver, &sdata);
break;
- }
default: m_obj_ptr= NULL;
}
=== modified file 'sql/backup/kernel.cc'
--- a/sql/backup/kernel.cc 2008-11-06 18:39:27 +0000
+++ b/sql/backup/kernel.cc 2008-11-13 19:34:18 +0000
@@ -185,7 +185,8 @@ execute_backup_command(THD *thd, LEX *le
else
{
context.write_message(log_level::INFO, "Backing up selected databases");
- res= info->add_dbs(lex->db_list); // backup databases specified by user
+ /* Backup databases specified by user. */
+ res= info->add_dbs(thd, lex->db_list);
}
info->close(); // close catalogue after filling it with objects to backup
@@ -1905,24 +1906,30 @@ int bcat_create_item(st_bstream_image_he
if (item->type == BSTREAM_IT_TABLESPACE)
{
- // if the tablespace exists, there is nothing more to do
- if (obs::tablespace_exists(thd, sobj))
+ Obj *ts= obs::find_tablespace(thd, sobj->get_name());
+
+ if (ts)
{
- DBUG_PRINT("restore",(" skipping tablespace which exists"));
- return BSTREAM_OK;
- }
+ /*
+ A tablespace with the same name exists. We have to check if other
+ attributes are the same as they were.
+ */
- /*
- If there is a different tablespace with the same name then we can't
- re-create the original tablespace used by tables being restored. We report
- this and cancel restore process.
- */
+ if (obs::compare_tablespace_attributes(ts, sobj))
+ {
+ /* The tablespace is the same. There is nothing more to do. */
+ DBUG_PRINT("restore",(" skipping tablespace which exists"));
+ return BSTREAM_OK;
+ }
- Obj *ts= obs::is_tablespace(thd, sobj);
+ /*
+ A tablespace with the same name exists, but it has been changed
+ since backup. We can't re-create the original tablespace used by
+ tables being restored. We report this and cancel restore process.
+ */
- if (ts)
- {
- DBUG_PRINT("restore",(" tablespace has changed on the server - aborting"));
+ DBUG_PRINT("restore",
+ (" tablespace has changed on the server - aborting"));
info->m_ctx.fatal_error(ER_BACKUP_TS_CHANGE, desc);
return BSTREAM_ERROR;
}
@@ -1943,12 +1950,14 @@ int bcat_create_item(st_bstream_image_he
error handling work in WL#4384 with possible implementation
via a related bug report.
*/
- if (!obs::check_user_existence(thd, sobj->get_name()))
+ if (!obs::check_user_existence(thd, sobj))
{
- info->m_ctx.report_error(log_level::WARNING,
+ info->m_ctx.report_error(log_level::WARNING,
ER_BACKUP_GRANT_SKIPPED,
- create_stmt);
- return BSTREAM_OK;
+ obs::grant_get_grant_info(sobj)->ptr(),
+ obs::grant_get_user_name(sobj)->ptr(),
+ obs::grant_get_host_name(sobj)->ptr());
+ return BSTREAM_OK;
}
/*
We need to check the grant against the database list to ensure the
=== modified file 'sql/backup/logger.cc'
--- a/sql/backup/logger.cc 2008-10-27 13:06:21 +0000
+++ b/sql/backup/logger.cc 2008-11-13 19:34:18 +0000
@@ -52,10 +52,10 @@ int Logger::write_message(log_level::val
error.msg= sql_strdup(msg);
}
- sql_print_error(out);
+ sql_print_error("%s", out);
if (m_push_errors)
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- error_code, msg);
+ error_code, "%s", msg);
DBUG_PRINT("backup_log",("[ERROR] %s", out));
if (m_state == READY || m_state == RUNNING)
@@ -69,15 +69,15 @@ int Logger::write_message(log_level::val
return 0;
case log_level::WARNING:
- sql_print_warning(out);
+ sql_print_warning("%s", out);
if (m_push_errors)
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- error_code, msg);
+ error_code, "%s", msg);
DBUG_PRINT("backup_log",("[Warning] %s", out));
return 0;
case log_level::INFO:
- sql_print_information(out);
+ sql_print_information("%s", out);
DBUG_PRINT("backup_log",("[Info] %s", out));
return 0;
=== modified file 'sql/ddl_blocker.cc'
--- a/sql/ddl_blocker.cc 2008-08-19 15:35:29 +0000
+++ b/sql/ddl_blocker.cc 2008-11-13 19:34:18 +0000
@@ -44,7 +44,8 @@ void DDL_blocker_class::destroy_DDL_bloc
m_instance= NULL;
}
-DDL_blocker_class::DDL_blocker_class()
+DDL_blocker_class::DDL_blocker_class() :
+ m_blocker_thd(NULL)
{
pthread_mutex_init(&THR_LOCK_DDL_blocker, MY_MUTEX_INIT_FAST);
pthread_mutex_init(&THR_LOCK_DDL_is_blocked, MY_MUTEX_INIT_FAST);
@@ -64,6 +65,9 @@ DDL_blocker_class::~DDL_blocker_class()
pthread_cond_destroy(&COND_DDL_blocker);
pthread_cond_destroy(&COND_process_blocked);
pthread_cond_destroy(&COND_DDL_blocker_blocked);
+
+ DBUG_ASSERT(!DDL_blocked);
+ DBUG_ASSERT(!m_blocker_thd);
}
/**
@@ -124,17 +128,33 @@ my_bool DDL_blocker_class::check_DDL_blo
Check the ddl blocker condition. Rest until ddl blocker is released.
*/
pthread_mutex_lock(&THR_LOCK_DDL_is_blocked);
- thd->enter_cond(&COND_DDL_blocker, &THR_LOCK_DDL_is_blocked,
- "DDL blocker: DDL is blocked");
- while (DDL_blocked && !thd->DDL_exception && (ret == 0))
+
+ DBUG_ASSERT(m_blocker_thd && DDL_blocked ||
+ !m_blocker_thd && !DDL_blocked);
+
+ if (m_blocker_thd && m_blocker_thd == thd)
{
- if (thd->backup_wait_timeout == 0)
- ret = -1;
- else
- ret= pthread_cond_timedwait(&COND_DDL_blocker, &THR_LOCK_DDL_is_blocked,
- &ddl_timeout);
+ ret= 0;
+ pthread_mutex_unlock(&THR_LOCK_DDL_is_blocked);
}
- thd->exit_cond("DDL blocker: DDL is not blocked");
+ else
+ {
+ thd->enter_cond(&COND_DDL_blocker, &THR_LOCK_DDL_is_blocked,
+ "DDL blocker: DDL is blocked");
+ while (DDL_blocked &&
+ !thd->DDL_exception &&
+ ret == 0 &&
+ thd->killed == THD::NOT_KILLED)
+ {
+ if (thd->backup_wait_timeout == 0)
+ ret = -1;
+ else
+ ret= pthread_cond_timedwait(&COND_DDL_blocker, &THR_LOCK_DDL_is_blocked,
+ &ddl_timeout);
+ }
+ thd->exit_cond("DDL blocker: DDL is not blocked");
+ }
+
if (ret == 0)
{
start_DDL();
@@ -171,12 +191,24 @@ my_bool DDL_blocker_class::block_DDL(THD
Rest until another blocker is done.
*/
pthread_mutex_lock(&THR_LOCK_DDL_blocker_blocked);
+
+ if (m_blocker_thd && m_blocker_thd == thd)
+ {
+ /* DDL blocker has been already acquired by the given thd. */
+
+ pthread_mutex_unlock(&THR_LOCK_DDL_blocker);
+
+ DEBUG_SYNC(thd, "after_block_ddl");
+ DBUG_RETURN(TRUE);
+ }
+
thd->enter_cond(&COND_DDL_blocker_blocked, &THR_LOCK_DDL_blocker_blocked,
"DDL blocker: Checking block on blocker");
while (DDL_blocked)
pthread_cond_wait(&COND_DDL_blocker_blocked,
&THR_LOCK_DDL_blocker_blocked);
DDL_blocked= TRUE;
+ m_blocker_thd= thd;
thd->exit_cond("DDL blocker: Ok to block DDL");
/*
@@ -203,6 +235,7 @@ void DDL_blocker_class::unblock_DDL()
{
pthread_mutex_lock(&THR_LOCK_DDL_blocker);
DDL_blocked= FALSE;
+ m_blocker_thd= NULL;
pthread_cond_broadcast(&COND_DDL_blocker);
pthread_cond_signal(&COND_DDL_blocker_blocked);
pthread_mutex_unlock(&THR_LOCK_DDL_blocker);
=== modified file 'sql/ddl_blocker.h'
--- a/sql/ddl_blocker.h 2008-06-25 13:39:04 +0000
+++ b/sql/ddl_blocker.h 2008-11-13 19:34:18 +0000
@@ -5,6 +5,8 @@
*/
#include "mysql_priv.h"
+class THD;
+
/**
@class DDL_blocker_class
@@ -119,4 +121,6 @@ class DDL_blocker_class
my_bool DDL_blocked; ///< Is blocking operation running
int DDL_blocks; ///< Number of DDL operations in progress.
static DDL_blocker_class *m_instance; ///< instance var for singleton
+
+ THD *m_blocker_thd;
};
=== modified file 'sql/log.cc'
--- a/sql/log.cc 2008-11-06 18:39:27 +0000
+++ b/sql/log.cc 2008-11-13 19:34:18 +0000
@@ -917,8 +917,27 @@ bool Log_to_csv_event_handler::
if (history_data->command)
{
- if (table->field[ET_OBH_FIELD_COMMAND]->store(history_data->command,
- strlen(history_data->command), system_charset_info))
+ LEX_STRING cmd;
+ uint str_end_unused;
+
+ if (String::needs_conversion(0, thd->charset(), system_charset_info,
+ &str_end_unused))
+ {
+ if (thd->convert_string(&cmd, system_charset_info,
+ history_data->command,
+ strlen(history_data->command),
+ thd->charset()))
+ goto err;
+
+ }
+ else
+ {
+ cmd.str= history_data->command;
+ cmd.length= strlen(cmd.str);
+ }
+
+ if (table->field[ET_OBH_FIELD_COMMAND]->store(cmd.str, cmd.length,
+ system_charset_info))
goto err;
table->field[ET_OBH_FIELD_COMMAND]->set_notnull();
}
=== modified file 'sql/mysql_priv.h'
--- a/sql/mysql_priv.h 2008-11-06 18:39:27 +0000
+++ b/sql/mysql_priv.h 2008-11-13 19:34:18 +0000
@@ -1136,6 +1136,11 @@ void init_update_queries(void);
void free_max_user_conn(void);
pthread_handler_t handle_bootstrap(void *arg);
int mysql_execute_command(THD *thd);
+
+class Ed_result;
+
+bool mysql_execute_direct(THD *thd, const LEX_STRING *query, Ed_result *result);
+
bool do_command(THD *thd);
bool dispatch_command(enum enum_server_command command, THD *thd,
char* packet, uint packet_length);
@@ -2593,6 +2598,11 @@ inline void lex_string_set(LEX_STRING *l
lex_str->length= strlen(c_str);
}
+inline int lex_string_cmp(const LEX_STRING *s1, const LEX_STRING *s2)
+{
+ return strncmp(s1->str, s2->str, min(s1->length, s2->length));
+}
+
bool load_charset(MEM_ROOT *mem_root,
Field *field,
CHARSET_INFO *dflt_cs,
=== modified file 'sql/protocol.cc'
--- a/sql/protocol.cc 2008-10-20 09:16:47 +0000
+++ b/sql/protocol.cc 2008-11-13 19:34:18 +0000
@@ -440,6 +440,8 @@ void net_end_statement(THD *thd)
if (thd->main_da.is_sent)
return;
+ thd->main_da.is_sent= TRUE;
+
switch (thd->main_da.status()) {
case Diagnostics_area::DA_ERROR:
/* The query failed, send error to log and abort bootstrap. */
@@ -469,7 +471,6 @@ void net_end_statement(THD *thd)
0, 0, NULL);
break;
}
- thd->main_da.is_sent= TRUE;
DBUG_VOID_RETURN;
}
@@ -800,7 +801,6 @@ bool Protocol::store(I_List<i_string>* s
return store((char*) tmp.ptr(), len, tmp.charset());
}
-
/****************************************************************************
Functions to handle the simple (default) protocol where everything is
This protocol is the one that is used by default between the MySQL server
@@ -1417,3 +1417,448 @@ bool Protocol_binary::send_out_parameter
return FALSE;
}
+
+///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
+
+Ed_result::Ed_result(MEM_ROOT *mem_root) :
+ m_mem_root(mem_root),
+ m_cur_rs(NULL),
+ m_status(Diagnostics_area::DA_EMPTY),
+ m_server_status(0),
+ m_total_warn_count(0),
+ m_affected_rows(0),
+ m_last_insert_id(0),
+ m_sql_errno(0)
+{
+ m_message[0]= 0;
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+bool Ed_result::add_result_set(List<Item> *col_metadata)
+{
+ Ed_result_set *rs= Ed_result_set::create(m_mem_root, col_metadata);
+
+ if (!rs)
+ return TRUE;
+
+ m_cur_rs= rs;
+
+ return push_back(rs, m_mem_root) ? TRUE : FALSE;
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+bool Ed_result::on_end_statement(THD *thd)
+{
+ DBUG_ASSERT(m_status == Diagnostics_area::DA_EMPTY);
+
+ m_status= thd->main_da.status();
+
+ if (m_status == Diagnostics_area::DA_OK)
+ {
+ m_server_status= thd->main_da.server_status();
+ m_total_warn_count= thd->main_da.total_warn_count();
+ m_affected_rows= thd->main_da.affected_rows();
+ m_last_insert_id= thd->main_da.last_insert_id();
+
+ strmake(m_message, thd->main_da.message(), sizeof (m_message) - 1);
+ }
+ else if (m_status == Diagnostics_area::DA_EOF)
+ {
+ m_server_status= thd->main_da.server_status();
+ m_total_warn_count= thd->main_da.total_warn_count();
+ }
+ else if (m_status == Diagnostics_area::DA_ERROR)
+ {
+ m_sql_errno= thd->main_da.sql_errno();
+ strmake(m_message, thd->main_da.message(), sizeof (m_message) - 1);
+ }
+
+ List_iterator_fast<MYSQL_ERROR> it(thd->warn_list);
+ while (true)
+ {
+ MYSQL_ERROR *err= it++;
+
+ if (!err)
+ break;
+
+ MYSQL_ERROR *err_copy= new (m_mem_root) MYSQL_ERROR(m_mem_root, err);
+
+ if (!err_copy || m_warnings.push_back(err_copy, m_mem_root))
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
+
+Ed_result_set *
+Ed_result_set::create(MEM_ROOT *mem_root, List<Item> *col_metadata)
+{
+ Ed_result_set *rs= new (mem_root) Ed_result_set(mem_root);
+
+ if (!rs || rs->init(col_metadata))
+ return NULL;
+
+ return rs;
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+bool Ed_result_set::init(List<Item> *col_metadata)
+{
+ m_metadata= Ed_result_set_metadata::create(m_mem_root, col_metadata);
+
+ return m_metadata == NULL;
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+Ed_row *Ed_result_set::add_row()
+{
+ Ed_row *row= Ed_row::create(m_mem_root, m_metadata);
+
+ if (!row)
+ return NULL;
+
+ m_cur_row= row;
+
+ return m_data.push_back(row, m_mem_root) ? NULL : row;
+}
+
+///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
+
+Ed_result_set_metadata *
+Ed_result_set_metadata::create(MEM_ROOT *mem_root,
+ List<Item> *col_metadata)
+{
+ Ed_result_set_metadata *md= new (mem_root) Ed_result_set_metadata();
+
+ if (!md || md->init(mem_root, col_metadata))
+ return NULL;
+
+ return md;
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+bool Ed_result_set_metadata::init(MEM_ROOT *mem_root, List<Item> *col_metadata)
+{
+ if (!col_metadata)
+ return FALSE;
+
+ m_metadata= new (mem_root) Send_field[col_metadata->elements];
+
+ if (!m_metadata)
+ return TRUE;
+
+ m_num_columns= col_metadata->elements;
+
+ List_iterator_fast<Item> it(*col_metadata);
+
+ int i= 0;
+ for (Item *column= it++; column; column= it++)
+ column->make_field(&m_metadata[i]);
+
+ return FALSE;
+}
+
+///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
+
+Ed_row *Ed_row::create(MEM_ROOT *mem_root,
+ const Ed_result_set_metadata *metadata)
+{
+ DBUG_ASSERT(metadata);
+
+ Ed_row *row= new (mem_root) Ed_row(mem_root, metadata);
+
+ if (!row || row->init())
+ return NULL;
+
+ return row;
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+bool Ed_row::init()
+{
+ m_columns= new (m_mem_root) Ed_column[m_metadata->get_num_columns()];
+
+ return m_columns == NULL;
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+bool Ed_row::add_null()
+{
+ if (m_cur_column >= m_metadata->get_num_columns())
+ return TRUE;
+
+ ++m_cur_column;
+
+ return FALSE;
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+bool Ed_row::add_column(const void *data_ptr, int data_length)
+{
+ if (m_cur_column >= m_metadata->get_num_columns())
+ return TRUE;
+
+ m_columns[m_cur_column++].set_data(m_mem_root, data_ptr, data_length);
+
+ return FALSE;
+}
+
+///////////////////////////////////////////////////////////////////////////
+//
+// Protocol_local: a protocol for retrieving result sets from the server
+// locally.
+//
+///////////////////////////////////////////////////////////////////////////
+
+void Protocol_local::prepare_for_resend()
+{
+ DBUG_ASSERT(m_result);
+
+ Ed_result_set *rs= m_result->get_cur_result_set();
+
+ DBUG_ASSERT(rs);
+
+ rs->add_row();
+}
+
+bool Protocol_local::write()
+{
+ return FALSE;
+}
+
+bool Protocol_local::store_null()
+{
+ DBUG_ASSERT(m_result);
+
+ Ed_result_set *rs= m_result->get_cur_result_set();
+ Ed_row *row= rs->get_cur_row();
+ DBUG_ASSERT(row);
+
+ return row->add_null();
+}
+
+bool Protocol_local::store_string(const char *str,
+ int length,
+ CHARSET_INFO *src_cs,
+ CHARSET_INFO *dst_cs)
+{
+ DBUG_ASSERT(m_result);
+
+ Ed_result_set *rs= m_result->get_cur_result_set();
+ Ed_row *row= rs->get_cur_row();
+ DBUG_ASSERT(row);
+
+ /* 'dst_cs' is set 0 when client issued SET character_set_results = NULL */
+
+ if (!dst_cs ||
+ my_charset_same(src_cs, dst_cs) ||
+ src_cs == &my_charset_bin ||
+ dst_cs == &my_charset_bin)
+ {
+ return row->add_column(str, length);
+ }
+
+ /* Store with conversion */
+ uint dummy_errors;
+
+ if (convert->copy(str, length, src_cs, dst_cs, &dummy_errors))
+ return TRUE;
+
+ return row->add_column(convert->ptr(), convert->length());
+}
+
+bool Protocol_local::store_tiny(longlong value)
+{
+ Ed_result_set *rs= m_result->get_cur_result_set();
+ const Ed_result_set_metadata *md= rs->get_metadata();
+ Ed_row *row= rs->get_cur_row();
+
+ int cur_col_idx= row->get_cur_column();
+
+ const Send_field *col_md= md->get_column(cur_col_idx);
+
+ char v= (char) value;
+
+ return row->add_column(&v, 1);
+}
+
+bool Protocol_local::store_short(longlong value)
+{
+ Ed_result_set *rs= m_result->get_cur_result_set();
+ const Ed_result_set_metadata *md= rs->get_metadata();
+ Ed_row *row= rs->get_cur_row();
+
+ int cur_col_idx= row->get_cur_column();
+
+ const Send_field *col_md= md->get_column(cur_col_idx);
+
+ int16 v= (int16) value;
+
+ return row->add_column(&v, 2);
+}
+
+bool Protocol_local::store_long(longlong value)
+{
+ Ed_result_set *rs= m_result->get_cur_result_set();
+ const Ed_result_set_metadata *md= rs->get_metadata();
+ Ed_row *row= rs->get_cur_row();
+
+ int cur_col_idx= row->get_cur_column();
+
+ const Send_field *col_md= md->get_column(cur_col_idx);
+
+ int32 v= (int32) value;
+
+ return row->add_column(&v, 4);
+}
+
+bool Protocol_local::store_longlong(longlong value, bool unsigned_flag)
+{
+ Ed_result_set *rs= m_result->get_cur_result_set();
+ const Ed_result_set_metadata *md= rs->get_metadata();
+ Ed_row *row= rs->get_cur_row();
+
+ int cur_col_idx= row->get_cur_column();
+
+ const Send_field *col_md= md->get_column(cur_col_idx);
+
+ int64 v= (int64) value;
+
+ return row->add_column(&v, 8);
+}
+
+bool Protocol_local::store_decimal(const my_decimal *value)
+{
+ Ed_result_set *rs= m_result->get_cur_result_set();
+ const Ed_result_set_metadata *md= rs->get_metadata();
+ Ed_row *row= rs->get_cur_row();
+
+ int cur_col_idx= row->get_cur_column();
+
+ const Send_field *col_md= md->get_column(cur_col_idx);
+
+ char buf[DECIMAL_MAX_STR_LENGTH];
+ String str(buf, sizeof (buf), &my_charset_bin);
+ my_decimal2string(E_DEC_FATAL_ERROR, value, 0, 0, 0, &str);
+
+ return row->add_column(str.ptr(), str.length());
+}
+
+bool Protocol_local::store(const char *str,
+ size_t length,
+ CHARSET_INFO *src_cs)
+{
+ CHARSET_INFO *dst_cs= this->thd->variables.character_set_results;
+ return store_string(str, length, src_cs, dst_cs);
+}
+
+bool Protocol_local::store(const char *str,
+ size_t length,
+ CHARSET_INFO *src_cs,
+ CHARSET_INFO *dst_cs)
+{
+ return store_string(str, length, src_cs, dst_cs);
+}
+
+bool Protocol_local::store(MYSQL_TIME *time)
+{
+ Ed_result_set *rs= m_result->get_cur_result_set();
+ const Ed_result_set_metadata *md= rs->get_metadata();
+ Ed_row *row= rs->get_cur_row();
+
+ int cur_col_idx= row->get_cur_column();
+
+ const Send_field *col_md= md->get_column(cur_col_idx);
+
+ return row->add_column(time, sizeof (MYSQL_TIME));
+}
+
+bool Protocol_local::store_date(MYSQL_TIME *time)
+{
+ Ed_result_set *rs= m_result->get_cur_result_set();
+ const Ed_result_set_metadata *md= rs->get_metadata();
+ Ed_row *row= rs->get_cur_row();
+
+ int cur_col_idx= row->get_cur_column();
+
+ const Send_field *col_md= md->get_column(cur_col_idx);
+
+ return row->add_column(time, sizeof (MYSQL_TIME));
+}
+
+bool Protocol_local::store_time(MYSQL_TIME *time)
+{
+ Ed_result_set *rs= m_result->get_cur_result_set();
+ const Ed_result_set_metadata *md= rs->get_metadata();
+ Ed_row *row= rs->get_cur_row();
+
+ int cur_col_idx= row->get_cur_column();
+
+ const Send_field *col_md= md->get_column(cur_col_idx);
+
+ return row->add_column(time, sizeof (MYSQL_TIME));
+}
+
+bool Protocol_local::store(float value, uint32 decimals, String *buffer)
+{
+ Ed_result_set *rs= m_result->get_cur_result_set();
+ const Ed_result_set_metadata *md= rs->get_metadata();
+ Ed_row *row= rs->get_cur_row();
+
+ int cur_col_idx= row->get_cur_column();
+
+ const Send_field *col_md= md->get_column(cur_col_idx);
+
+ return row->add_column(&value, sizeof (float));
+}
+
+bool Protocol_local::store(double value, uint32 decimals, String *buffer)
+{
+ Ed_result_set *rs= m_result->get_cur_result_set();
+ const Ed_result_set_metadata *md= rs->get_metadata();
+ Ed_row *row= rs->get_cur_row();
+
+ int cur_col_idx= row->get_cur_column();
+
+ const Send_field *col_md= md->get_column(cur_col_idx);
+
+ return row->add_column(&value, sizeof (double));
+}
+
+bool Protocol_local::store(Field *field)
+{
+ if (field->is_null())
+ return store_null();
+ return field->send_binary(this);
+}
+
+bool Protocol_local::send_result_set_metadata(List<Item> *columns, uint)
+{
+ DBUG_ASSERT(m_result);
+
+ return m_result->add_result_set(columns);
+}
+
+bool Protocol_local::send_out_parameters(List<Item_param> *sp_params)
+{
+ return FALSE;
+}
+
+#ifdef EMBEDDED_LIBRARY
+void Protocol_local::remove_last_row()
+{ }
+#endif
=== modified file 'sql/protocol.h'
--- a/sql/protocol.h 2008-08-07 17:52:43 +0000
+++ b/sql/protocol.h 2008-11-13 19:34:18 +0000
@@ -114,6 +114,8 @@ public:
*/
};
virtual enum enum_protocol_type type()= 0;
+
+ virtual bool on_end_statement() { return FALSE; }
};
@@ -191,3 +193,286 @@ uchar *net_store_data(uchar *to,const uc
uchar *net_store_data(uchar *to,int32 from);
uchar *net_store_data(uchar *to,longlong from);
+///////////////////////////////////////////////////////////////////////////
+
+/**
+ Protocol_void: an implementation of Protocol, which just trashes results.
+*/
+
+class Protocol_void :public Protocol
+{
+public:
+ inline Protocol_void(THD *thd)
+ : Protocol(thd)
+ { }
+
+public:
+ virtual inline void prepare_for_resend() { }
+ virtual inline bool write() { return FALSE; }
+ virtual inline bool store_null() { return FALSE; }
+ virtual inline bool store_tiny(longlong) { return FALSE; }
+ virtual inline bool store_short(longlong) { return FALSE; }
+ virtual inline bool store_long(longlong) { return FALSE; }
+ virtual inline bool store_longlong(longlong, bool) { return FALSE; }
+ virtual inline bool store_decimal(const my_decimal *) { return FALSE; }
+ virtual inline bool store(const char *, size_t, CHARSET_INFO *)
+ { return FALSE; }
+ virtual inline bool store(const char *, size_t,
+ CHARSET_INFO *, CHARSET_INFO *)
+ { return FALSE; }
+ virtual inline bool store(MYSQL_TIME *) { return FALSE; }
+ virtual inline bool store_date(MYSQL_TIME *) { return FALSE; }
+ virtual inline bool store_time(MYSQL_TIME *) { return FALSE; }
+ virtual inline bool store(float, uint32, String *) { return FALSE; }
+ virtual inline bool store(double, uint32, String *) { return FALSE; }
+ virtual inline bool store(Field *) { return FALSE; }
+
+ virtual inline bool send_result_set_metadata(List<Item> *, uint)
+ { return FALSE; }
+ virtual inline bool send_out_parameters(List<Item_param> *) { return FALSE; }
+#ifdef EMBEDDED_LIBRARY
+ void remove_last_row() { }
+#endif
+ virtual enum enum_protocol_type type() { return PROTOCOL_TEXT; /* FIXME */ };
+};
+
+///////////////////////////////////////////////////////////////////////////
+
+/**
+ Ed_column -- a class representing a column data in a row. Used with
+ Ed_row and Protocol_local.
+*/
+class Ed_column : public LEX_STRING, public Sql_alloc
+{
+public:
+ inline Ed_column()
+ {
+ str= NULL;
+ length= 0;
+ }
+
+ inline void set_data(MEM_ROOT *mem_root, const void *p_str, int p_length)
+ {
+ str= (char *) memdup_root(mem_root, p_str, p_length);
+ length= p_length;
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////
+
+/**
+ Ed_result_set_metadata -- a class representing result set metadata. Used
+ with Ed_result_set and Protocol_local.
+*/
+
+class Ed_result_set_metadata : public Sql_alloc
+{
+public:
+ static Ed_result_set_metadata *create(MEM_ROOT *mem_root,
+ List<Item> *col_metadata);
+
+public:
+ inline int get_num_columns() const { return m_num_columns; }
+
+ inline const Send_field *get_column(int idx) const
+ { return &m_metadata[idx]; }
+
+private:
+ inline Ed_result_set_metadata() :
+ m_num_columns(0),
+ m_metadata(NULL)
+ { }
+
+private:
+ bool init(MEM_ROOT *mem_root, List<Item> *col_metadata);
+
+private:
+ int m_num_columns;
+ Send_field *m_metadata;
+};
+
+///////////////////////////////////////////////////////////////////////////
+
+/**
+ Ed_row -- a class representing a row in a result set. Used with
+ Ed_result_set and Protocol_local.
+*/
+class Ed_row : public Sql_alloc
+{
+public:
+ static Ed_row *create(MEM_ROOT *mem_root,
+ const Ed_result_set_metadata *metadata);
+
+public:
+ bool add_null();
+ bool add_column(const void *data_ptr, int data_length);
+
+public:
+ inline const Ed_result_set_metadata *get_metadata() const
+ { return m_metadata; }
+
+ inline const Ed_column *get_column(int idx) const
+ { return &m_columns[idx]; }
+
+ inline const Ed_column *operator [](int idx) const
+ { return get_column(idx); }
+
+ inline int get_cur_column() const { return m_cur_column; }
+
+private:
+ inline Ed_row(MEM_ROOT *mem_root,
+ const Ed_result_set_metadata *metadata) :
+ m_mem_root(mem_root),
+ m_metadata(metadata),
+ m_cur_column(0)
+ { }
+
+ bool init();
+
+private:
+ MEM_ROOT *m_mem_root;
+ const Ed_result_set_metadata *m_metadata;
+ Ed_column *m_columns;
+ int m_cur_column;
+};
+
+///////////////////////////////////////////////////////////////////////////
+
+/**
+ Ed_result_set -- a class representing one result set. Used with Ed_result
+ and Protocol_local.
+*/
+class Ed_result_set : public Sql_alloc
+{
+public:
+ static Ed_result_set *create(MEM_ROOT *mem_root,
+ List<Item> *col_metadata);
+
+private:
+ inline Ed_result_set(MEM_ROOT *mem_root) :
+ m_mem_root(mem_root),
+ m_metadata(NULL),
+ m_cur_row(NULL)
+ { }
+
+private:
+ bool init(List<Item> *col_metadata);
+
+public:
+ inline const Ed_result_set_metadata *get_metadata() const
+ { return m_metadata; }
+
+ inline List<Ed_row> *data() { return &m_data; }
+ inline Ed_row *get_cur_row() { return m_cur_row; }
+
+ Ed_row *add_row();
+
+private:
+ MEM_ROOT *m_mem_root;
+
+ Ed_result_set_metadata *m_metadata;
+ List<Ed_row> m_data;
+
+ Ed_row *m_cur_row;
+};
+
+///////////////////////////////////////////////////////////////////////////
+
+/*
+ Ed_result -- a class representing results for an SQL statement execution.
+ Used with Protocol_local.
+*/
+class Ed_result : public List<Ed_result_set>
+{
+public:
+ Ed_result(MEM_ROOT *mem_root);
+
+ inline ~Ed_result()
+ { }
+
+public:
+ inline Ed_result_set *get_cur_result_set() { return m_cur_rs; }
+
+ bool add_result_set(List<Item> *col_metadata);
+
+public:
+ bool on_end_statement(THD *thd);
+
+public:
+ inline uint get_status() const { return m_status; }
+ inline uint get_server_status() const { return m_server_status; }
+ inline uint get_total_warn_count() const { return m_total_warn_count; }
+ inline ha_rows get_affected_rows() const { return m_affected_rows; }
+ inline ulonglong get_last_insert_id() const { return m_last_insert_id; }
+ inline uint get_sql_errno() const { return m_sql_errno; }
+ inline const char *get_message() const { return m_message; }
+ inline List<MYSQL_ERROR> *get_warnings() { return &m_warnings; }
+
+private:
+ MEM_ROOT *m_mem_root;
+ Ed_result_set *m_cur_rs;
+
+private:
+ /*
+ NOTE: this section will be refactored / eliminated when warning
+ support in THD is refactored.
+ */
+ uint m_status;
+ uint m_server_status;
+ uint m_total_warn_count;
+ ha_rows m_affected_rows;
+ ulonglong m_last_insert_id;
+ uint m_sql_errno;
+ char m_message[MYSQL_ERRMSG_SIZE];
+ List<MYSQL_ERROR> m_warnings;
+};
+
+///////////////////////////////////////////////////////////////////////////
+
+/**
+ Protocol_local: a protocol for retrieving result sets from the server
+ locally.
+*/
+class Protocol_local :public Protocol
+{
+public:
+ inline Protocol_local(THD *thd, Ed_result *result)
+ : Protocol(thd),
+ m_result(result)
+ { }
+
+public:
+ virtual void prepare_for_resend();
+ virtual bool write();
+ virtual bool store_null();
+ virtual bool store_tiny(longlong from);
+ virtual bool store_short(longlong from);
+ virtual bool store_long(longlong from);
+ virtual bool store_longlong(longlong from, bool unsigned_flag);
+ virtual bool store_decimal(const my_decimal *);
+ virtual bool store(const char *from, size_t length, CHARSET_INFO *cs);
+ virtual bool store(const char *from, size_t length,
+ CHARSET_INFO *fromcs, CHARSET_INFO *tocs);
+ virtual bool store(MYSQL_TIME *time);
+ virtual bool store_date(MYSQL_TIME *time);
+ virtual bool store_time(MYSQL_TIME *time);
+ virtual bool store(float value, uint32 decimals, String *buffer);
+ virtual bool store(double value, uint32 decimals, String *buffer);
+ virtual bool store(Field *field);
+
+ virtual bool send_result_set_metadata(List<Item> *list, uint flags);
+ virtual bool send_out_parameters(List<Item_param> *sp_params);
+#ifdef EMBEDDED_LIBRARY
+ void remove_last_row();
+#endif
+ virtual enum enum_protocol_type type() { return PROTOCOL_TEXT; /* FIXME */ };
+ virtual bool on_end_statement() { return m_result->on_end_statement(thd); };
+
+private:
+ bool store_string(const char *str, int length,
+ CHARSET_INFO *src_cs, CHARSET_INFO *dst_cs);
+
+private:
+ Ed_result *m_result;
+};
+
=== modified file 'sql/share/errmsg.txt'
--- a/sql/share/errmsg.txt 2008-11-07 17:07:58 +0000
+++ b/sql/share/errmsg.txt 2008-11-13 19:34:18 +0000
@@ -6397,7 +6397,7 @@ ER_BACKUP_GET_META_PRIV
ER_BACKUP_CANT_RESTORE_PRIV
eng "Could not execute grant '%-.64s'."
ER_BACKUP_GRANT_SKIPPED
- eng "The grant '%-.64s' was skipped because the user does not exist."
+ eng "The grant '%-.64s' for the user '%-.64s'@'%-.64s' was skipped because the user does not exist."
ER_BACKUP_GRANT_WRONG_DB
eng "The grant '%-.64s' failed. Database not included in the backup image."
ER_BACKUP_LOGPATHS
=== modified file 'sql/si_objects.cc'
--- a/sql/si_objects.cc 2008-10-27 13:06:21 +0000
+++ b/sql/si_objects.cc 2008-11-13 19:34:18 +0000
@@ -26,333 +26,105 @@
#include "sp.h"
#include "sp_head.h" // for sp_add_to_query_tables().
-TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list); // defined in sql_show.cc
-
DDL_blocker_class *DDL_blocker= NULL;
+#define QUERY_BUFFER_SIZE 4096
+
///////////////////////////////////////////////////////////////////////////
namespace {
-// Helper methods
-
-/**
- Execute the SQL string passed.
-
- This is a private helper function to the implementation.
-*/
-int silent_exec(THD *thd, String *query)
-{
- Vio *save_vio= thd->net.vio;
-
- DBUG_PRINT("si_objects",("executing %s",query->c_ptr()));
-
- /*
- Note: the change net.vio idea taken from execute_init_command in
- sql_parse.cc
- */
- thd->net.vio= 0;
-
- thd->query= query->c_ptr();
- thd->query_length= query->length();
-
- thd->set_time();
- pthread_mutex_lock(&::LOCK_thread_count);
- thd->query_id= ::next_query_id();
- pthread_mutex_unlock(&::LOCK_thread_count);
-
- /*
- @todo The following is a work around for online backup and the DDL blocker.
- It should be removed when the generalized solution is in place.
- This is needed to ensure the restore (which uses DDL) is not blocked
- when the DDL blocker is engaged.
- */
- thd->DDL_exception= TRUE;
-
- /*
- Note: This is a copy and paste from the code in sql_parse.cc.
- See "case COM_QUERY:".
- */
- const char *found_semicolon= thd->query;
- char *packet_end= thd->query + thd->query_length;
- mysql_parse(thd, thd->query, thd->query_length, &found_semicolon);
- while (!thd->killed && found_semicolon && !thd->is_error())
- {
- char *next_packet= (char*) found_semicolon;
- /*
- Multiple queries exits, execute them individually
- */
- close_thread_tables(thd);
- ulong length= (ulong)(packet_end - next_packet);
-
- /* Remove garbage at start of query */
- while (my_isspace(thd->charset(), *next_packet) && length > 0)
- {
- next_packet++;
- length--;
- }
- pthread_mutex_lock(&LOCK_thread_count);
- thd->query_length= length;
- thd->query= next_packet;
- thd->query_id= next_query_id();
- thd->set_time(); /* Reset the query start time. */
- /* TODO: set thd->lex->sql_command to SQLCOM_END here */
- pthread_mutex_unlock(&LOCK_thread_count);
- mysql_parse(thd, next_packet, length, & found_semicolon);
- }
-
- close_thread_tables(thd);
+///////////////////////////////////////////////////////////////////////////
+//
+// Type identifiers in INFORMATION_SCHEMA.
+//
+///////////////////////////////////////////////////////////////////////////
- thd->net.vio= save_vio;
+const LEX_STRING IS_TYPE_TABLE= { C_STRING_WITH_LEN("BASE TABLE") };
+const LEX_STRING IS_TYPE_VIEW= { C_STRING_WITH_LEN("VIEW") };
- if (thd->is_error())
- {
- DBUG_PRINT("restore",
- ("error executing query %s!", thd->query));
- DBUG_PRINT("restore",("last error (%d): %s",thd->net.last_errno
- ,thd->net.last_error));
- return thd->net.last_errno ? (int)thd->net.last_errno : -1;
- }
-
- return 0;
-}
+///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
-/*
- This method gets the create statement for a procedure or function.
-*/
-bool serialize_routine(THD *thd,
- int type,
- String db_name,
- String r_name,
- String *string)
+void log_warnings(Ed_result *result)
{
- int ret= 0;
- sp_head *sp;
- sp_name *routine_name;
- LEX_STRING sql_mode;
- DBUG_ENTER("serialize_routine");
- DBUG_PRINT("serialize_routine", ("name: %s@%s", db_name.c_ptr(),
- r_name.c_ptr()));
-
- DBUG_ASSERT(type == TYPE_ENUM_PROCEDURE || type == TYPE_ENUM_FUNCTION);
- sp_cache **cache = type == TYPE_ENUM_PROCEDURE ?
- &thd->sp_proc_cache : &thd->sp_func_cache;
- LEX_STRING db;
- db.str= db_name.c_ptr();
- db.length= db_name.length();
- LEX_STRING name;
- name.str= r_name.c_ptr();
- name.length= r_name.length();
- routine_name= new sp_name(db, name, true);
- routine_name->init_qname(thd);
- if (type == TYPE_ENUM_PROCEDURE)
- thd->variables.max_sp_recursion_depth++;
- if ((sp= sp_find_routine(thd, type, routine_name, cache, FALSE)))
- {
- sys_var_thd_sql_mode::symbolic_mode_representation(thd,
- sp->m_sql_mode, &sql_mode);
- Stored_program_creation_ctx *sp_ctx= sp->get_creation_ctx();
+ List_iterator_fast<MYSQL_ERROR> it(*result->get_warnings());
- /*
- Prepend sql_mode command.
- */
- string->append("SET SQL_MODE = '");
- string->append(sql_mode.str);
- string->append("'; ");
-
- /*
- append character set client charset information
- */
- string->append("SET CHARACTER_SET_CLIENT = '");
- string->append(sp_ctx->get_client_cs()->csname);
- string->append("'; ");
-
- /*
- append collation_connection information
- */
- string->append("SET COLLATION_CONNECTION = '");
- string->append(sp_ctx->get_connection_cl()->name);
- string->append("'; ");
-
- /*
- append collation_connection information
- */
- string->append("SET COLLATION_DATABASE = '");
- string->append(sp_ctx->get_db_cl()->name);
- string->append("'; ");
-
- string->append(sp->m_defstr.str);
- }
- else
+ while (true)
{
- string->length(0);
- ret= TRUE;
- }
- if (type == TYPE_ENUM_PROCEDURE)
- thd->variables.max_sp_recursion_depth--;
- DBUG_RETURN(ret);
-}
-
-/*
- This method calls silent_exec() while saving the context
- information before the call and restoring after the call.
-
- If save_timezone, it also saves and restores the timezone.
-*/
-bool execute_with_ctx(THD *thd, String *query, bool save_timezone)
-{
- bool ret= false;
- ulong orig_sql_mode;
- CHARSET_INFO *orig_char_set_client;
- CHARSET_INFO *orig_coll_conn;
- CHARSET_INFO *orig_coll_db;
- Time_zone *tm_zone;
- DBUG_ENTER("Obj::execute_with_ctx()");
-
- /*
- Preserve SQL_MODE, CHARACTER_SET_CLIENT, COLLATION_CONNECTION,
- and COLLATION_DATABASE.
- */
- orig_sql_mode= thd->variables.sql_mode;
- orig_char_set_client= thd->variables.character_set_client;
- orig_coll_conn= thd->variables.collation_connection;
- orig_coll_db= thd->variables.collation_database;
-
- /*
- Preserve timezone.
- */
- if (save_timezone)
- tm_zone= thd->variables.time_zone;
-
- ret= silent_exec(thd, query);
-
- /*
- Restore SQL_MODE, CHARACTER_SET_CLIENT, COLLATION_CONNECTION,
- and COLLATION_DATABASE.
- */
- thd->variables.sql_mode= orig_sql_mode;
- thd->variables.character_set_client= orig_char_set_client;
- thd->variables.collation_connection= orig_coll_conn;
- thd->variables.collation_database= orig_coll_db;
-
- /*
- Restore timezone.
- */
- if (save_timezone)
- thd->variables.time_zone= tm_zone;
+ MYSQL_ERROR *err= it++;
- DBUG_RETURN(ret);
-}
-
-/*
- Drops an object.
+ if (!err)
+ break;
- obj_name is the name of the object e.g., DATABASE, PROCEDURE, etc.
- name1 is the db name (blank for database objects)
- name2 is the name of the object
-*/
-bool drop_object(THD *thd, const char *obj_name, String *name1, String *name2)
-{
- DBUG_ENTER("Obj::drop_object()");
- String cmd;
- cmd.length(0);
- cmd.append("DROP ");
- cmd.append(obj_name);
- cmd.append(" IF EXISTS ");
- if (name1 && (name1->length() > 0))
- {
- append_identifier(thd, &cmd, name1->c_ptr(), name1->length());
- cmd.append(".");
+ sql_print_information("SQL warning: code: %u; level: %d; msg: %s",
+ (unsigned int) err->code,
+ (int) err->level,
+ (const char *) err->msg);
}
- append_identifier(thd, &cmd, name2->c_ptr(), name2->length());
- DBUG_RETURN(silent_exec(thd, &cmd));
}
-/**
- Open given table in @c INFORMATION_SCHEMA database.
-
- This is a private helper function to the implementation.
-
- @param[in] thd Thread context
- @param[in] st Schema table enum
- @param[in] db_list List of databases for select condition
-
- @note: The select condition is designed to form a WHERE clause based on
- the database/schema column of the information_schema views. Most views have
- a database/schema column but for those that do not, you must ignore the
- selection condition by passing db_list = NULL.
+///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
- @retval TABLE* The schema table
-*/
-TABLE* open_schema_table(THD *thd, ST_SCHEMA_TABLE *st, List<LEX_STRING> *db_list)
+bool run_query(THD *thd, const LEX_STRING *query, Ed_result *result)
{
- TABLE *t;
- TABLE_LIST arg;
- my_bitmap_map *old_map;
-
- bzero( &arg, sizeof(TABLE_LIST) );
+ DBUG_ENTER("run_query()");
+ DBUG_PRINT("run_query",
+ ("query: %.*s",
+ (int) query->length, (const char *) query->str));
- // set context for create_schema_table call
- arg.schema_table= st;
- arg.alias= NULL;
- arg.select_lex= NULL;
+ ulong sql_mode_saved= thd->variables.sql_mode;
+ CHARSET_INFO *client_cs_saved= thd->variables.character_set_client;
+ CHARSET_INFO *results_cs_saved= thd->variables.character_set_results;
+ CHARSET_INFO *connection_cl_saved= thd->variables.collation_connection;
- t= create_schema_table(thd,&arg); // Note: callers must free t.
-
- if( !t ) return NULL; // error!
+ thd->variables.sql_mode= 0;
/*
- Temporarily set thd->lex->wild to NULL to keep st->fill_table
- happy.
+ Temporary tables should be ignored while looking for table structures.
+ Backup wants to backup ordinary tables, not temporary ones.
*/
- ::String *wild= thd->lex->wild;
- ::enum_sql_command command= thd->lex->sql_command;
-
- thd->lex->wild = NULL;
- thd->lex->sql_command = enum_sql_command(0);
+ TABLE *tmp_tables_saved= thd->temporary_tables;
+ thd->temporary_tables= NULL;
- // context for fill_table
- arg.table= t;
-
- old_map= tmp_use_all_columns(t, t->read_set);
+ /* A query is in UTF8 (internal character set). */
+ thd->variables.character_set_client= system_charset_info;
/*
- Create a selection condition only if db_list is defined.
+ Ed_results should be fetched without any conversion (in the original
+ character set) in order to preserve object definition query intact.
*/
- if (db_list)
- st->fill_table(thd, &arg, obs::create_db_select_condition(thd, t, db_list));
- else
- st->fill_table(thd, &arg, NULL);
+ thd->variables.character_set_results= &my_charset_bin;
+ thd->variables.collation_connection= system_charset_info;
+ thd->update_charset();
- tmp_restore_column_map(t->read_set, old_map);
+ bool rc= mysql_execute_direct(thd, query, result);
- // undo changes to thd->lex
- thd->lex->wild= wild;
- thd->lex->sql_command= command;
+ thd->variables.sql_mode= sql_mode_saved;
+ thd->variables.collation_connection= connection_cl_saved;
+ thd->variables.character_set_results= results_cs_saved;
+ thd->variables.character_set_client= client_cs_saved;
+ thd->update_charset();
- return t;
-}
+ thd->temporary_tables= tmp_tables_saved;
-/*
- Prepend the USE DB <obj> command.
-*/
-void prepend_db(THD *thd, String *serialization, String *db_name)
-{
- DBUG_ENTER("Obj::prepend_db()");
- /*
- prepend "USE db" statement
- */
- serialization->length(0);
- serialization->append("USE ");
- append_identifier(thd, serialization, db_name->c_ptr(), db_name->length());
- serialization->append("; ");
- DBUG_VOID_RETURN;
+ DBUG_RETURN(rc);
}
///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
struct Table_name_key
{
+public:
+ static uchar * get_key(const uchar *record,
+ size_t *key_length,
+ my_bool not_used __attribute__((unused)));
+
+ static void delete_key(void *data);
+
+public:
Table_name_key(const char *db_name_str,
uint db_name_length,
const char *table_name_str,
@@ -367,1270 +139,1235 @@ struct Table_name_key
key.append(table_name);
}
+public:
String db_name;
String table_name;
String key;
};
-uchar *
-get_table_name_key(const uchar *record,
- size_t *key_length,
- my_bool not_used __attribute__((unused)))
+///////////////////////////////////////////////////////////////////////////
+
+uchar *Table_name_key::get_key(const uchar *record,
+ size_t *key_length,
+ my_bool not_used __attribute__((unused)))
{
Table_name_key *tnk= (Table_name_key *) record;
*key_length= tnk->key.length();
return (uchar *) tnk->key.c_ptr_safe();
}
-void delete_table_name_key(void *data)
+///////////////////////////////////////////////////////////////////////////
+
+void Table_name_key::delete_key(void *data)
{
Table_name_key *tnk= (Table_name_key *) data;
delete tnk;
}
-}
-
+///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
-namespace obs {
-
-/**
- Build a where clause for list of databases.
-
- This method is used to help improve the efficiency of queries against
- information schema tables. It builds a condition tree of the form
- db_col IN ('a','b','c') where a,b,c are database names.
-
- @param[in] thd Thread context.
- @param[in] t The table to operate on.
- @param[in] db_list The list of databases in form List<LEX_STRING>
-
- @returns NULL if no databases in list or pointer to COND tree.
-*/
-COND *create_db_select_condition(THD *thd,
- TABLE *t,
- List<LEX_STRING> *db_list)
-{
- List<Item> in_db_list;
- List_iterator< ::LEX_STRING> it(*db_list);
- ::LEX_STRING *db;
- DBUG_ENTER("Obj::create_select_condition()");
+class Fmt
+{
+public:
+ Fmt(const char *format, ...);
- /*
- If no list of databases, just return NULL
- */
- if (!db_list->elements)
- DBUG_RETURN(NULL);
+public:
+ const char *str() const { return m_buffer; }
+ int length() const { return m_length; }
- /*
- Build an inclusion list in the form of 'a', 'b', etc.
- */
- while ((db= it++))
- {
- Item *db_name= new Item_string(db->str, db->length, system_charset_info);
- db_name->fix_fields(thd, &db_name);
- db_name->next= NULL;
- in_db_list.push_front(db_name);
- }
+private:
+ char m_buffer[QUERY_BUFFER_SIZE];
+ int m_length;
+};
- /*
- Build the compared field "table_schema" and link to temp table field.
- */
- Item *db_field= new Item_field(thd, thd->lex->current_context(), t->field[1]);
- in_db_list.push_front(db_field);
+///////////////////////////////////////////////////////////////////////////
- /*
- Build the in function item comparison and add list of databases.
- */
- Item_func_in *in_cond = new Item_func_in(in_db_list);
- in_cond->fix_fields(thd, (Item **)&in_cond);
- in_cond->fix_length_and_dec();
+Fmt::Fmt(const char *format, ...)
+{
+ va_list args;
- DBUG_RETURN(in_cond);
+ va_start(args, format);
+ m_length= my_vsnprintf(m_buffer, sizeof (m_buffer), format, args);
+ va_end(args);
}
///////////////////////////////////////////////////////////////////////////
-
-//
-// Implementation: object impl classes.
-//
-
///////////////////////////////////////////////////////////////////////////
-/**
- @class DatabaseObj
-
- This class provides an abstraction to a database object for creation and
- capture of the creation data.
-*/
-class DatabaseObj : public Obj
+class Out_stream
{
public:
- DatabaseObj(const String *db_name);
+ Out_stream(String *serialization) :
+ m_serialization(serialization)
+ { }
public:
- virtual bool materialize(uint serialization_version,
- const String *serialization);
-
- const String* get_name()
- { return &m_db_name; }
-
- const String *get_db_name()
- {
- return &m_db_name;
- }
-
-private:
- // These attributes are to be used only for serialization.
- String m_db_name;
-
- bool drop(THD *thd);
- virtual bool do_serialize(THD *thd, String *serialization);
- virtual bool do_execute(THD *thd);
+ Out_stream &operator <<(const char *query);
+ Out_stream &operator <<(const LEX_STRING *query);
+ Out_stream &operator <<(const String &query);
+ Out_stream &operator <<(const Fmt &query);
private:
- // These attributes are to be used only for materialization.
- String m_create_stmt;
+ String *m_serialization;
};
///////////////////////////////////////////////////////////////////////////
-/**
- @class TableObj
-
- This class provides an abstraction to a table object for creation and
- capture of the creation data.
-*/
-class TableObj : public Obj
+Out_stream &Out_stream::operator <<(const char *query)
{
-public:
- TableObj(const String *db_name,
- const String *table_name,
- bool table_is_view);
+ LEX_STRING str= { (char *) query, strlen(query) };
+ return Out_stream::operator <<(&str);
+}
-public:
- virtual bool materialize(uint serialization_version,
- const String *serialization);
+///////////////////////////////////////////////////////////////////////////
- const String* get_name()
- { return &m_table_name; }
+Out_stream &Out_stream::operator <<(const LEX_STRING *query)
+{
+ char chunk_buffer[QUERY_BUFFER_SIZE];
+ LEX_STRING chunk;
- const String *get_db_name()
- {
- return &m_db_name;
- }
+ chunk.str= chunk_buffer;
+ chunk.length= my_snprintf(chunk_buffer, QUERY_BUFFER_SIZE,
+ "%d %.*s\n",
+ (int) query->length,
+ (int) query->length,
+ (const char *) query->str);
-private:
- // These attributes are to be used only for serialization.
- String m_db_name;
- String m_table_name;
- bool m_table_is_view;
+ m_serialization->append(chunk.str, chunk.length);
- bool drop(THD *thd);
- virtual bool do_serialize(THD *thd, String *serialization);
- virtual bool do_execute(THD *thd);
+ return *this;
+}
-private:
- // These attributes are to be used only for materialization.
- String m_create_stmt;
+///////////////////////////////////////////////////////////////////////////
-private:
- bool serialize_table(THD *thd, String *serialization);
- bool serialize_view(THD *thd, String *serialization);
-};
+Out_stream &Out_stream::operator <<(const String &query)
+{
+ LEX_STRING str= { (char *) query.ptr(), query.length() };
+ return Out_stream::operator <<(&str);
+}
///////////////////////////////////////////////////////////////////////////
-/**
- @class TriggerObj
+Out_stream &Out_stream::operator <<(const Fmt &query)
+{
+ LEX_STRING str= { (char *) query.str(), query.length() };
+ return Out_stream::operator <<(&str);
+}
- This class provides an abstraction to a trigger object for creation and
- capture of the creation data.
-*/
-class TriggerObj : public Obj
+///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
+
+class In_stream
{
public:
- TriggerObj(const String *db_name,
- const String *trigger_name);
+ In_stream(uint serialization_version,
+ const String *serialization) :
+ m_serialization_version(serialization_version),
+ m_serialization(serialization),
+ m_read_ptr(m_serialization->ptr()),
+ m_end_ptr(m_serialization->ptr() + m_serialization->length())
+ { }
public:
- virtual bool materialize(uint serialization_version,
- const String *serialization);
-
- const String* get_name()
- { return &m_trigger_name; }
-
- const String *get_db_name()
- {
- return &m_db_name;
- }
-
-private:
- // These attributes are to be used only for serialization.
- String m_db_name;
- String m_trigger_name;
-
- bool drop(THD *thd);
- virtual bool do_serialize(THD *thd, String *serialization);
- virtual bool do_execute(THD *thd);
+ uint serialization_version() const { return m_serialization_version; }
+public:
+ bool next(LEX_STRING *chunk);
private:
- // These attributes are to be used only for materialization.
- String m_create_stmt;
+ uint m_serialization_version;
+ const String *m_serialization;
+ const char *m_read_ptr;
+ const char *m_end_ptr;
};
///////////////////////////////////////////////////////////////////////////
-/**
- @class StoredProcObj
-
- This class provides an abstraction to a stored procedure object for creation
- and capture of the creation data.
-*/
-class StoredProcObj : public Obj
+bool In_stream::next(LEX_STRING *chunk)
{
-public:
- StoredProcObj(const String *db_name,
- const String *stored_proc_name);
-
-public:
- virtual bool materialize(uint serialization_version,
- const String *serialization);
+ if (m_read_ptr >= m_end_ptr)
+ return TRUE;
- const String* get_name()
- { return &m_stored_proc_name; }
+ const char *delimiter_ptr=
+ my_strchr(system_charset_info, m_read_ptr, m_end_ptr, ' ');
- const String *get_db_name()
+ if (!delimiter_ptr)
{
- return &m_db_name;
+ m_read_ptr= m_end_ptr;
+ return TRUE;
}
-private:
- // These attributes are to be used only for serialization.
- String m_db_name;
- String m_stored_proc_name;
+ char buffer[STRING_BUFFER_USUAL_SIZE];
+ int n= delimiter_ptr - m_read_ptr;
- bool drop(THD *thd);
- virtual bool do_serialize(THD *thd, String *serialization);
- virtual bool do_execute(THD *thd);
+ memcpy(buffer, m_read_ptr, n);
+ buffer[n]= 0;
-private:
- // These attributes are to be used only for materialization.
- String m_create_stmt;
-};
+ chunk->str= (char *) delimiter_ptr + 1;
+ chunk->length= atoi(buffer);
+ m_read_ptr+= n /* chunk length */
+ + 1 /* delimiter (a space) */
+ + chunk->length /* chunk */
+ + 1; /* chunk delimiter (\n) */
+
+ return FALSE;
+}
+
+///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
-/**
- @class StoredFuncObj
+#define STR(x) x.length(), x.ptr()
+#define LXS(x) x->length, x->str
- This class provides an abstraction to a stored function object for creation
- and capture of the creation data.
-*/
-class StoredFuncObj : public Obj
+///////////////////////////////////////////////////////////////////////////
+
+}
+
+///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
+
+namespace obs {
+
+///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
+
+class Abstract_obj : public Obj
{
public:
- StoredFuncObj(const String *db_name,
- const String *stored_func_name);
+ virtual bool serialize(THD *thd, String *serialization);
-public:
+ virtual bool execute(THD *thd);
+
+protected:
virtual bool materialize(uint serialization_version,
const String *serialization);
- const String* get_name()
- { return &m_stored_func_name; }
+ virtual bool do_materialize(In_stream *is);
- const String *get_db_name()
- {
- return &m_db_name;
- }
+ /**
+ Primitive implementing @c serialize() method.
+ */
+ virtual bool do_serialize(THD *thd, Out_stream &os) = 0;
-private:
- // These attributes are to be used only for serialization.
- String m_db_name;
- String m_stored_func_name;
+protected:
+ MEM_ROOT m_mem_root; /* This mem-root is for keeping stmt list. */
+ List<String> m_stmt_lst;
- bool drop(THD *thd);
- virtual bool do_serialize(THD *thd, String *serialization);
- virtual bool do_execute(THD *thd);
+protected:
+ Abstract_obj();
+ virtual ~Abstract_obj();
private:
- // These attributes are to be used only for materialization.
- String m_create_stmt;
+ Abstract_obj(const Abstract_obj &);
+ Abstract_obj &operator =(const Abstract_obj &);
};
///////////////////////////////////////////////////////////////////////////
-#ifdef HAVE_EVENT_SCHEDULER
-/**
- @class EventObj
- This class provides an abstraction to a event object for creation and capture
- of the creation data.
-*/
-class EventObj : public Obj
+Abstract_obj::Abstract_obj()
{
-public:
- EventObj(const String *db_name,
- const String *event_name);
+ init_sql_alloc(&m_mem_root, ALLOC_ROOT_MIN_BLOCK_SIZE, 0);
+}
-public:
- virtual bool materialize(uint serialization_version,
- const String *serialization);
+///////////////////////////////////////////////////////////////////////////
- const String* get_name()
- { return &m_event_name; }
+Abstract_obj::~Abstract_obj()
+{
+ free_root(&m_mem_root, MYF(0));
+}
- const String *get_db_name()
- {
- return &m_db_name;
- }
+///////////////////////////////////////////////////////////////////////////
-private:
- // These attributes are to be used only for serialization.
- String m_db_name;
- String m_event_name;
+/**
+ Serialize object state into a buffer. The buffer actually should be a
+ binary buffer. String class is used here just because we don't have
+ convenient primitive for binary buffers.
- bool drop(THD *thd);
- virtual bool do_serialize(THD *thd, String *serialization);
- virtual bool do_execute(THD *thd);
+ Serialization format is opaque to the client, i.e. the client should
+ not make any assumptions about the format or the content of the
+ returned buffer.
-private:
- // These attributes are to be used only for materialization.
- String m_create_stmt;
-};
-#endif // HAVE_EVENT_SCHEDULER
+ Serialization format can be changed in the future versions. However,
+ the server must be able to materialize objects coded in any previous
+ formats.
-/**
- @class TablespaceObj
+ @param[in] thd Server thread context.
+ @param[in] serialization Buffer to serialize the object
- This class provides an abstraction to a user object for creation and
- capture of the creation data.
+ @return error status.
+ @retval FALSE on success.
+ @retval TRUE on error.
+
+ @note The real work is done inside @c do_serialize() primitive which should be
+ defied in derived classes. This method prepares appropriate context and calls
+ the primitive.
*/
-class TablespaceObj : public Obj
+
+bool Abstract_obj::serialize(THD *thd, String *serialization)
{
-public:
- TablespaceObj(const String *ts_name);
+ ulong saved_sql_mode= thd->variables.sql_mode;
+ thd->variables.sql_mode= 0;
-public:
- virtual bool do_serialize(THD *thd, String *serialization);
+ Out_stream os(serialization);
- virtual bool materialize(uint serialization_version,
- const String *serialization);
+ bool ret= do_serialize(thd, os);
- virtual bool do_execute(THD *thd);
+ thd->variables.sql_mode= saved_sql_mode;
- const String *describe();
+ return ret;
+}
- const String *build_serialization();
+///////////////////////////////////////////////////////////////////////////
+/**
+ Create the object in the database.
+
+ @param[in] thd Server thread context.
+
+ @return error status.
+ @retval FALSE on success.
+ @retval TRUE on error.
+*/
+
+bool Abstract_obj::execute(THD *thd)
+{
/*
- The get_db_name primitive is not used for tablespaces.
+ Save and update session sql_mode.
+
+ Although backup queries can reset it by itself, we should be able to
+ run at least "set" statement. Backup queries are generated using
+ sql_mode == 0, so we also should use it. If a query needs another
+ sql_mode (stored rountines), it will reset it once more.
*/
- const String *get_db_name() { return 0; }
- const String* get_name()
- { return &m_ts_name; }
+ ulong saved_sql_mode= thd->variables.sql_mode;
+ thd->variables.sql_mode= 0;
- const String* get_datafile()
- { return &m_datafile; }
+ /*
+ NOTE: other session variables are not preserved, so backup query must
+ take care to clean up the environment after itself.
+ */
- const String* get_comments()
- { return &m_comments; }
+ bool rc;
+ List_iterator_fast<String> it(m_stmt_lst);
+ while (true)
+ {
+ String *stmt= it++;
- const String* get_engine()
- { return &m_engine; }
+ if (!stmt)
+ break;
- void set_datafile(const String *df)
- { m_datafile.copy(*df); }
+ LEX_STRING query= { (char *) stmt->ptr(), stmt->length() };
- void set_comments(const String *c)
- { m_comments.copy(*c); }
+ rc= mysql_execute_direct(thd, &query, NULL);
- void set_engine(const String *engine)
- { m_engine.copy(*engine); }
+ /* Ignore warnings from materialization for now. */
-private:
- // These attributes are to be used only for serialization.
- String m_ts_name;
- String m_datafile;
- String m_comments;
- String m_engine;
+ if (rc)
+ break;
+ }
- // Drop is not supported by this object.
- bool drop(THD *thd)
- { return 0; }
+ thd->variables.sql_mode= saved_sql_mode;
-private:
- // These attributes are to be used only for materialization.
- String m_create_stmt;
-};
+ return rc == TRUE;
+}
-/**
- @class DbGrantObj
+///////////////////////////////////////////////////////////////////////////
- This class provides an abstraction to database-level grants.
- This class will permit the recording and replaying of these
- grants.
-*/
-class DbGrantObj : public Obj
+bool Abstract_obj::materialize(uint serialization_version,
+ const String *serialization)
{
-public:
- DbGrantObj(const String *grantee,
- const String *db_name,
- const String *priv_type);
+ m_stmt_lst.delete_elements();
-public:
- virtual bool materialize(uint serialization_version,
- const String *serialization);
+ In_stream is(serialization_version, serialization);
- const String* get_name()
- {
- return &m_name;
- }
+ return do_materialize(&is);
+}
- const String *get_db_name()
- {
- return &m_db_name;
- }
+///////////////////////////////////////////////////////////////////////////
- const String *get_priv_type()
+bool Abstract_obj::do_materialize(In_stream *is)
+{
+ while (true)
{
- return &m_priv_type;
- }
+ LEX_STRING stmt;
-protected:
- // These attributes are to be used only for serialization.
- String m_db_name; ///< corresponds with TABLE_SCHEMA in IS tables.
- String m_name; ///< name used to list in catalog.
- String m_grantee; ///< corresponds with GRANTEE in IS tables.
- String m_priv_type; ///< corresponds with PRIVILEGE_TYPE in IS tables.
+ if (is->next(&stmt))
+ break;
- bool drop(THD *thd) { return 0; }; // Drop not supported.
- virtual bool do_execute(THD *thd);
+ String *s= new (&m_mem_root) String();
-private:
- virtual bool do_serialize(THD *thd, String *serialization);
- // These attributes are to be used only for materialization.
- String m_grant_stmt;
-};
+ if (!s ||
+ s->copy(stmt.str, stmt.length, system_charset_info) ||
+ m_stmt_lst.push_back(s))
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
/**
- @class TblGrantObj
+ @class Database_obj
- This class provides an abstraction to table-level and routine-level grants.
- This class will permit the recording and replaying of these
- grants.
+ This class provides an abstraction to a database object for creation and
+ capture of the creation data.
*/
-class TblGrantObj : public DbGrantObj
+
+class Database_obj : public Abstract_obj
{
public:
- TblGrantObj(const String *grantee,
- const String *db_name,
- const String *table_name,
- const String *priv_type);
+ Database_obj(const char *db_name_str, int db_name_length);
public:
+ virtual inline const String *get_name() const { return &m_db_name; }
+ virtual inline const String *get_db_name() const { return &m_db_name; }
- const String *get_table_name()
- {
- return &m_table_name;
- }
+private:
+ /* These attributes are to be used only for serialization. */
+ String m_db_name;
-protected:
- // These attributes are to be used only for serialization.
- String m_table_name; ///< corresponds with TABLE_NAME in IS tables.
+ virtual bool do_serialize(THD *thd, Out_stream &os);
+};
+///////////////////////////////////////////////////////////////////////////
+
+/**
+ @class Table_obj
+
+ This class provides an abstraction to a table object for creation and
+ capture of the creation data.
+*/
+
+class Table_obj : public Abstract_obj
+{
+public:
+ Table_obj(const char *db_name_str, int db_name_length,
+ const char *table_name_str, int table_name_length);
+
+public:
+ virtual inline const String *get_name() const { return &m_table_name; }
+ virtual inline const String *get_db_name() const { return &m_db_name; }
private:
- virtual bool do_serialize(THD *thd, String *serialization);
+ /* These attributes are to be used only for serialization. */
+ String m_db_name;
+ String m_table_name;
- // These attributes are to be used only for materialization.
- String m_grant_stmt;
+ virtual bool do_serialize(THD *thd, Out_stream &os);
};
+///////////////////////////////////////////////////////////////////////////
+
/**
- @class ColGrantObj
+ @class View_obj
- This class provides an abstraction to column-level grants.
- This class will permit the recording and replaying of these
- grants.
+ This class provides an abstraction to a view object for creation and
+ capture of the creation data.
*/
-class ColGrantObj : public TblGrantObj
+
+class View_obj : public Abstract_obj
{
public:
- ColGrantObj(const String *grantee,
- const String *db_name,
- const String *table_name,
- const String *col_name,
- const String *priv_type);
+ View_obj(const char *db_name_str, int db_name_length,
+ const char *view_name_str, int view_name_length);
public:
-
- const String *get_col_name()
- {
- return &m_col_name;
- }
-
-protected:
- // These attributes are to be used only for serialization.
- String m_col_name; ///< corresponds with COLUMN_NAME in IS tables.
+ virtual inline const String *get_name() const { return &m_view_name; }
+ virtual inline const String *get_db_name() const { return &m_db_name; }
private:
- virtual bool do_serialize(THD *thd, String *serialization);
+ /* These attributes are to be used only for serialization. */
+ String m_db_name;
+ String m_view_name;
- // These attributes are to be used only for materialization.
- String m_grant_stmt;
+ virtual bool do_serialize(THD *thd, Out_stream &os);
};
///////////////////////////////////////////////////////////////////////////
-//
-// Implementation: iterator impl classes.
-//
+/**
+ @class Trigger_obj
-///////////////////////////////////////////////////////////////////////////
+ This class provides an abstraction to a trigger object for creation and
+ capture of the creation data.
+*/
-class InformationSchemaIterator : public Obj_iterator
+class Trigger_obj : public Abstract_obj
{
public:
- static bool prepare_is_table(
- THD *thd,
- TABLE **is_table,
- handler **ha,
- my_bitmap_map **orig_columns,
- enum_schema_tables is_table_idx,
- List<LEX_STRING> db_list);
-
-public:
- InformationSchemaIterator(THD *thd,
- TABLE *is_table,
- handler *ha,
- my_bitmap_map *orig_columns)
- :
- m_thd(thd),
- m_is_table(is_table),
- m_ha(ha),
- m_orig_columns(orig_columns)
- { }
-
- virtual ~InformationSchemaIterator();
+ Trigger_obj(const char *db_name_str, int db_name_length,
+ const char *trigger_name_str, int trigger_name_length);
public:
- virtual Obj *next();
-
-protected:
- virtual Obj *create_obj(TABLE *t) = 0;
- THD *m_thd;
+ virtual inline const String *get_name() const { return &m_trigger_name; }
+ virtual inline const String *get_db_name() const { return &m_db_name; }
private:
- TABLE *m_is_table;
- handler *m_ha;
- my_bitmap_map *m_orig_columns;
+ /* These attributes are to be used only for serialization. */
+ String m_db_name;
+ String m_trigger_name;
+ virtual bool do_serialize(THD *thd, Out_stream &os);
};
///////////////////////////////////////////////////////////////////////////
-class ObjIteratorDummyImpl : Obj_iterator
+/**
+ @class Stored_proc_obj
+
+ This class provides an abstraction to a stored procedure object for creation
+ and capture of the creation data.
+*/
+
+class Stored_proc_obj : public Abstract_obj
{
public:
- ObjIteratorDummyImpl() { return; }
- virtual ~ObjIteratorDummyImpl() { return; }
- virtual Obj *next() { return NULL; }
+ Stored_proc_obj(const char *db_name_str, int db_name_length,
+ const char *sp_name_str, int sp_name_length);
-protected:
- virtual Obj *create_obj(TABLE *t) { return NULL; }
+public:
+ virtual inline const String *get_name() const { return &m_sp_name; }
+ virtual inline const String *get_db_name() const { return &m_db_name; }
+private:
+ /* These attributes are to be used only for serialization. */
+ String m_db_name;
+ String m_sp_name;
+
+ virtual bool do_serialize(THD *thd, Out_stream &os);
};
///////////////////////////////////////////////////////////////////////////
-class DatabaseIterator : public InformationSchemaIterator
+
+/**
+ @class Stored_func_obj
+
+ This class provides an abstraction to a stored function object for creation
+ and capture of the creation data.
+*/
+
+class Stored_func_obj : public Abstract_obj
{
public:
- DatabaseIterator(THD *thd,
- TABLE *is_table,
- handler *ha,
- my_bitmap_map *orig_columns) :
- InformationSchemaIterator(thd, is_table, ha, orig_columns)
- { }
+ Stored_func_obj(const char *db_name_str, int db_name_length,
+ const char *sf_name_str, int sf_name_length);
-protected:
- virtual DatabaseObj *create_obj(TABLE *t);
+public:
+ virtual inline const String *get_name() const { return &m_sf_name; }
+ virtual inline const String *get_db_name() const { return &m_db_name; }
+
+private:
+ /* These attributes are to be used only for serialization. */
+ String m_db_name;
+ String m_sf_name;
+
+ virtual bool do_serialize(THD *thd, Out_stream &os);
};
///////////////////////////////////////////////////////////////////////////
-class DbTablesIterator : public InformationSchemaIterator
-{
-public:
- DbTablesIterator(THD *thd,
- const String *db_name,
- TABLE *is_table,
- handler *ha,
- my_bitmap_map *orig_columns) :
- InformationSchemaIterator(thd, is_table, ha, orig_columns)
- {
- m_db_name.copy(*db_name);
- }
+#ifdef HAVE_EVENT_SCHEDULER
-protected:
- virtual TableObj *create_obj(TABLE *t);
+/**
+ @class Event_obj
- virtual bool is_type_accepted(const String *type) const;
+ This class provides an abstraction to a event object for creation and capture
+ of the creation data.
+*/
- virtual bool is_engine_accepted(const String *engine) const;
+class Event_obj : public Abstract_obj
+{
+public:
+ Event_obj(const char *db_name_str, int db_name_length,
+ const char *event_name_str, int event_name_length);
- virtual TableObj *create_table_obj(const String *db_name,
- const String *table_name) const;
+public:
+ virtual inline const String *get_name() const { return &m_event_name; }
+ virtual inline const String *get_db_name() const { return &m_db_name; }
private:
+ /* These attributes are to be used only for serialization. */
String m_db_name;
+ String m_event_name;
+
+ virtual bool do_serialize(THD *thd, Out_stream &os);
};
+#endif // HAVE_EVENT_SCHEDULER
+
///////////////////////////////////////////////////////////////////////////
-class DbViewsIterator : public DbTablesIterator
+/**
+ @class Tablespace_obj
+
+ This class provides an abstraction to a user object for creation and
+ capture of the creation data.
+*/
+
+class Tablespace_obj : public Abstract_obj
{
public:
- DbViewsIterator(THD *thd,
- const String *db_name,
- TABLE *is_tables,
- handler *ha,
- my_bitmap_map *orig_columns)
- : DbTablesIterator(thd, db_name, is_tables, ha, orig_columns)
- { }
+ Tablespace_obj(const char *ts_name_str, int ts_name_length,
+ const char *comment_str, int comment_length,
+ const char *data_file_name_str, int data_file_name_length,
+ const char *engine_str, int engine_length);
+
+ Tablespace_obj(const char *ts_name_str, int ts_name_length);
+
+public:
+ virtual inline const String *get_name() const { return &m_ts_name; }
+ virtual inline const String *get_db_name() const { return NULL; }
+
+ const String *get_description();
protected:
- virtual bool is_type_accepted(const String *type) const;
+ virtual bool do_serialize(THD *thd, Out_stream &os);
- virtual bool is_engine_accepted(const String *engine) const
- {
- return true;
- }
+ virtual bool materialize(uint serialization_version,
+ const String *serialization);
- virtual TableObj *create_table_obj(const String *db_name,
- const String *table_name) const;
+private:
+ /* These attributes are to be used only for serialization. */
+ String m_ts_name;
+ String m_comment;
+ String m_data_file_name;
+ String m_engine;
+
+private:
+ String m_description;
};
///////////////////////////////////////////////////////////////////////////
-class DbTriggerIterator : public InformationSchemaIterator
+/**
+ @class Grant_obj
+
+ This class provides an abstraction to grants. This class will permit the
+ recording and replaying of these grants.
+*/
+
+class Grant_obj : public Abstract_obj
{
public:
- DbTriggerIterator(THD *thd,
- const String *db_name,
- TABLE *is_table,
- handler *ha,
- my_bitmap_map *orig_columns) :
- InformationSchemaIterator(thd, is_table, ha, orig_columns)
- {
- m_db_name.copy(*db_name);
- }
+ static void generate_unique_id(const String *user_name,
+ const String *host_name,
+ String *id);
+
+public:
+ Grant_obj(const char *id_str, int id_length);
+
+ Grant_obj(const char *user_name_str, int user_name_length,
+ const char *host_name_str, int host_name_length,
+ const char *priv_type_str, int priv_type_length,
+ const char *db_name_str, int db_name_length,
+ const char *table_name_str, int table_name_length,
+ const char *column_name_str, int column_name_length);
+
+public:
+ virtual bool do_materialize(In_stream *is);
+
+public:
+ virtual inline const String *get_name() const { return &m_id; }
+ virtual inline const String *get_db_name() const { return &m_id; }
+
+ inline const String *get_user_name() const { return &m_user_name; }
+ inline const String *get_host_name() const { return &m_host_name; }
+ inline const String *get_grant_info() const { return &m_grant_info; }
protected:
- virtual TriggerObj *create_obj(TABLE *t);
+ /* These attributes are to be used only for serialization. */
+ String m_id; ///< identify grant object (grantee is not unique).
+ String m_user_name;
+ String m_host_name;
+ String m_grant_info;
private:
- String m_db_name;
+ virtual bool do_serialize(THD *thd, Out_stream &os);
};
///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
-class DbStoredProcIterator : public InformationSchemaIterator
+template <typename T>
+T *create_row_set_iterator(THD *thd, const LEX_STRING *query)
{
-public:
- DbStoredProcIterator(THD *thd,
- const String *db_name,
- TABLE *is_table,
- handler *ha,
- my_bitmap_map *orig_columns) :
- InformationSchemaIterator(thd, is_table, ha, orig_columns)
+ Ed_result result(thd->mem_root);
+
+ if (run_query(thd, query, &result) ||
+ result.get_warnings()->elements > 0)
{
- m_db_name.copy(*db_name);
+ /* Should be no warnings. */
+ log_warnings(&result);
+ return NULL;
}
-protected:
- virtual Obj *create_obj(TABLE *t);
+ DBUG_ASSERT(result.elements == 1);
- virtual bool check_type(const String *sr_type) const;
+ Ed_result_set *rs= result.get_cur_result_set();
- virtual Obj *create_sr_object(const String *db_name,
- const String *sr_name);
+ DBUG_ASSERT(rs);
-private:
- String m_db_name;
-};
+ T *it= new T(rs);
-class DbGrantIterator : public InformationSchemaIterator
-{
-public:
- DbGrantIterator(THD *thd,
- const String *db_name,
- TABLE *is_table,
- handler *ha,
- my_bitmap_map *orig_columns) :
- InformationSchemaIterator(thd, is_table, ha, orig_columns)
- {
- m_db_name.copy(*db_name);
- }
+ return it ? it : NULL;
+}
+///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
+
+class Ed_result_set_iterator : public Obj_iterator
+{
protected:
- virtual DbGrantObj *create_obj(TABLE *t);
+ inline Ed_result_set_iterator(Ed_result_set *rs);
-private:
- String m_db_name;
+protected:
+ Ed_result_set *m_rs;
+ List_iterator_fast<Ed_row> m_row_it;
};
-class TblGrantIterator : public InformationSchemaIterator
-{
-public:
- TblGrantIterator(THD *thd,
- const String *db_name,
- TABLE *is_table,
- handler *ha,
- my_bitmap_map *orig_columns) :
- InformationSchemaIterator(thd, is_table, ha, orig_columns)
- {
- m_db_name.copy(*db_name);
- }
+///////////////////////////////////////////////////////////////////////////
-protected:
- virtual TblGrantObj *create_obj(TABLE *t);
+inline Ed_result_set_iterator::Ed_result_set_iterator(Ed_result_set *rs)
+ : m_rs(rs),
+ m_row_it(*rs->data())
+{ }
-private:
- String m_db_name;
-};
+///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
-class ColGrantIterator : public InformationSchemaIterator
+class Database_iterator : public Ed_result_set_iterator
{
public:
- ColGrantIterator(THD *thd,
- const String *db_name,
- TABLE *is_table,
- handler *ha,
- my_bitmap_map *orig_columns) :
- InformationSchemaIterator(thd, is_table, ha, orig_columns)
- {
- m_db_name.copy(*db_name);
- }
+ static Database_iterator *create(THD *thd);
-protected:
- virtual ColGrantObj *create_obj(TABLE *t);
+public:
+ inline Database_iterator(Ed_result_set *rs)
+ :Ed_result_set_iterator(rs)
+ { }
-private:
- String m_db_name;
+public:
+ virtual Obj *next();
};
-
///////////////////////////////////////////////////////////////////////////
-class DbStoredFuncIterator : public DbStoredProcIterator
+Database_iterator *Database_iterator::create(THD *thd)
{
-public:
- DbStoredFuncIterator(THD *thd,
- const String *db_name,
- TABLE *is_table,
- handler *ha,
- my_bitmap_map *orig_columns) :
- DbStoredProcIterator(thd, db_name, is_table, ha, orig_columns)
- { }
+ LEX_STRING query= { C_STRING_WITH_LEN(
+ "SELECT schema_name "
+ "FROM INFORMATION_SCHEMA.SCHEMATA "
+ "WHERE LCASE(schema_name) != 'mysql' AND "
+ "LCASE(schema_name) != 'information_schema'") };
-protected:
- virtual bool check_type(const String *sr_type) const;
+ return create_row_set_iterator<Database_iterator>(thd, &query);
+}
- virtual Obj *create_sr_object(const String *db_name,
- const String *sr_name);
-};
+///////////////////////////////////////////////////////////////////////////
+
+template
+Database_iterator *
+create_row_set_iterator<Database_iterator>(THD *thd, const LEX_STRING *query);
///////////////////////////////////////////////////////////////////////////
-#ifdef HAVE_EVENT_SCHEDULER
-class DbEventIterator : public InformationSchemaIterator
+
+Obj *Database_iterator::next()
{
-public:
- DbEventIterator(THD *thd,
- const String *db_name,
- TABLE *is_table,
- handler *ha,
- my_bitmap_map *orig_columns) :
- InformationSchemaIterator(thd, is_table, ha, orig_columns)
- {
- m_db_name.copy(*db_name);
- }
+ Ed_row *row= m_row_it++;
-protected:
- virtual EventObj *create_obj(TABLE *t);
+ if (!row)
+ return NULL;
-private:
- String m_db_name;
-};
-#endif
+ DBUG_ASSERT(row->get_metadata()->get_num_columns() == 1);
+ const Ed_column *db_name= row->get_column(0);
+ Database_obj *db= new Database_obj(db_name->str, db_name->length);
+
+ return db ? db : NULL;
+}
+
+///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
-class ViewBaseObjectsIterator : public Obj_iterator
+class Db_tables_iterator : public Ed_result_set_iterator
{
public:
- enum IteratorType
- {
- GET_BASE_TABLES,
- GET_BASE_VIEWS
- };
+ static Db_tables_iterator *create(THD *thd, const String *db_name);
public:
- virtual ~ViewBaseObjectsIterator();
+ inline Db_tables_iterator(Ed_result_set *rs)
+ :Ed_result_set_iterator(rs)
+ { }
public:
- virtual TableObj *next();
+ virtual Obj *next();
+};
-private:
- static ViewBaseObjectsIterator *create(THD *thd,
- const String *db_name,
- const String *view_name,
- IteratorType iterator_type );
+///////////////////////////////////////////////////////////////////////////
-private:
- ViewBaseObjectsIterator(HASH *table_names);
+Db_tables_iterator *Db_tables_iterator::create(THD *thd, const String *db_name)
+{
+ char query_buffer[QUERY_BUFFER_SIZE];
+ LEX_STRING query;
-private:
- HASH *m_table_names;
- uint m_cur_idx;
+ query.str= query_buffer;
+ query.length= my_snprintf(query_buffer, QUERY_BUFFER_SIZE,
+ "SELECT '%.*s', table_name "
+ "FROM INFORMATION_SCHEMA.TABLES "
+ "WHERE table_schema = '%.*s' AND table_type = '%.*s'",
+ (int) db_name->length(),
+ (const char *) db_name->ptr(),
+ (int) db_name->length(),
+ (const char *) db_name->ptr(),
+ (int) IS_TYPE_TABLE.length,
+ (const char *) IS_TYPE_TABLE.str);
-private:
- friend Obj_iterator *get_view_base_tables(THD *,
- const String *,
- const String *);
-
- friend Obj_iterator *get_view_base_views(THD *,
- const String *,
- const String *);
-};
+ return create_row_set_iterator<Db_tables_iterator>(thd, &query);
+}
///////////////////////////////////////////////////////////////////////////
-//
-// Implementation: InformationSchemaIterator class.
-//
+template
+Db_tables_iterator *
+create_row_set_iterator<Db_tables_iterator>(THD *thd, const LEX_STRING *query);
///////////////////////////////////////////////////////////////////////////
-bool InformationSchemaIterator::prepare_is_table(
- THD *thd,
- TABLE **is_table,
- handler **ha,
- my_bitmap_map **orig_columns,
- enum_schema_tables is_table_idx,
- List<LEX_STRING> db_list)
+Obj *Db_tables_iterator::next()
{
- ST_SCHEMA_TABLE *st= get_schema_table(is_table_idx);
- if (!(*is_table= open_schema_table(thd, st, &db_list)))
- return TRUE;
+ Ed_row *row= m_row_it++;
- *ha= (*is_table)->file;
+ if (!row)
+ return NULL;
- if (!*ha)
- {
- free_tmp_table(thd, *is_table);
- return TRUE;
- }
+ DBUG_ASSERT(row->get_metadata()->get_num_columns() == 2);
- *orig_columns=
- dbug_tmp_use_all_columns(*is_table, (*is_table)->read_set);
+ const Ed_column *db_name= row->get_column(0);
+ const Ed_column *table_name= row->get_column(1);
- if ((*ha)->ha_rnd_init(TRUE))
- {
- dbug_tmp_restore_column_map((*is_table)->read_set, *orig_columns);
- free_tmp_table(thd, *is_table);
- return TRUE;
- }
+ Table_obj *table= new Table_obj(db_name->str, db_name->length,
+ table_name->str, table_name->length);
- return FALSE;
+ return table ? table : NULL;
}
-InformationSchemaIterator::~InformationSchemaIterator()
+///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
+
+class Db_views_iterator : public Ed_result_set_iterator
{
- m_ha->ha_rnd_end();
+public:
+ static Db_views_iterator *create(THD *thd, const String *db_name);
- dbug_tmp_restore_column_map(m_is_table->read_set, m_orig_columns);
- free_tmp_table(m_thd, m_is_table);
-}
+public:
+ inline Db_views_iterator(Ed_result_set *rs)
+ :Ed_result_set_iterator(rs)
+ { }
+
+public:
+ virtual Obj *next();
+};
+
+///////////////////////////////////////////////////////////////////////////
-Obj *InformationSchemaIterator::next()
+Db_views_iterator *Db_views_iterator::create(THD *thd, const String *db_name)
{
- while (true)
- {
- if (m_ha->rnd_next(m_is_table->record[0]))
- return NULL;
+ char query_buffer[QUERY_BUFFER_SIZE];
+ LEX_STRING query;
- Obj *obj= create_obj(m_is_table);
+ query.str= query_buffer;
+ query.length= my_snprintf(query_buffer, QUERY_BUFFER_SIZE,
+ "SELECT '%.*s', table_name "
+ "FROM INFORMATION_SCHEMA.TABLES "
+ "WHERE table_schema = '%.*s' AND table_type = '%.*s'",
+ (int) db_name->length(),
+ (const char *) db_name->ptr(),
+ (int) db_name->length(),
+ (const char *) db_name->ptr(),
+ (int) IS_TYPE_VIEW.length,
+ (const char *) IS_TYPE_VIEW.str);
- if (obj)
- return obj;
- }
+ return create_row_set_iterator<Db_views_iterator>(thd, &query);
}
///////////////////////////////////////////////////////////////////////////
-//
-// Implementation: DatabaseIterator class.
-//
+template
+Db_views_iterator *
+create_row_set_iterator<Db_views_iterator>(THD *thd, const LEX_STRING *query);
///////////////////////////////////////////////////////////////////////////
-DatabaseObj* DatabaseIterator::create_obj(TABLE *t)
+Obj *Db_views_iterator::next()
{
- String name;
+ Ed_row *row= m_row_it++;
+
+ if (!row)
+ return NULL;
+
+ DBUG_ASSERT(row->get_metadata()->get_num_columns() == 2);
- t->field[1]->val_str(&name);
+ const Ed_column *db_name= row->get_column(0);
+ const Ed_column *view_name= row->get_column(1);
- DBUG_PRINT("DatabaseIterator::next", (" Found database %s", name.ptr()));
+ View_obj *view= new View_obj(db_name->str, db_name->length,
+ view_name->str, view_name->length);
- return new DatabaseObj(&name);
+ return view ? view : NULL;
}
///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
-//
-// Implementation: DbTablesIterator class.
-//
+class Db_trigger_iterator : public Ed_result_set_iterator
+{
+public:
+ static Db_trigger_iterator *create(THD *thd, const String *db_name);
+
+public:
+ inline Db_trigger_iterator(Ed_result_set *rs)
+ :Ed_result_set_iterator(rs)
+ { }
+
+public:
+ virtual Obj *next();
+};
///////////////////////////////////////////////////////////////////////////
-TableObj* DbTablesIterator::create_obj(TABLE *t)
+Db_trigger_iterator *Db_trigger_iterator::create(THD *thd, const String *db_name)
{
- String table_name;
- String db_name;
- String type;
- String engine;
+ char query_buffer[QUERY_BUFFER_SIZE];
+ LEX_STRING query;
- t->field[1]->val_str(&db_name);
- t->field[2]->val_str(&table_name);
- t->field[3]->val_str(&type);
- t->field[4]->val_str(&engine);
+ query.str= query_buffer;
+ query.length= my_snprintf(query_buffer, QUERY_BUFFER_SIZE,
+ "SELECT '%.*s', trigger_name "
+ "FROM INFORMATION_SCHEMA.TRIGGERS "
+ "WHERE trigger_schema = '%.*s'",
+ (int) db_name->length(),
+ (const char *) db_name->ptr(),
+ (int) db_name->length(),
+ (const char *) db_name->ptr());
- // Skip tables not from the given database.
+ return create_row_set_iterator<Db_trigger_iterator>(thd, &query);
+}
- if (db_name != m_db_name)
- return NULL;
+///////////////////////////////////////////////////////////////////////////
- // Skip tables/views depending on enumerate_views flag.
+template
+Db_trigger_iterator *
+create_row_set_iterator<Db_trigger_iterator>(THD *thd, const LEX_STRING *query);
- if (!is_type_accepted(&type))
- return NULL;
+///////////////////////////////////////////////////////////////////////////
- // TODO: actually, Backup Kernel needs to know also tables with
- // invalid/empty engines. It is required so that Backup Kernel can throw
- // a warning to the user.
+Obj *Db_trigger_iterator::next()
+{
+ Ed_row *row= m_row_it++;
- if (!is_engine_accepted(&engine))
+ if (!row)
return NULL;
- DBUG_PRINT("DbTablesIterator::next", (" Found table %s.%s",
- db_name.ptr(), table_name.ptr()));
+ DBUG_ASSERT(row->get_metadata()->get_num_columns() == 2);
- return create_table_obj(&db_name, &table_name);
-}
+ const Ed_column *db_name= row->get_column(0);
+ const Ed_column *trigger_name= row->get_column(1);
-bool DbTablesIterator::is_type_accepted(const String *type) const
-{
- return my_strcasecmp(system_charset_info,
- ((String *) type)->c_ptr_safe(), "BASE TABLE") == 0;
-}
+ Trigger_obj *trigger= new Trigger_obj(db_name->str, db_name->length,
+ trigger_name->str, trigger_name->length);
-bool DbTablesIterator::is_engine_accepted(const String *engine) const
-{
- return engine->length() > 0;
+ return trigger ? trigger : NULL;
}
-TableObj *DbTablesIterator::create_table_obj(const String *db_name,
- const String *table_name) const
+///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
+
+class Db_stored_proc_iterator : public Ed_result_set_iterator
{
- return new TableObj(db_name, table_name, false);
-}
+public:
+ static Db_stored_proc_iterator *create(THD *thd, const String *db_name);
-///////////////////////////////////////////////////////////////////////////
+public:
+ inline Db_stored_proc_iterator(Ed_result_set *rs)
+ :Ed_result_set_iterator(rs)
+ { }
-//
-// Implementation: DbViewsIterator class.
-//
+public:
+ virtual Obj *next();
+};
///////////////////////////////////////////////////////////////////////////
-bool DbViewsIterator::is_type_accepted(const String *type) const
+Db_stored_proc_iterator *
+Db_stored_proc_iterator::create(THD *thd, const String *db_name)
{
- return my_strcasecmp(system_charset_info,
- ((String *) type)->c_ptr_safe(), "VIEW") == 0;
-}
+ char query_buffer[QUERY_BUFFER_SIZE];
+ LEX_STRING query;
-TableObj *DbViewsIterator::create_table_obj(const String *db_name,
- const String *table_name) const
-{
- return new TableObj(db_name, table_name, true);
+ query.str= query_buffer;
+ query.length= my_snprintf(query_buffer, QUERY_BUFFER_SIZE,
+ "SELECT '%.*s', routine_name "
+ "FROM INFORMATION_SCHEMA.ROUTINES "
+ "WHERE routine_schema = '%.*s' AND routine_type = 'PROCEDURE'",
+ (int) db_name->length(),
+ (const char *) db_name->ptr(),
+ (int) db_name->length(),
+ (const char *) db_name->ptr());
+
+ return create_row_set_iterator<Db_stored_proc_iterator>(thd, &query);
}
///////////////////////////////////////////////////////////////////////////
-//
-// Implementation: DbTriggerIterator class.
-//
+template
+Db_stored_proc_iterator *
+create_row_set_iterator<Db_stored_proc_iterator>(THD *thd,
+ const LEX_STRING *query);
///////////////////////////////////////////////////////////////////////////
-TriggerObj *DbTriggerIterator::create_obj(TABLE *t)
+Obj *Db_stored_proc_iterator::next()
{
- String db_name;
- String trigger_name;
+ Ed_row *row= m_row_it++;
+
+ if (!row)
+ return NULL;
- t->field[1]->val_str(&db_name);
- t->field[2]->val_str(&trigger_name);
+ DBUG_ASSERT(row->get_metadata()->get_num_columns() == 2);
- // Skip triggers not from the given database.
+ const Ed_column *db_name= row->get_column(0);
+ const Ed_column *routine_name= row->get_column(1);
- if (db_name != m_db_name)
- return NULL;
+ Stored_proc_obj *sp= new Stored_proc_obj(db_name->str, db_name->length,
+ routine_name->str, routine_name->length);
- return new TriggerObj(&db_name, &trigger_name);
+ return sp ? sp : NULL;
}
///////////////////////////////////////////////////////////////////////////
-
-//
-// Implementation: DbStoredProcIterator class.
-//
-
///////////////////////////////////////////////////////////////////////////
-Obj *DbStoredProcIterator::create_obj(TABLE *t)
+class Db_stored_func_iterator : public Ed_result_set_iterator
{
- String db_name;
- String sr_name;
- String sr_type;
-
- t->field[2]->val_str(&db_name);
- t->field[3]->val_str(&sr_name);
- t->field[4]->val_str(&sr_type);
-
- // Skip stored procedure not from the given database.
+public:
+ static Db_stored_func_iterator *create(THD *thd, const String *db_name);
- if (db_name != m_db_name)
- return NULL;
+public:
+ inline Db_stored_func_iterator(Ed_result_set *rs)
+ :Ed_result_set_iterator(rs)
+ { }
- if (!check_type(&sr_type))
- return NULL;
+public:
+ virtual Obj *next();
+};
- return create_sr_object(&db_name, &sr_name);
-}
+///////////////////////////////////////////////////////////////////////////
-bool DbStoredProcIterator::check_type(const String *sr_type) const
+Db_stored_func_iterator *
+Db_stored_func_iterator::create(THD *thd, const String *db_name)
{
- return
- my_strcasecmp(system_charset_info,
- ((String *) sr_type)->c_ptr_safe(),
- "PROCEDURE") == 0;
-}
+ char query_buffer[QUERY_BUFFER_SIZE];
+ LEX_STRING query;
-Obj *DbStoredProcIterator::create_sr_object(const String *db_name,
- const String *sr_name)
-{
- return new StoredProcObj(db_name, sr_name);
+ query.str= query_buffer;
+ query.length= my_snprintf(query_buffer, QUERY_BUFFER_SIZE,
+ "SELECT '%.*s', routine_name "
+ "FROM INFORMATION_SCHEMA.ROUTINES "
+ "WHERE routine_schema = '%.*s' AND routine_type = 'FUNCTION'",
+ (int) db_name->length(),
+ (const char *) db_name->ptr(),
+ (int) db_name->length(),
+ (const char *) db_name->ptr());
+
+ return create_row_set_iterator<Db_stored_func_iterator>(thd, &query);
}
///////////////////////////////////////////////////////////////////////////
-//
-// Implementation: DbStoredFuncIterator class.
-//
+template
+Db_stored_func_iterator *
+create_row_set_iterator<Db_stored_func_iterator>(THD *thd,
+ const LEX_STRING *query);
///////////////////////////////////////////////////////////////////////////
-bool DbStoredFuncIterator::check_type(const String *sr_type) const
+Obj *Db_stored_func_iterator::next()
{
- return
- my_strcasecmp(system_charset_info,
- ((String *) sr_type)->c_ptr_safe(),
- "FUNCTION") == 0;
-}
+ Ed_row *row= m_row_it++;
-Obj *DbStoredFuncIterator::create_sr_object(const String *db_name,
- const String *sr_name)
-{
- return new StoredFuncObj(db_name, sr_name);
+ if (!row)
+ return NULL;
+
+ DBUG_ASSERT(row->get_metadata()->get_num_columns() == 2);
+
+ const Ed_column *db_name= row->get_column(0);
+ const Ed_column *routine_name= row->get_column(1);
+
+ Stored_func_obj *sf= new Stored_func_obj(db_name->str, db_name->length,
+ routine_name->str, routine_name->length);
+
+ return sf ? sf : NULL;
}
-#ifdef HAVE_EVENT_SCHEDULER
+///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
-//
-// Implementation: DbEventIterator class.
-//
+class Db_event_iterator : public Ed_result_set_iterator
+{
+public:
+ static Db_event_iterator *create(THD *thd, const String *db_name);
+
+public:
+ inline Db_event_iterator(Ed_result_set *rs)
+ :Ed_result_set_iterator(rs)
+ { }
+
+public:
+ virtual Obj *next();
+};
///////////////////////////////////////////////////////////////////////////
-EventObj *DbEventIterator::create_obj(TABLE *t)
+
+Db_event_iterator *
+Db_event_iterator::create(THD *thd, const String *db_name)
{
- String db_name;
- String event_name;
+#ifdef HAVE_EVENT_SCHEDULER
- t->field[1]->val_str(&db_name);
- t->field[2]->val_str(&event_name);
+ char query_buffer[QUERY_BUFFER_SIZE];
+ LEX_STRING query;
- // Skip event not from the given database.
+ query.str= query_buffer;
+ query.length= my_snprintf(query_buffer, QUERY_BUFFER_SIZE,
+ "SELECT '%.*s', event_name "
+ "FROM INFORMATION_SCHEMA.EVENTS "
+ "WHERE event_schema = '%.*s'",
+ (int) db_name->length(),
+ (const char *) db_name->ptr(),
+ (int) db_name->length(),
+ (const char *) db_name->ptr());
- if (db_name != m_db_name)
- return NULL;
+ return create_row_set_iterator<Db_event_iterator>(thd, &query);
+
+#else
+
+ return NULL;
- return new EventObj(&db_name, &event_name);
-}
#endif
+}
///////////////////////////////////////////////////////////////////////////
-//
-// Implementation: DbGrantIterator class.
-//
+#ifdef HAVE_EVENT_SCHEDULER
+template
+Db_event_iterator *
+create_row_set_iterator<Db_event_iterator>(THD *thd, const LEX_STRING *query);
+#endif
///////////////////////////////////////////////////////////////////////////
-DbGrantObj* DbGrantIterator::create_obj(TABLE *t)
+Obj *Db_event_iterator::next()
{
- String grantee; // corresponds with GRANTEE
- String db_name; // corresponds with TABLE_SCHEMA
- String priv_type; // corresponds with PRIVILEGE_TYPE
-
- t->field[0]->val_str(&grantee);
- t->field[2]->val_str(&db_name);
- t->field[3]->val_str(&priv_type);
-
- /*
- The fill method for SCHEMA_PRIVILEGES does not use the COND portion
- of the generic fill() method. Thus, we have to do the restriction here.
+#ifdef HAVE_EVENT_SCHEDULER
- Ensure the only rows sent back from iterator are the ones that match the
- database specified.
- */
- if (db_name == m_db_name)
- {
- DBUG_PRINT("DbGrantIterator::create", (" Found grant %s %s %s",
- db_name.ptr(), grantee.ptr(), priv_type.ptr()));
+ Ed_row *row= m_row_it++;
- /*
- Include grants for only users that exist at time of backup.
- */
- if (check_user_existence(m_thd, &grantee))
- return new DbGrantObj(&grantee, &db_name, &priv_type);
- else
- return NULL;
- }
- else
+ if (!row)
return NULL;
-}
-///////////////////////////////////////////////////////////////////////////
+ DBUG_ASSERT(row->get_metadata()->get_num_columns() == 2);
-//
-// Implementation: TblGrantIterator class.
-//
+ const Ed_column *db_name= row->get_column(0);
+ const Ed_column *event_name= row->get_column(1);
-///////////////////////////////////////////////////////////////////////////
+ Event_obj *event= new Event_obj(db_name->str, db_name->length,
+ event_name->str, event_name->length);
-TblGrantObj* TblGrantIterator::create_obj(TABLE *t)
-{
- String grantee; // corresponds with GRANTEE
- String db_name; // corresponds with TABLE_SCHEMA
- String tbl_name; // corresponds with TABLE_NAME
- String priv_type; // corresponds with PRIVILEGE_TYPE
-
- t->field[0]->val_str(&grantee);
- t->field[2]->val_str(&db_name);
- t->field[3]->val_str(&tbl_name);
- t->field[4]->val_str(&priv_type);
+ return event ? event : NULL;
- /*
- The fill method for TABLE_PRIVILEGES does not use the COND portion
- of the generic fill() method. Thus, we have to do the restriction here.
+#else
- Ensure the only rows sent back from iterator are the ones that match the
- database specified.
- */
- if (db_name == m_db_name)
- {
- DBUG_PRINT("TblGrantIterator::create", (" Found grant %s %s %s %s",
- db_name.ptr(), grantee.ptr(), tbl_name.ptr(), priv_type.ptr()));
+ return NULL;
- /*
- Include grants for only users that exist at time of backup.
- */
- if (check_user_existence(m_thd, &grantee))
- return new TblGrantObj(&grantee, &db_name, &tbl_name, &priv_type);
- else
- return NULL;
- }
- else
- return NULL;
+#endif
}
///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
-//
-// Implementation: ColGrantIterator class.
-//
+class View_base_obj_iterator : public Obj_iterator
+{
+public:
+ View_base_obj_iterator();
+ virtual ~View_base_obj_iterator();
+
+public:
+ virtual Obj *next();
+
+protected:
+ template <typename T>
+ static T *create(THD *thd, const String *db_name, const String *view_name);
+
+protected:
+ bool init(THD *thd, const String *db_name, const String *view_name);
+
+ virtual bool is_obj_accepted(TABLE_LIST *obj)= 0;
+ virtual Obj *create_obj(const String *db_name, const String *obj_name)= 0;
+
+private:
+ HASH *m_table_names;
+ uint m_cur_idx;
+};
///////////////////////////////////////////////////////////////////////////
-ColGrantObj* ColGrantIterator::create_obj(TABLE *t)
+template <typename T>
+T *View_base_obj_iterator::create(THD *thd,
+ const String *db_name,
+ const String *view_name)
{
- String grantee; // corresponds with GRANTEE
- String db_name; // corresponds with TABLE_SCHEMA
- String tbl_name; // corresponds with TABLE_NAME
- String col_name; // corresponds with COLUMN_NAME
- String priv_type; // corresponds with PRIVILEGE_TYPE
-
- t->field[0]->val_str(&grantee);
- t->field[2]->val_str(&db_name);
- t->field[3]->val_str(&tbl_name);
- t->field[4]->val_str(&col_name);
- t->field[5]->val_str(&priv_type);
+ T *it= new T();
- /*
- The fill method for COLUMN_PRIVILEGES does not use the COND portion
- of the generic fill() method. Thus, we have to do the restriction here.
-
- Ensure the only rows sent back from iterator are the ones that match the
- database specified.
- */
- if (db_name == m_db_name)
+ if (it->init(thd, db_name, view_name))
{
- DBUG_PRINT("ColGrantIterator::create", (" Found grant %s %s %s %s %s",
- db_name.ptr(), grantee.ptr(), tbl_name.ptr(), col_name.ptr(),
- priv_type.ptr()));
-
- /*
- Include grants for only users that exist at time of backup.
- */
- if (check_user_existence(m_thd, &grantee))
- return new ColGrantObj(&grantee, &db_name, &tbl_name,
- &col_name, &priv_type);
- else
- return NULL;
- }
- else
+ delete it;
return NULL;
+ }
+
+ return it;
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+View_base_obj_iterator::View_base_obj_iterator() :
+ m_table_names(NULL),
+ m_cur_idx(0)
+{
}
///////////////////////////////////////////////////////////////////////////
-//
-// Implementation: ViewBaseObjectsIterator class.
-//
+View_base_obj_iterator::~View_base_obj_iterator()
+{
+ if (!m_table_names)
+ return;
+
+ hash_free(m_table_names);
+ delete m_table_names;
+}
///////////////////////////////////////////////////////////////////////////
-ViewBaseObjectsIterator *
-ViewBaseObjectsIterator::create(THD *thd,
- const String *db_name,
- const String *view_name,
- IteratorType iterator_type)
+bool View_base_obj_iterator::init(THD *thd,
+ const String *db_name,
+ const String *view_name)
{
- uint table_count; // Passed to open_tables(). Not used.
+ DBUG_ASSERT(!m_table_names);
+
+ uint not_used; /* Passed to open_tables(). Not used. */
THD *my_thd= new THD();
my_thd->security_ctx= thd->security_ctx;
@@ -1646,20 +1383,20 @@ ViewBaseObjectsIterator::create(THD *thd
((String *) view_name)->c_ptr_safe(),
TL_READ);
- if (open_tables(my_thd, &tl, &table_count, 0))
+ if (open_tables(my_thd, &tl, ¬_used, MYSQL_OPEN_SKIP_TEMPORARY))
{
close_thread_tables(my_thd);
delete my_thd;
thd->store_globals();
- return NULL;
+ return TRUE;
}
- HASH *table_names = new HASH();
+ m_table_names = new HASH();
- hash_init(table_names, system_charset_info, 16, 0, 0,
- get_table_name_key,
- delete_table_name_key,
+ hash_init(m_table_names, system_charset_info, 16, 0, 0,
+ Table_name_key::get_key,
+ Table_name_key::delete_key,
MYF(0));
if (tl->view_tables)
@@ -1673,23 +1410,16 @@ ViewBaseObjectsIterator::create(THD *thd
new Table_name_key(tl2->db, tl2->db_length,
tl2->table_name, tl2->table_name_length);
- if (iterator_type == GET_BASE_TABLES && tl2->view ||
- iterator_type == GET_BASE_VIEWS && !tl2->view)
+ if (!is_obj_accepted(tl2) ||
+ hash_search(m_table_names,
+ (uchar *) tnk->key.c_ptr_safe(),
+ tnk->key.length()))
{
delete tnk;
continue;
}
- if (!hash_search(table_names,
- (uchar *) tnk->key.c_ptr_safe(),
- tnk->key.length()))
- {
- my_hash_insert(table_names, (uchar *) tnk);
- }
- else
- {
- delete tnk;
- }
+ my_hash_insert(m_table_names, (uchar *) tnk);
}
}
@@ -1698,22 +1428,12 @@ ViewBaseObjectsIterator::create(THD *thd
thd->store_globals();
- return new ViewBaseObjectsIterator(table_names);
-}
-
-ViewBaseObjectsIterator::ViewBaseObjectsIterator(HASH *table_names) :
- m_table_names(table_names),
- m_cur_idx(0)
-{
+ return FALSE;
}
-ViewBaseObjectsIterator::~ViewBaseObjectsIterator()
-{
- hash_free(m_table_names);
- delete m_table_names;
-}
+///////////////////////////////////////////////////////////////////////////
-TableObj *ViewBaseObjectsIterator::next()
+Obj *View_base_obj_iterator::next()
{
if (m_cur_idx >= m_table_names->records)
return NULL;
@@ -1723,223 +1443,189 @@ TableObj *ViewBaseObjectsIterator::next(
++m_cur_idx;
- return new TableObj(&tnk->db_name, &tnk->table_name, false);
+ return create_obj(&tnk->db_name, &tnk->table_name);
}
///////////////////////////////////////////////////////////////////////////
-
-//
-// Implementation: enumeration functions.
-//
-
///////////////////////////////////////////////////////////////////////////
-Obj_iterator *get_databases(THD *thd)
+class View_base_table_iterator : public View_base_obj_iterator
{
- TABLE *is_table;
- handler *ha;
- my_bitmap_map *orig_columns;
-
- if (InformationSchemaIterator::prepare_is_table(
- thd, &is_table, &ha, &orig_columns, SCH_SCHEMATA,
- thd->lex->db_list))
- return NULL;
-
- return new DatabaseIterator(thd, is_table, ha, orig_columns);
-}
+public:
+ static View_base_obj_iterator *
+ create(THD *thd, const String *db_name, const String *view_name)
+ {
+ return View_base_obj_iterator::create<View_base_table_iterator>
+ (thd, db_name, view_name);
+ }
-template <typename Iterator>
-Iterator *create_is_iterator(THD *thd,
- enum_schema_tables is_table_idx,
- const String *db_name)
-{
- TABLE *is_table;
- handler *ha;
- my_bitmap_map *orig_columns;
-
- LEX_STRING dbname;
- String db;
- db.copy(*db_name);
- thd->make_lex_string(&dbname, db.c_ptr(), db.length(), FALSE);
- List<LEX_STRING> db_list;
- db_list.push_back(&dbname);
-
- if (InformationSchemaIterator::prepare_is_table(
- thd, &is_table, &ha, &orig_columns, is_table_idx,
- db_list))
- return NULL;
+protected:
+ virtual bool is_obj_accepted(TABLE_LIST *obj)
+ { return !obj->view; }
- return new Iterator(thd, db_name, is_table, ha, orig_columns);
-}
+ virtual Obj *create_obj(const String *db_name, const String *obj_name)
+ {
+ return new Table_obj(db_name->ptr(), db_name->length(),
+ obj_name->ptr(), obj_name->length());
+ }
+};
-template
-DbTablesIterator *
-create_is_iterator<DbTablesIterator>(THD *, enum_schema_tables, const String *);
+///////////////////////////////////////////////////////////////////////////
template
-DbViewsIterator *
-create_is_iterator<DbViewsIterator>(THD *, enum_schema_tables, const String *);
+View_base_table_iterator *
+View_base_obj_iterator::create<View_base_table_iterator>(
+ THD *thd, const String *db_name, const String *view_name);
-template
-DbTriggerIterator *
-create_is_iterator<DbTriggerIterator>(THD *, enum_schema_tables, const String *);
+///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
-template
-DbStoredProcIterator *
-create_is_iterator<DbStoredProcIterator>(THD *, enum_schema_tables, const String *);
+class View_base_view_iterator : public View_base_obj_iterator
+{
+public:
+ static View_base_obj_iterator *
+ create(THD *thd, const String *db_name, const String *view_name)
+ {
+ return View_base_obj_iterator::create<View_base_view_iterator>
+ (thd, db_name, view_name);
+ }
-template
-DbStoredFuncIterator *
-create_is_iterator<DbStoredFuncIterator>(THD *, enum_schema_tables, const String *);
+protected:
+ virtual bool is_obj_accepted(TABLE_LIST *obj)
+ { return obj->view; }
-#ifdef HAVE_EVENT_SCHEDULER
-template
-DbEventIterator *
-create_is_iterator<DbEventIterator>(THD *, enum_schema_tables, const String *);
-#endif
+ virtual Obj *create_obj(const String *db_name, const String *obj_name)
+ {
+ return new View_obj(db_name->ptr(), db_name->length(),
+ obj_name->ptr(), obj_name->length());
+ }
+};
-template
-DbGrantIterator *
-create_is_iterator<DbGrantIterator>(THD *, enum_schema_tables, const String *);
+///////////////////////////////////////////////////////////////////////////
template
-TblGrantIterator *
-create_is_iterator<TblGrantIterator>(THD *, enum_schema_tables, const String *);
+View_base_view_iterator *
+View_base_obj_iterator::create<View_base_view_iterator>(
+ THD *thd, const String *db_name, const String *view_name);
-template
-ColGrantIterator *
-create_is_iterator<ColGrantIterator>(THD *, enum_schema_tables, const String *);
+///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
-Obj_iterator *get_db_tables(THD *thd, const String *db_name)
+class Grant_iterator : public Ed_result_set_iterator
{
- return create_is_iterator<DbTablesIterator>(thd, SCH_TABLES, db_name);
-}
+public:
+ static Grant_iterator *create(THD *thd, const String *db_name);
-Obj_iterator *get_db_views(THD *thd, const String *db_name)
-{
- return create_is_iterator<DbViewsIterator>(thd, SCH_TABLES, db_name);
-}
+public:
+ inline Grant_iterator(Ed_result_set *rs)
+ :Ed_result_set_iterator(rs)
+ { }
-Obj_iterator *get_db_triggers(THD *thd, const String *db_name)
-{
- return create_is_iterator<DbTriggerIterator>(thd, SCH_TRIGGERS, db_name);
-}
+public:
+ virtual Obj *next();
+};
-Obj_iterator *get_db_stored_procedures(THD *thd, const String *db_name)
-{
- return create_is_iterator<DbStoredProcIterator>(thd, SCH_PROCEDURES, db_name);
-}
+///////////////////////////////////////////////////////////////////////////
-Obj_iterator *get_db_stored_functions(THD *thd, const String *db_name)
+Grant_iterator *
+Grant_iterator::create(THD *thd, const String *db_name)
{
- return create_is_iterator<DbStoredFuncIterator>(thd, SCH_PROCEDURES, db_name);
-}
+ char query_buffer[QUERY_BUFFER_SIZE];
+ LEX_STRING query;
-Obj_iterator *get_db_events(THD *thd, const String *db_name)
-{
-#ifdef HAVE_EVENT_SCHEDULER
- return create_is_iterator<DbEventIterator>(thd, SCH_EVENTS, db_name);
-#else
- return (Obj_iterator *)new ObjIteratorDummyImpl;
-#endif
+ query.str= query_buffer;
+ query.length= my_snprintf(query_buffer, QUERY_BUFFER_SIZE,
+ "(SELECT user AS c1, "
+ "host AS c2, "
+ "privilege_type AS c3, "
+ "table_schema AS c4, "
+ "NULL AS c5, "
+ "NULL AS c6 "
+ "FROM INFORMATION_SCHEMA.SCHEMA_PRIVILEGES, mysql.user "
+ "WHERE table_schema = '%.*s' AND "
+ "grantee = CONCAT(\"'\", user, \"'@'\", host, \"'\")) "
+ "UNION "
+ "(SELECT user, host, privilege_type, table_schema, table_name, NULL "
+ "FROM INFORMATION_SCHEMA.TABLE_PRIVILEGES, mysql.user "
+ "WHERE table_schema = '%.*s' AND "
+ "grantee = CONCAT(\"'\", user, \"'@'\", host, \"'\")) "
+ "UNION "
+ "(SELECT user, host, privilege_type, table_schema, table_name, column_name "
+ "FROM INFORMATION_SCHEMA.COLUMN_PRIVILEGES, mysql.user "
+ "WHERE table_schema = '%.*s' AND "
+ "grantee = CONCAT(\"'\", user, \"'@'\", host, \"'\")) "
+ "ORDER BY c1 ASC, c2 ASC, c3 ASC, c4 ASC, c5 ASC, c6 ASC",
+ (int) db_name->length(),
+ (const char *) db_name->ptr(),
+ (int) db_name->length(),
+ (const char *) db_name->ptr(),
+ (int) db_name->length(),
+ (const char *) db_name->ptr());
+
+ return create_row_set_iterator<Grant_iterator>(thd, &query);
}
-/**
- GrantObjIterator constructor
+///////////////////////////////////////////////////////////////////////////
- This constructor initializes iterators for the grants supported.
- These include database-, table- and routine-, and column-level grants.
- The iterators return all of the grants for the database specified.
-*/
-GrantObjIterator::GrantObjIterator(THD *thd, const String *db_name)
-: Obj_iterator()
-{
- db_grants= create_is_iterator<DbGrantIterator>(thd,
- SCH_SCHEMA_PRIVILEGES,
- db_name);
- tbl_grants= create_is_iterator<TblGrantIterator>(thd,
- SCH_TABLE_PRIVILEGES,
- db_name);
- col_grants= create_is_iterator<ColGrantIterator>(thd,
- SCH_COLUMN_PRIVILEGES,
- db_name);
-}
-
-Obj *GrantObjIterator::next()
-{
- Obj *obj= 0;
- obj= db_grants->next();
- if (!obj)
- obj= tbl_grants->next();
- if (!obj)
- obj= col_grants->next();
- return obj;
-}
+Obj *Grant_iterator::next()
+{
+ Ed_row *row= m_row_it++;
-/**
- Creates a high-level iterator that iterates over database-, table-,
- routine-, and column-level privileges which shall permit a single
- iterator from the si_objects to retrieve all of the privileges for
- a given database.
+ if (!row)
+ return NULL;
- @param[IN] thd Current THD object
- @param[IN] db_name Name of database to get grants
+ DBUG_ASSERT(row->get_metadata()->get_num_columns() == 6);
- @Note The client is responsible for destroying the returned iterator.
+ const Ed_column *user_name= row->get_column(0);
+ const Ed_column *host_name= row->get_column(1);
+ const Ed_column *privilege_type= row->get_column(2);
+ const Ed_column *db_name= row->get_column(3);
+ const Ed_column *tbl_name= row->get_column(4);
+ const Ed_column *col_name= row->get_column(5);
+
+ LEX_STRING table_name= { C_STRING_WITH_LEN("") };
+ LEX_STRING column_name= { C_STRING_WITH_LEN("") };
+
+ if (tbl_name)
+ table_name= *tbl_name;
+
+ if (col_name)
+ column_name= *col_name;
+
+ Grant_obj *grant= new Grant_obj(user_name->str, user_name->length,
+ host_name->str, host_name->length,
+ privilege_type->str, privilege_type->length,
+ db_name->str, db_name->length,
+ table_name.str, table_name.length,
+ column_name.str, column_name.length);
- @return a pointer to an iterator object.
- @retval NULL in case of error.
-*/
-Obj_iterator *get_all_db_grants(THD *thd, const String *db_name)
-{
- return new GrantObjIterator(thd, db_name);
+ return grant ? grant : NULL;
}
///////////////////////////////////////////////////////////////////////////
-//
-// Implementation: dependency functions.
-//
+template
+Grant_iterator *
+create_row_set_iterator<Grant_iterator>(THD *thd, const LEX_STRING *query);
///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
-Obj_iterator* get_view_base_tables(THD *thd,
- const String *db_name,
- const String *view_name)
-{
- return ViewBaseObjectsIterator::create(
- thd, db_name, view_name, ViewBaseObjectsIterator::GET_BASE_TABLES);
-}
-
-Obj_iterator* get_view_base_views(THD *thd,
- const String *db_name,
- const String *view_name)
+Database_obj::Database_obj(const char *db_name_str, int db_name_length)
{
- return ViewBaseObjectsIterator::create(
- thd, db_name, view_name, ViewBaseObjectsIterator::GET_BASE_VIEWS);
+ m_db_name.copy(db_name_str, db_name_length, system_charset_info);
}
///////////////////////////////////////////////////////////////////////////
-//
-// Implementation: DatabaseObj class.
-//
-
-///////////////////////////////////////////////////////////////////////////
-
-DatabaseObj::DatabaseObj(const String *db_name)
-{
- m_db_name.copy(*db_name); // copy name string to newly allocated memory
-}
-
/**
Serialize the object.
This method produces the data necessary for materializing the object
on restore (creates object).
- @param[in] thd Thread context.
- @param[out] serialization The data needed to recreate this object.
+ @param[in] thd Thread context.
+ @param[out] os Output stream.
@note this method will return an error if the db_name is either
mysql or information_schema as these are not objects that
@@ -1949,315 +1635,435 @@ DatabaseObj::DatabaseObj(const String *d
@retval FALSE on success
@retval TRUE on error
*/
-bool DatabaseObj::do_serialize(THD *thd, String *serialization)
+
+bool Database_obj::do_serialize(THD *thd, Out_stream &os)
{
- HA_CREATE_INFO create;
- DBUG_ENTER("DatabaseObj::serialize()");
- DBUG_PRINT("DatabaseObj::serialize", ("name: %s", m_db_name.c_ptr()));
+ DBUG_ENTER("Database_obj::serialize()");
+ DBUG_PRINT("Database_obj::serialize",
+ ("name: %.*s",
+ m_db_name.length(), m_db_name.ptr()));
if (is_internal_db_name(&m_db_name))
{
- DBUG_PRINT("backup",(" Skipping internal database %s", m_db_name.c_ptr()));
+ DBUG_PRINT("backup",
+ (" Skipping internal database %.*s",
+ m_db_name.length(), m_db_name.ptr()));
+
DBUG_RETURN(TRUE);
}
- create.default_table_charset= system_charset_info;
- if (check_db_dir_existence(m_db_name.c_ptr()))
+ /* Run 'SHOW CREATE' query. */
+
+ char query_buffer[QUERY_BUFFER_SIZE];
+ LEX_STRING query;
+
+ query.str= query_buffer;
+ query.length= my_snprintf(query_buffer, QUERY_BUFFER_SIZE,
+ "SHOW CREATE DATABASE `%.*s`",
+ (int) m_db_name.length(),
+ (const char *) m_db_name.ptr());
+
+ Ed_result result(thd->mem_root);
+
+ if (run_query(thd, &query, &result) ||
+ result.get_warnings()->elements > 0)
{
- my_error(ER_BAD_DB_ERROR, MYF(0), m_db_name.c_ptr());
+ /*
+ There should be no warnings. A warning means that serialization has
+ failed.
+ */
+ log_warnings(&result);
DBUG_RETURN(TRUE);
}
- load_db_opt_by_name(thd, m_db_name.c_ptr(), &create);
+ /* Generate serialization. */
- serialization->append(STRING_WITH_LEN("CREATE DATABASE "));
- append_identifier(thd, serialization, m_db_name.c_ptr(), m_db_name.length());
+ DBUG_ASSERT(result.elements == 1);
- if (create.default_table_charset)
- {
- serialization->append(STRING_WITH_LEN(" DEFAULT CHARACTER SET "));
- serialization->append(create.default_table_charset->csname);
- if (!(create.default_table_charset->state & MY_CS_PRIMARY))
- {
- serialization->append(STRING_WITH_LEN(" COLLATE "));
- serialization->append(create.default_table_charset->name);
- }
- }
- DBUG_RETURN(FALSE);
-}
+ Ed_result_set *rs= result.get_cur_result_set();
-/**
- Materialize the serialization string.
+ DBUG_ASSERT(rs);
- This method saves serialization string into a member variable.
+ if (rs->data()->elements == 0)
+ DBUG_RETURN(TRUE);
- @param[in] serialization_version version number of this interface
- @param[in] serialization the string from serialize()
+ DBUG_ASSERT(rs->data()->elements == 1);
+
+ List_iterator_fast<Ed_row> row_it(*rs->data());
+ Ed_row *row= row_it++;
+
+ DBUG_ASSERT(row->get_metadata()->get_num_columns() == 2);
+
+ const Ed_column *create_stmt= row->get_column(1);
+
+ os <<
+ "SET @saved_cs_client = @@character_set_client" <<
+ "SET character_set_client = utf8" <<
+ Fmt("DROP DATABASE IF EXISTS `%.*s`", STR(m_db_name)) <<
+ create_stmt <<
+ "SET character_set_client = @saved_cs_client";
- @todo take serialization_version into account
- @returns Error status.
- @retval FALSE on success
- @retval TRUE on error
- */
-bool DatabaseObj::materialize(uint serialization_version,
- const String *serialization)
-{
- DBUG_ENTER("DatabaseObj::materialize()");
- m_create_stmt.copy(*serialization);
DBUG_RETURN(FALSE);
}
+///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
+
+Table_obj::Table_obj(const char *db_name_str, int db_name_length,
+ const char *table_name_str, int table_name_length)
+{
+ m_db_name.copy(db_name_str, db_name_length, system_charset_info);
+ m_table_name.copy(table_name_str, table_name_length, system_charset_info);
+}
+
+///////////////////////////////////////////////////////////////////////////
+
/**
- Create the object.
+ Serialize the object.
- This method uses serialization string in a query and executes it.
+ This method produces the data necessary for materializing the object
+ on restore (creates object).
- @param[in] thd Thread context.
+ @param[in] thd Thread context.
+ @param[out] os Output stream.
@returns Error status.
@retval FALSE on success
@retval TRUE on error
*/
-bool DatabaseObj::do_execute(THD *thd)
+
+bool Table_obj::do_serialize(THD *thd, Out_stream &os)
{
- DBUG_ENTER("DatabaseObj::execute()");
- drop(thd);
- DBUG_RETURN(silent_exec(thd, &m_create_stmt));
-}
+ DBUG_ENTER("Table_obj::serialize()");
+ DBUG_PRINT("Table_obj::serialize",
+ ("name: %.*s.%.*s",
+ m_db_name.length(), m_db_name.ptr(),
+ m_table_name.length(), m_table_name.ptr()));
-/**
- Drop the object.
+ char query_buffer[QUERY_BUFFER_SIZE];
+ LEX_STRING query;
- This method calls the silent_exec method to execute the query.
+ query.str= query_buffer;
+ query.length= my_snprintf(query_buffer, QUERY_BUFFER_SIZE,
+ "SHOW CREATE TABLE `%.*s`.`%.*s`",
+ (int) m_db_name.length(),
+ (const char *) m_db_name.ptr(),
+ (int) m_table_name.length(),
+ (const char *) m_table_name.ptr());
- @note This uses "IF EXISTS" and does not return error if
- object does not exist.
+ Ed_result result(thd->mem_root);
- @param[in] thd Thread context.
- @param[out] serialization the data needed to recreate this object
+ if (run_query(thd, &query, &result) ||
+ result.get_warnings()->elements > 0)
+ {
+ /*
+ There should be no warnings. A warning means that serialization has
+ failed.
+ */
+ log_warnings(&result);
+ DBUG_RETURN(TRUE);
+ }
- @returns Error status.
- @retval FALSE on success
- @retval TRUE on error
-*/
-bool DatabaseObj::drop(THD *thd)
-{
- DBUG_ENTER("DatabaseObj::drop()");
- DBUG_RETURN(drop_object(thd,
- (char *) "DATABASE",
- 0,
- &m_db_name));
-}
+ DBUG_ASSERT(result.elements == 1);
-///////////////////////////////////////////////////////////////////////////
+ Ed_result_set *rs= result.get_cur_result_set();
-//
-// Implementation: TableObj class.
-//
+ DBUG_ASSERT(rs);
-///////////////////////////////////////////////////////////////////////////
+ if (rs->data()->elements == 0)
+ DBUG_RETURN(TRUE);
-TableObj::TableObj(const String *db_name,
- const String *table_name,
- bool table_is_view) :
- m_table_is_view(table_is_view)
-{
- m_db_name.copy(*db_name);
- m_table_name.copy(*table_name);
-}
+ DBUG_ASSERT(rs->data()->elements == 1);
-bool TableObj::serialize_table(THD *thd, String *serialization)
-{
- return 0;
+ List_iterator_fast<Ed_row> row_it(*rs->data());
+ Ed_row *row= row_it++;
+
+ DBUG_ASSERT(row->get_metadata()->get_num_columns() == 2);
+
+ const Ed_column *create_stmt= row->get_column(1);
+
+ os <<
+ "SET @saved_cs_client = @@character_set_client" <<
+ "SET character_set_client = utf8" <<
+ Fmt("USE `%.*s`", STR(m_db_name)) <<
+ create_stmt <<
+ "SET character_set_client = @saved_cs_client";
+
+ DBUG_RETURN(FALSE);
}
-bool TableObj::serialize_view(THD *thd, String *serialization)
+///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
+
+View_obj::View_obj(const char *db_name_str, int db_name_length,
+ const char *view_name_str, int view_name_length)
{
- return 0;
+ m_db_name.copy(db_name_str, db_name_length, system_charset_info);
+ m_view_name.copy(view_name_str, view_name_length, system_charset_info);
}
-/**
- Serialize the object.
+///////////////////////////////////////////////////////////////////////////
- This method produces the data necessary for materializing the object
- on restore (creates object).
+static bool
+get_view_create_stmt(THD *thd,
+ View_obj *view,
+ const LEX_STRING **create_stmt,
+ const LEX_STRING **client_cs_name,
+ const LEX_STRING **connection_cl_name)
+{
+ char query_buffer[QUERY_BUFFER_SIZE];
+ LEX_STRING query;
- @param[in] thd Thread context.
- @param[out] serialization The data needed to recreate this object.
+ /* Get a create statement for a view. */
- @returns Error status.
- @retval FALSE on success
- @retval TRUE on error
-*/
-bool TableObj::do_serialize(THD *thd, String *serialization)
-{
- bool ret= 0;
- LEX_STRING tname, dbname;
- DBUG_ENTER("TableObj::serialize()");
- DBUG_PRINT("TableObj::serialize", ("name: %s@%s", m_db_name.c_ptr(),
- m_table_name.c_ptr()));
-
- prepend_db(thd, serialization, &m_db_name);
- tname.str= m_table_name.c_ptr();
- tname.length= m_table_name.length();
- dbname.str= m_db_name.c_ptr();
- dbname.length= m_db_name.length();
- Table_ident *name_id= new Table_ident(tname);
- name_id->db= dbname;
+ query.str= query_buffer;
+ query.length= my_snprintf(query_buffer, QUERY_BUFFER_SIZE,
+ "SHOW CREATE VIEW `%.*s`.`%.*s`",
+ (int) view->get_db_name()->length(),
+ (const char *) view->get_db_name()->ptr(),
+ (int) view->get_name()->length(),
+ (const char *) view->get_name()->ptr());
- /*
- Add the view to the table list and set the thd to look at views only.
- Note: derived from sql_yacc.yy.
- */
- thd->lex->select_lex.add_table_to_list(thd, name_id, NULL, 0);
- TABLE_LIST *table_list= (TABLE_LIST*)thd->lex->select_lex.table_list.first;
- thd->lex->sql_command = SQLCOM_SHOW_CREATE;
+ Ed_result result(thd->mem_root);
- /*
- Setup view specific variables and settings
- */
- if (m_table_is_view)
+ if (run_query(thd, &query, &result) ||
+ result.get_warnings()->elements > 0)
{
- thd->lex->only_view= 1;
- thd->lex->view_prepare_mode= TRUE; // use prepare mode
- table_list->skip_temporary= 1; // skip temporary tables
+ /*
+ There should be no warnings. A warning means that serialization has
+ failed.
+ */
+ log_warnings(&result);
+ return TRUE;
}
- /*
- Open the view and its base tables or views
- */
- if (open_normal_and_derived_tables(thd, table_list, 0)) {
- close_thread_tables(thd);
- thd->lex->select_lex.table_list.empty();
- DBUG_RETURN(TRUE);
- }
+ DBUG_ASSERT(result.elements == 1);
- /*
- Setup view specific variables and settings
- */
- if (m_table_is_view)
+ Ed_result_set *rs= result.get_cur_result_set();
+
+ DBUG_ASSERT(rs);
+
+ if (rs->data()->elements == 0)
+ return TRUE;
+
+ DBUG_ASSERT(rs->data()->elements == 1);
+
+ List_iterator_fast<Ed_row> row_it(*rs->data());
+ Ed_row *row= row_it++;
+
+ DBUG_ASSERT(row->get_metadata()->get_num_columns() == 4);
+
+ *create_stmt= row->get_column(1);
+ *client_cs_name= row->get_column(2);
+ *connection_cl_name= row->get_column(3);
+
+ return FALSE;
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+static bool
+dump_base_object_stubs(THD *thd,
+ Obj_iterator *base_object_it,
+ Out_stream &os)
+{
+ char base_obj_stmt_buf[QUERY_BUFFER_SIZE];
+ String base_obj_stmt(base_obj_stmt_buf,
+ sizeof (base_obj_stmt_buf),
+ system_charset_info);
+
+ while (true)
{
- View_creation_ctx *creation_ctx= table_list->view_creation_ctx;
+ Obj *base_obj= base_object_it->next();
- /*
- append character set client charset information
- */
- serialization->append("SET CHARACTER_SET_CLIENT = '");
- serialization->append(creation_ctx->get_client_cs()->csname);
- serialization->append("'; ");
+ if (!base_obj)
+ break;
+
+ /* Dump header of base obj stub. */
+
+ os <<
+ Fmt("CREATE DATABASE IF NOT EXISTS `%.*s`",
+ (int) base_obj->get_db_name()->length(),
+ (const char *) base_obj->get_db_name()->ptr());
+
+ base_obj_stmt.length(0);
+ base_obj_stmt.append(C_STRING_WITH_LEN("CREATE TABLE IF NOT EXISTS `"));
+ base_obj_stmt.append(*base_obj->get_db_name());
+ base_obj_stmt.append(C_STRING_WITH_LEN("`.`"));
+ base_obj_stmt.append(*base_obj->get_name());
+ base_obj_stmt.append(C_STRING_WITH_LEN("`("));
+
+ /* Get base obj structure. */
+
+ char query_buffer[QUERY_BUFFER_SIZE];
+ LEX_STRING query;
+
+ query.str= query_buffer;
+ query.length= my_snprintf(query_buffer, QUERY_BUFFER_SIZE,
+ "SHOW COLUMNS FROM `%.*s`.`%.*s`",
+ (int) base_obj->get_db_name()->length(),
+ (const char *) base_obj->get_db_name()->ptr(),
+ (int) base_obj->get_name()->length(),
+ (const char *) base_obj->get_name()->ptr());
+
+ Ed_result result(thd->mem_root);
+
+ if (run_query(thd, &query, &result) ||
+ result.get_warnings()->elements > 0)
+ {
+ /*
+ There should be no warnings. A warning means that serialization has
+ failed.
+ */
+ log_warnings(&result);
+ delete base_obj;
+ return TRUE;
+ }
+
+ DBUG_ASSERT(result.elements == 1);
+
+ Ed_result_set *rs= result.get_cur_result_set();
+ DBUG_ASSERT(rs);
+
+ /* Dump structure of base obj stub. */
+
+ List_iterator_fast<Ed_row> row_it(*rs->data());
+ bool first_column= TRUE;
+
+ while (true)
+ {
+ Ed_row *row= row_it++;
+
+ if (!row)
+ break;
+
+ DBUG_ASSERT(row->get_metadata()->get_num_columns() == 6);
+
+ const LEX_STRING *col_name= row->get_column(0);
+ const LEX_STRING *col_type= row->get_column(1);
+
+ if (first_column)
+ first_column= FALSE;
+ else
+ base_obj_stmt.append(C_STRING_WITH_LEN(", "));
+
+ base_obj_stmt.append(C_STRING_WITH_LEN("`"));
+ base_obj_stmt.append(col_name->str, col_name->length);
+ base_obj_stmt.append(C_STRING_WITH_LEN("` "));
+ base_obj_stmt.append(col_type->str, col_type->length);
+ }
- /*
- append collation_connection information
- */
- serialization->append("SET COLLATION_CONNECTION = '");
- serialization->append(creation_ctx->get_connection_cl()->name);
- serialization->append("'; ");
+ base_obj_stmt.append(C_STRING_WITH_LEN(") ENGINE = MyISAM"));
- table_list->view_db= dbname;
- serialization->set_charset(creation_ctx->get_client_cs());
+ os << base_obj_stmt;
+
+ delete base_obj;
}
- /*
- Get the create statement and close up shop.
- */
- ret= m_table_is_view ?
- view_store_create_info(thd, table_list, serialization) :
- store_create_info(thd, table_list, serialization, NULL,
- /* show_database */ TRUE);
- close_thread_tables(thd);
- serialization->set_charset(system_charset_info);
- thd->lex->select_lex.table_list.empty();
- DBUG_RETURN(FALSE);
+ return FALSE;
}
-/**
- Materialize the serialization string.
+///////////////////////////////////////////////////////////////////////////
- This method saves serialization string into a member variable.
+/**
+ Serialize the object.
- @param[in] serialization_version version number of this interface
- @param[in] serialization the string from serialize()
+ This method produces the data necessary for materializing the object
+ on restore (creates object).
- @todo take serialization_version into account
+ @param[in] thd Thread context.
+ @param[out] os Output stream.
@returns Error status.
@retval FALSE on success
@retval TRUE on error
- */
-bool TableObj::materialize(uint serialization_version,
- const String *serialization)
+*/
+bool View_obj::do_serialize(THD *thd, Out_stream &os)
{
- DBUG_ENTER("TableObj::materialize()");
- m_create_stmt.copy(*serialization);
- DBUG_RETURN(FALSE);
-}
+ DBUG_ENTER("View_obj::serialize()");
+ DBUG_PRINT("View_obj::serialize",
+ ("name: %.*s.%.*s",
+ m_db_name.length(), m_db_name.ptr(),
+ m_view_name.length(), m_view_name.ptr()));
-/**
- Create the object represented by TableObj in the database.
+ const LEX_STRING *create_stmt;
+ const LEX_STRING *client_cs_name;
+ const LEX_STRING *connection_cl_name;
- This method uses serialization string in a query and executes it.
+ if (get_view_create_stmt(thd, this, &create_stmt,
+ &client_cs_name, &connection_cl_name))
+ {
+ DBUG_RETURN(TRUE);
+ }
- @param[in] thd Thread context.
+ /* Dump the header. */
- @returns Error status.
- @retval FALSE on success
- @retval TRUE on error
-*/
-bool TableObj::do_execute(THD *thd)
-{
- DBUG_ENTER("TableObj::execute()");
- drop(thd);
- DBUG_RETURN(silent_exec(thd, &m_create_stmt));
-}
+ os <<
+ "SET @saved_cs_client = @@character_set_client" <<
+ "SET @saved_col_connection = @@collation_connection" <<
+ "SET character_set_client = utf8";
-/**
- Drop the object.
+ /* Get view dependencies. */
+
+ {
+ Obj_iterator *base_table_it=
+ get_view_base_tables(thd, &m_db_name, &m_view_name);
+
+ if (!base_table_it ||
+ dump_base_object_stubs(thd, base_table_it, os))
+ {
+ DBUG_RETURN(TRUE);
+ }
- This method calls the silent_exec method to execute the query.
+ delete base_table_it;
+ }
- @note This uses "IF EXISTS" and does not return error if
- object does not exist.
+ {
+ Obj_iterator *base_view_it=
+ get_view_base_views(thd, &m_db_name, &m_view_name);
- @param[in] thd Thread context.
- @param[out] serialization The data needed to recreate this object.
+ if (!base_view_it ||
+ dump_base_object_stubs(thd, base_view_it, os))
+ {
+ DBUG_RETURN(TRUE);
+ }
- @returns Error status.
- @retval FALSE on success
- @retval TRUE on error
-*/
-bool TableObj::drop(THD *thd)
-{
- DBUG_ENTER("TableObj::drop()");
- DBUG_RETURN(drop_object(thd,
- (char *) "TABLE",
- &m_db_name,
- &m_table_name));
+ delete base_view_it;
+ }
+
+ os <<
+ Fmt("USE `%.*s`", STR(m_db_name)) <<
+ Fmt("SET character_set_client = %.*s", LXS(client_cs_name)) <<
+ Fmt("SET collation_connection = %.*s", LXS(connection_cl_name)) <<
+ create_stmt <<
+ "SET character_set_client = @saved_cs_client" <<
+ "SET collation_connection = @saved_col_connection";
+
+ DBUG_RETURN(FALSE);
}
///////////////////////////////////////////////////////////////////////////
-
-//
-// Implementation: TriggerObj class.
-//
///////////////////////////////////////////////////////////////////////////
-TriggerObj::TriggerObj(const String *db_name,
- const String *trigger_name)
+Trigger_obj::Trigger_obj(const char *db_name_str, int db_name_length,
+ const char *trigger_name_str, int trigger_name_length)
{
- // copy strings to newly allocated memory
- m_db_name.copy(*db_name);
- m_trigger_name.copy(*trigger_name);
+ m_db_name.copy(db_name_str, db_name_length, system_charset_info);
+ m_trigger_name.copy(trigger_name_str, trigger_name_length,
+ system_charset_info);
}
+///////////////////////////////////////////////////////////////////////////
+
/**
Serialize the object.
This method produces the data necessary for materializing the object
on restore (creates object).
- @param[in] thd Thread handler.
- @param[out] serialization The data needed to recreate this object.
+ @param[in] thd Thread handler.
+ @param[out] os Output stream.
@note this method will return an error if the db_name is either
mysql or information_schema as these are not objects that
@@ -2267,190 +2073,101 @@ TriggerObj::TriggerObj(const String *db_
@retval FALSE on success
@retval TRUE on error
*/
-bool TriggerObj::do_serialize(THD *thd, String *serialization)
-{
- bool ret= false;
- uint num_tables;
- sp_name *trig_name;
- LEX_STRING trg_name;
- ulonglong trg_sql_mode;
- LEX_STRING trg_sql_mode_str;
- LEX_STRING trg_sql_original_stmt;
- LEX_STRING trg_client_cs_name;
- LEX_STRING trg_connection_cl_name;
- LEX_STRING trg_db_cl_name;
- CHARSET_INFO *trg_client_cs;
- DBUG_ENTER("TriggerObj::serialize()");
-
- DBUG_PRINT("TriggerObj::serialize", ("name: %s in %s",
- m_trigger_name.c_ptr(), m_db_name.c_ptr()));
-
- prepend_db(thd, serialization, &m_db_name);
- LEX_STRING db;
- db.str= m_db_name.c_ptr();
- db.length= m_db_name.length();
- LEX_STRING t_name;
- t_name.str= m_trigger_name.c_ptr();
- t_name.length= m_trigger_name.length();
- trig_name= new sp_name(db, t_name, true);
- trig_name->init_qname(thd);
- TABLE_LIST *lst= get_trigger_table(thd, trig_name);
- if (!lst)
- DBUG_RETURN(FALSE);
- alloc_mdl_locks(lst, thd->mem_root);
+bool Trigger_obj::do_serialize(THD *thd, Out_stream &os)
+{
+ DBUG_ENTER("Trigger_obj::do_serialize()");
+ DBUG_PRINT("Trigger_obj::do_serialize",
+ ("name: %.*s.%.*s",
+ m_db_name.length(), m_db_name.ptr(),
+ m_trigger_name.length(), m_trigger_name.ptr()));
DBUG_EXECUTE_IF("backup_fail_add_trigger", DBUG_RETURN(TRUE););
- if (open_tables(thd, &lst, &num_tables, 0))
- DBUG_RETURN(TRUE);
-
- DBUG_ASSERT(num_tables == 1);
- Table_triggers_list *triggers= lst->table->triggers;
- if (!triggers)
- DBUG_RETURN(FALSE);
-
- int trigger_idx= triggers->find_trigger_by_name(&trig_name->m_name);
- if (trigger_idx < 0)
- DBUG_RETURN(FALSE);
-
- triggers->get_trigger_info(thd,
- trigger_idx,
- &trg_name,
- &trg_sql_mode,
- &trg_sql_original_stmt,
- &trg_client_cs_name,
- &trg_connection_cl_name,
- &trg_db_cl_name);
- sys_var_thd_sql_mode::symbolic_mode_representation(thd,
- trg_sql_mode,
- &trg_sql_mode_str);
-
- /*
- prepend SQL Mode
- */
- serialization->append("SET SQL_MODE = '");
- serialization->append(trg_sql_mode_str.str);
- serialization->append("'; ");
-
- /*
- append character set client charset information
- */
- serialization->append("SET CHARACTER_SET_CLIENT = '");
- serialization->append(trg_client_cs_name.str);
- serialization->append("'; ");
-
- /*
- append collation_connection information
- */
- serialization->append("SET COLLATION_CONNECTION = '");
- serialization->append(trg_connection_cl_name.str);
- serialization->append("'; ");
- /*
- append collation_connection information
- */
- serialization->append("SET COLLATION_DATABASE = '");
- serialization->append(trg_db_cl_name.str);
- serialization->append("'; ");
-
- if (resolve_charset(trg_client_cs_name.str, NULL, &trg_client_cs))
- ret= false;
- else
- serialization->append(trg_sql_original_stmt.str);
- close_thread_tables(thd);
- thd->lex->select_lex.table_list.empty();
- serialization->set_charset(system_charset_info);
- DBUG_RETURN(ret);
-}
-
-/**
- Materialize the serialization string.
+ char query_buffer[QUERY_BUFFER_SIZE];
+ LEX_STRING query;
- This method saves serialization string into a member variable.
+ query.str= query_buffer;
+ query.length= my_snprintf(query_buffer, QUERY_BUFFER_SIZE,
+ "SHOW CREATE TRIGGER `%.*s`.`%.*s`",
+ (int) m_db_name.length(),
+ (const char *) m_db_name.ptr(),
+ (int) m_trigger_name.length(),
+ (const char *) m_trigger_name.ptr());
- @param[in] serialization_version version number of this interface
- @param[in] serialization the string from serialize()
+ Ed_result result(thd->mem_root);
- @todo take serialization_version into account
-
- @returns Error status.
- @retval FALSE on success
- @retval TRUE on error
-*/
-bool TriggerObj::materialize(uint serialization_version,
- const String *serialization)
-{
- DBUG_ENTER("TriggerObj::materialize()");
- m_create_stmt.copy(*serialization);
- DBUG_RETURN(0);
-}
+ if (run_query(thd, &query, &result) ||
+ result.get_warnings()->elements > 0)
+ {
+ /*
+ There should be no warnings. A warning means that serialization has
+ failed.
+ */
+ log_warnings(&result);
+ DBUG_RETURN(TRUE);
+ }
-/**
- Create the object.
+ DBUG_ASSERT(result.elements == 1);
- This method uses serialization string in a query and executes it.
+ Ed_result_set *rs= result.get_cur_result_set();
- @param[in] thd Thread context.
+ DBUG_ASSERT(rs);
- @returns Error status.
- @retval FALSE on success
- @retval TRUE on error
-*/
-bool TriggerObj::do_execute(THD *thd)
-{
- DBUG_ENTER("TriggerObj::execute()");
- drop(thd);
- DBUG_RETURN(execute_with_ctx(thd, &m_create_stmt, false));
-}
+ if (rs->data()->elements == 0)
+ DBUG_RETURN(TRUE);
-/**
- Drop the object.
+ DBUG_ASSERT(rs->data()->elements == 1);
- This method calls the silent_exec method to execute the query.
+ List_iterator_fast<Ed_row> row_it(*rs->data());
+ Ed_row *row= row_it++;
- @note This uses "IF EXISTS" and does not return error if
- object does not exist.
+ DBUG_ASSERT(row->get_metadata()->get_num_columns() == 6);
- @param[in] thd Thread context.
- @param[out] serialization The data needed to recreate this object.
+ const Ed_column *sql_mode= row->get_column(1);
+ const Ed_column *create_stmt= row->get_column(2);
+ const Ed_column *client_cs= row->get_column(3);
+ const Ed_column *connection_cl= row->get_column(4);
+ const Ed_column *db_cl= row->get_column(5);
+
+ os <<
+ "SET @saved_cs_client = @@character_set_client" <<
+ "SET @saved_col_connection = @@collation_connection" <<
+ "SET @saved_col_database = @@collation_database" <<
+ "SET character_set_client = utf8" <<
+ Fmt("USE `%.*s`", STR(m_db_name)) <<
+ Fmt("SET character_set_client = %.*s", LXS(client_cs)) <<
+ Fmt("SET collation_connection = %.*s", LXS(connection_cl)) <<
+ Fmt("SET collation_database = %.*s", LXS(db_cl)) <<
+ Fmt("SET sql_mode = '%.*s'", LXS(sql_mode)) <<
+ create_stmt <<
+ "SET character_set_client = @saved_cs_client" <<
+ "SET collation_connection = @saved_col_connection" <<
+ "SET collation_database = @saved_col_database";
- @returns Error status.
- @retval FALSE on success
- @retval TRUE on error
-*/
-bool TriggerObj::drop(THD *thd)
-{
- DBUG_ENTER("TriggerObj::drop()");
- DBUG_RETURN(drop_object(thd,
- (char *) "TRIGGER",
- &m_db_name,
- &m_trigger_name));
+ DBUG_RETURN(FALSE);
}
///////////////////////////////////////////////////////////////////////////
-
-//
-// Implementation: StoredProcObj class.
-//
-
///////////////////////////////////////////////////////////////////////////
-StoredProcObj::StoredProcObj(const String *db_name,
- const String *stored_proc_name)
+Stored_proc_obj::Stored_proc_obj(const char *db_name_str, int db_name_length,
+ const char *sp_name_str, int sp_name_length)
{
- // copy strings to newly allocated memory
- m_db_name.copy(*db_name);
- m_stored_proc_name.copy(*stored_proc_name);
+ m_db_name.copy(db_name_str, db_name_length, system_charset_info);
+ m_sp_name.copy(sp_name_str, sp_name_length, system_charset_info);
}
+///////////////////////////////////////////////////////////////////////////
+
/**
Serialize the object.
This method produces the data necessary for materializing the object
on restore (creates object).
- @param[in] thd Thread context.
- @param[out] serialization The data needed to recreate this object.
+ @param[in] thd Thread context.
+ @param[out] os Output stream.
@note this method will return an error if the db_name is either
mysql or information_schema as these are not objects that
@@ -2458,107 +2175,99 @@ StoredProcObj::StoredProcObj(const Strin
@returns Error status.
*/
-bool StoredProcObj::do_serialize(THD *thd, String *serialization)
-{
- bool ret= false;
- DBUG_ENTER("StoredProcObj::serialize()");
- DBUG_PRINT("StoredProcObj::serialize", ("name: %s in %s",
- m_stored_proc_name.c_ptr(), m_db_name.c_ptr()));
- prepend_db(thd, serialization, &m_db_name);
- ret= serialize_routine(thd, TYPE_ENUM_PROCEDURE, m_db_name,
- m_stored_proc_name, serialization);
- serialization->set_charset(system_charset_info);
- DBUG_RETURN(ret);
-}
-
-/**
- Materialize the serialization string.
-
- This method saves serialization string into a member variable.
- @param[in] serialization_version version number of this interface
- @param[in] serialization the string from serialize()
+bool Stored_proc_obj::do_serialize(THD *thd, Out_stream &os)
+{
+ DBUG_ENTER("Stored_proc_obj::do_serialize()");
+ DBUG_PRINT("Stored_proc_obj::do_serialize",
+ ("name: %.*s.%.*s",
+ m_db_name.length(), m_db_name.ptr(),
+ m_sp_name.length(), m_sp_name.ptr()));
+
+ char query_buffer[QUERY_BUFFER_SIZE];
+ LEX_STRING query;
+
+ query.str= query_buffer;
+ query.length= my_snprintf(query_buffer, QUERY_BUFFER_SIZE,
+ "SHOW CREATE PROCEDURE `%.*s`.`%.*s`",
+ (int) m_db_name.length(),
+ (const char *) m_db_name.ptr(),
+ (int) m_sp_name.length(),
+ (const char *) m_sp_name.ptr());
- @todo take serialization_version into account
+ Ed_result result(thd->mem_root);
- @returns Error status.
- @retval FALSE on success
- @retval TRUE on error
-*/
-bool StoredProcObj::materialize(uint serialization_version,
- const String *serialization)
-{
- DBUG_ENTER("StoredProcObj::materialize()");
- m_create_stmt.copy(*serialization);
- DBUG_RETURN(0);
-}
+ if (run_query(thd, &query, &result) ||
+ result.get_warnings()->elements > 0)
+ {
+ /*
+ There should be no warnings. A warning means that serialization has
+ failed.
+ */
+ log_warnings(&result);
+ DBUG_RETURN(TRUE);
+ }
-/**
- Create the object.
+ DBUG_ASSERT(result.elements == 1);
- This method uses serialization string in a query and executes it.
+ Ed_result_set *rs= result.get_cur_result_set();
- @param[in] thd current thread
+ DBUG_ASSERT(rs);
- @returns Error status.
- @retval FALSE on success
- @retval TRUE on error
-*/
-bool StoredProcObj::do_execute(THD *thd)
-{
- DBUG_ENTER("StoredProcObj::execute()");
- drop(thd);
- DBUG_RETURN(execute_with_ctx(thd, &m_create_stmt, false));
-}
+ if (rs->data()->elements == 0)
+ DBUG_RETURN(TRUE);
-/**
- Drop the object.
+ DBUG_ASSERT(rs->data()->elements == 1);
- This method calls the silent_exec method to execute the query.
+ List_iterator_fast<Ed_row> row_it(*rs->data());
+ Ed_row *row= row_it++;
- @note This uses "IF EXISTS" and does not return error if
- object does not exist.
+ DBUG_ASSERT(row->get_metadata()->get_num_columns() == 6);
- @param[in] thd current thread
- @param[out] serialization the data needed to recreate this object
+ const Ed_column *sql_mode= row->get_column(1);
+ const Ed_column *create_stmt= row->get_column(2);
+ const Ed_column *client_cs= row->get_column(3);
+ const Ed_column *connection_cl= row->get_column(4);
+ const Ed_column *db_cl= row->get_column(5);
+
+ os <<
+ "SET @saved_cs_client = @@character_set_client" <<
+ "SET @saved_col_connection = @@collation_connection" <<
+ "SET @saved_col_database = @@collation_database" <<
+ "SET character_set_client = utf8" <<
+ Fmt("USE `%.*s`", STR(m_db_name)) <<
+ Fmt("SET character_set_client = %.*s", LXS(client_cs)) <<
+ Fmt("SET collation_connection = %.*s", LXS(connection_cl)) <<
+ Fmt("SET collation_database = %.*s", LXS(db_cl)) <<
+ Fmt("SET sql_mode = '%.*s'", LXS(sql_mode)) <<
+ create_stmt <<
+ "SET character_set_client = @saved_cs_client" <<
+ "SET collation_connection = @saved_col_connection" <<
+ "SET collation_database = @saved_col_database";
- @returns Error status.
- @retval FALSE on success
- @retval TRUE on error
-*/
-bool StoredProcObj::drop(THD *thd)
-{
- DBUG_ENTER("StoredProcObj::drop()");
- DBUG_RETURN(drop_object(thd,
- (char *) "PROCEDURE",
- &m_db_name,
- &m_stored_proc_name));
+ DBUG_RETURN(FALSE);
}
///////////////////////////////////////////////////////////////////////////
-
-//
-// Implementation: StoredFuncObj class.
-//
-
///////////////////////////////////////////////////////////////////////////
-StoredFuncObj::StoredFuncObj(const String *db_name,
- const String *stored_func_name)
+Stored_func_obj::Stored_func_obj(const char *db_name_str, int db_name_length,
+ const char *sf_name_str, int sf_name_length)
{
- // copy strings to newly allocated memory
- m_db_name.copy(*db_name);
- m_stored_func_name.copy(*stored_func_name);
+ m_db_name.copy(db_name_str, db_name_length, system_charset_info);
+ m_sf_name.copy(sf_name_str, sf_name_length, system_charset_info);
}
+///////////////////////////////////////////////////////////////////////////
+
/**
Serialize the object.
This method produces the data necessary for materializing the object
on restore (creates object).
- @param[in] thd Thread context.
- @param[out] serialization The data needed to recreate this object.
+ @param[in] thd Thread context.
+ @param[out] os Output stream.
@note this method will return an error if the db_name is either
mysql or information_schema as these are not objects that
@@ -2567,108 +2276,102 @@ StoredFuncObj::StoredFuncObj(const Strin
@returns Error status.
@retval FALSE on success
@retval TRUE on error
- */
-bool StoredFuncObj::do_serialize(THD *thd, String *serialization)
-{
- bool ret= false;
- DBUG_ENTER("StoredFuncObj::serialize()");
- DBUG_PRINT("StoredProcObj::serialize", ("name: %s in %s",
- m_stored_func_name.c_ptr(), m_db_name.c_ptr()));
- prepend_db(thd, serialization, &m_db_name);
- ret= serialize_routine(thd, TYPE_ENUM_FUNCTION, m_db_name,
- m_stored_func_name, serialization);
- serialization->set_charset(system_charset_info);
- DBUG_RETURN(ret);
-}
-
-/**
- Materialize the serialization string.
-
- This method saves serialization string into a member variable.
+*/
- @param[in] serialization_version version number of this interface
- @param[in] serialization the string from serialize()
+bool Stored_func_obj::do_serialize(THD *thd, Out_stream &os)
+{
+ DBUG_ENTER("Stored_func_obj::do_serialize()");
+ DBUG_PRINT("Stored_func_obj::do_serialize",
+ ("name: %.*s.%.*s",
+ m_db_name.length(), m_db_name.ptr(),
+ m_sf_name.length(), m_sf_name.ptr()));
+
+ char query_buffer[QUERY_BUFFER_SIZE];
+ LEX_STRING query;
+
+ query.str= query_buffer;
+ query.length= my_snprintf(query_buffer, QUERY_BUFFER_SIZE,
+ "SHOW CREATE FUNCTION `%.*s`.`%.*s`",
+ (int) m_db_name.length(),
+ (const char *) m_db_name.ptr(),
+ (int) m_sf_name.length(),
+ (const char *) m_sf_name.ptr());
- @todo take serialization_version into account
+ Ed_result result(thd->mem_root);
- @returns Error status.
- @retval FALSE on success
- @retval TRUE on error
-*/
-bool StoredFuncObj::materialize(uint serialization_version,
- const String *serialization)
-{
- DBUG_ENTER("StoredFuncObj::materialize()");
- m_create_stmt.copy(*serialization);
- DBUG_RETURN(0);
-}
+ if (run_query(thd, &query, &result) ||
+ result.get_warnings()->elements > 0)
+ {
+ /*
+ There should be no warnings. A warning means that serialization has
+ failed.
+ */
+ log_warnings(&result);
+ DBUG_RETURN(TRUE);
+ }
-/**
- Create the object.
+ DBUG_ASSERT(result.elements == 1);
- This method uses serialization string in a query and executes it.
+ Ed_result_set *rs= result.get_cur_result_set();
- @param[in] thd Thread context.
+ DBUG_ASSERT(rs);
- @returns Error status.
- @retval FALSE on success
- @retval TRUE on error
-*/
-bool StoredFuncObj::do_execute(THD *thd)
-{
- DBUG_ENTER("StoredFuncObj::execute()");
- drop(thd);
- DBUG_RETURN(execute_with_ctx(thd, &m_create_stmt, false));
-}
+ if (rs->data()->elements == 0)
+ DBUG_RETURN(TRUE);
-/**
- Drop the object.
+ DBUG_ASSERT(rs->data()->elements == 1);
- This method calls the silent_exec method to execute the query.
+ List_iterator_fast<Ed_row> row_it(*rs->data());
+ Ed_row *row= row_it++;
- @note This uses "IF EXISTS" and does not return error if
- object does not exist.
+ DBUG_ASSERT(row->get_metadata()->get_num_columns() == 6);
- @param[in] thd Thread context.
- @param[out] serialization The data needed to recreate this object.
+ const Ed_column *sql_mode= row->get_column(1);
+ const Ed_column *create_stmt= row->get_column(2);
+ const Ed_column *client_cs= row->get_column(3);
+ const Ed_column *connection_cl= row->get_column(4);
+ const Ed_column *db_cl= row->get_column(5);
+
+ os <<
+ "SET @saved_cs_client = @@character_set_client" <<
+ "SET @saved_col_connection = @@collation_connection" <<
+ "SET @saved_col_database = @@collation_database" <<
+ "SET character_set_client = utf8" <<
+ Fmt("USE `%.*s`", STR(m_db_name)) <<
+ Fmt("SET character_set_client = %.*s", LXS(client_cs)) <<
+ Fmt("SET collation_connection = %.*s", LXS(connection_cl)) <<
+ Fmt("SET collation_database = %.*s", LXS(db_cl)) <<
+ Fmt("SET sql_mode = '%.*s'", LXS(sql_mode)) <<
+ create_stmt <<
+ "SET character_set_client = @saved_cs_client" <<
+ "SET collation_connection = @saved_col_connection" <<
+ "SET collation_database = @saved_col_database";
- @returns Error status.
- @retval FALSE on success
- @retval TRUE on error
-*/
-bool StoredFuncObj::drop(THD *thd)
-{
- DBUG_ENTER("StoredFuncObj::drop()");
- DBUG_RETURN(drop_object(thd,
- (char *) "FUNCTION",
- &m_db_name,
- &m_stored_func_name));
+ DBUG_RETURN(FALSE);
}
///////////////////////////////////////////////////////////////////////////
-
-//
-// Implementation: EventObj class.
-//
-
/////////////////////////////////////////////////////////////////////////////
+
#ifdef HAVE_EVENT_SCHEDULER
-EventObj::EventObj(const String *db_name,
- const String *event_name)
+
+Event_obj::Event_obj(const char *db_name_str, int db_name_length,
+ const char *event_name_str, int event_name_length)
{
- // copy strings to newly allocated memory
- m_db_name.copy(*db_name);
- m_event_name.copy(*event_name);
+ m_db_name.copy(db_name_str, db_name_length, system_charset_info);
+ m_event_name.copy(event_name_str, event_name_length, system_charset_info);
}
+///////////////////////////////////////////////////////////////////////////
+
/**
Serialize the object.
This method produces the data necessary for materializing the object
on restore (creates object).
- @param[in] thd Thread context.
- @param[out] serialization The data needed to recreate this object.
+ @param[in] thd Thread context.
+ @param[out] os Output stream.
@note this method will return an error if the db_name is either
mysql or information_schema as these are not objects that
@@ -2678,206 +2381,158 @@ EventObj::EventObj(const String *db_name
@retval FALSE on success
@retval TRUE on error
*/
-bool EventObj::do_serialize(THD *thd, String *serialization)
-{
- bool ret= false;
- Open_tables_state open_tables_backup;
- Event_timed et;
- LEX_STRING sql_mode;
- DBUG_ENTER("EventObj::serialize()");
- DBUG_PRINT("EventObj::serialize", ("name: %s.%s", m_db_name.c_ptr(),
- m_event_name.c_ptr()));
-
- prepend_db(thd, serialization, &m_db_name);
- Event_db_repository *db_repository= Events::get_db_repository();
- thd->reset_n_backup_open_tables_state(&open_tables_backup);
- LEX_STRING db;
- db.str= m_db_name.c_ptr();
- db.length= m_db_name.length();
- LEX_STRING ev;
- ev.str= m_event_name.c_ptr();
- ev.length= m_event_name.length();
- ret= db_repository->load_named_event(thd, db, ev, &et);
- thd->restore_backup_open_tables_state(&open_tables_backup);
- if (sys_var_thd_sql_mode::symbolic_mode_representation(thd,
- et.sql_mode, &sql_mode))
- DBUG_RETURN(TRUE);
- if (!ret)
- {
- /*
- Prepend sql_mode command.
- */
- serialization->append("SET SQL_MODE = '");
- serialization->append(sql_mode.str);
- serialization->append("'; ");
-
- /*
- append time zone information
- */
- serialization->append("SET TIME_ZONE = '");
- const String *tz= et.time_zone->get_name();
- serialization->append(tz->ptr());
- serialization->append("'; ");
- /*
- append character set client charset information
- */
- serialization->append("SET CHARACTER_SET_CLIENT = '");
- serialization->append(et.creation_ctx->get_client_cs()->csname);
- serialization->append("'; ");
+bool Event_obj::do_serialize(THD *thd, Out_stream &os)
+{
+ DBUG_ENTER("Event_obj::serialize()");
+ DBUG_PRINT("Event_obj::serialize",
+ ("name: %.*s.%.*s",
+ m_db_name.length(), m_db_name.ptr(),
+ m_event_name.length(), m_event_name.ptr()));
+
+ char query_buffer[QUERY_BUFFER_SIZE];
+ LEX_STRING query;
+
+ query.str= query_buffer;
+ query.length= my_snprintf(query_buffer, QUERY_BUFFER_SIZE,
+ "SHOW CREATE EVENT `%.*s`.`%.*s`",
+ (int) m_db_name.length(),
+ (const char *) m_db_name.ptr(),
+ (int) m_event_name.length(),
+ (const char *) m_event_name.ptr());
- /*
- append collation_connection information
- */
- serialization->append("SET COLLATION_CONNECTION = '");
- serialization->append(et.creation_ctx->get_connection_cl()->name);
- serialization->append("'; ");
+ Ed_result result(thd->mem_root);
+ if (run_query(thd, &query, &result) ||
+ result.get_warnings()->elements > 0)
+ {
/*
- append collation_connection information
+ There should be no warnings. A warning means that serialization has
+ failed.
*/
- serialization->append("SET COLLATION_DATABASE = '");
- serialization->append(et.creation_ctx->get_db_cl()->name);
- serialization->append("'; ");
-
- if (et.get_create_event(thd, serialization))
- DBUG_RETURN(0);
+ log_warnings(&result);
+ DBUG_RETURN(TRUE);
}
- serialization->set_charset(system_charset_info);
- DBUG_RETURN(0);
-}
-/**
- Materialize the serialization string.
+ DBUG_ASSERT(result.elements == 1);
- This method saves serialization string into a member variable.
+ Ed_result_set *rs= result.get_cur_result_set();
- @param[in] serialization_version version number of this interface
- @param[in] serialization the string from serialize()
+ DBUG_ASSERT(rs);
- @todo take serialization_version into account
+ if (rs->data()->elements == 0)
+ DBUG_RETURN(TRUE);
- @returns Error status.
- @retval FALSE on success
- @retval TRUE on error
-*/
-bool EventObj::materialize(uint serialization_version,
- const String *serialization)
-{
- DBUG_ENTER("EventObj::materialize()");
- m_create_stmt.copy(*serialization);
- DBUG_RETURN(0);
-}
+ DBUG_ASSERT(rs->data()->elements == 1);
-/**
- Create the object.
+ List_iterator_fast<Ed_row> row_it(*rs->data());
+ Ed_row *row= row_it++;
- This method uses serialization string in a query and executes it.
+ DBUG_ASSERT(row->get_metadata()->get_num_columns() == 7);
- @param[in] thd Thread context.
+ const Ed_column *sql_mode= row->get_column(1);
+ const Ed_column *tz= row->get_column(2);
+ const Ed_column *create_stmt= row->get_column(3);
+ const Ed_column *client_cs= row->get_column(4);
+ const Ed_column *connection_cl= row->get_column(5);
+ const Ed_column *db_cl= row->get_column(6);
+
+ os <<
+ "SET @saved_time_zone = @@time_zone" <<
+ "SET @saved_cs_client = @@character_set_client" <<
+ "SET @saved_col_connection = @@collation_connection" <<
+ "SET @saved_col_database = @@collation_database" <<
+ "SET character_set_client = utf8" <<
+ Fmt("USE `%.*s`", STR(m_db_name)) <<
+ Fmt("SET time_zone = '%.*s'", LXS(tz)) <<
+ Fmt("SET character_set_client = %.*s", LXS(client_cs)) <<
+ Fmt("SET collation_connection = %.*s", LXS(connection_cl)) <<
+ Fmt("SET collation_database = %.*s", LXS(db_cl)) <<
+ Fmt("SET sql_mode = '%.*s'", LXS(sql_mode)) <<
+ create_stmt <<
+ "SET time_zone = @saved_time_zone" <<
+ "SET character_set_client = @saved_cs_client" <<
+ "SET collation_connection = @saved_col_connection" <<
+ "SET collation_database = @saved_col_database";
- @returns Error status.
- @retval FALSE on success
- @retval TRUE on error
-*/
-bool EventObj::do_execute(THD *thd)
-{
- DBUG_ENTER("EventObj::execute()");
- drop(thd);
- DBUG_RETURN(execute_with_ctx(thd, &m_create_stmt, true));
+ DBUG_RETURN(FALSE);
}
-/**
- Drop the object.
-
- This method calls the silent_exec method to execute the query.
-
- @note This uses "IF EXISTS" and does not return error if
- object does not exist.
-
- @param[in] thd Thread context.
- @param[out] serialization the data needed to recreate this object
-
- @returns Error status.
- @retval FALSE on success
- @retval TRUE on error
-*/
-bool EventObj::drop(THD *thd)
-{
- DBUG_ENTER("EventObj::drop()");
- DBUG_RETURN(drop_object(thd,
- (char *) "EVENT",
- &m_db_name,
- &m_event_name));
-}
#endif // HAVE_EVENT_SCHEDULER
///////////////////////////////////////////////////////////////////////////
-
-//
-// Implementation: TablespaceObj class.
-//
-
/////////////////////////////////////////////////////////////////////////////
-TablespaceObj::TablespaceObj(const String *ts_name)
-{
- // copy strings to newly allocated memory
- m_ts_name.copy(*ts_name);
- m_datafile.length(0);
- m_comments.length(0);
+Tablespace_obj::Tablespace_obj(
+ const char *ts_name_str, int ts_name_length,
+ const char *comment_str, int comment_length,
+ const char *data_file_name_str, int data_file_name_length,
+ const char *engine_str, int engine_length)
+{
+ m_ts_name.copy(ts_name_str, ts_name_length, system_charset_info);
+ m_comment.copy(comment_str, comment_length, system_charset_info);
+ m_data_file_name.copy(data_file_name_str, data_file_name_length,
+ system_charset_info);
+ m_engine.copy(engine_str, engine_length, system_charset_info);
+
+ m_description.length(0);
+}
+
+Tablespace_obj::Tablespace_obj(const char *ts_name_str, int ts_name_length)
+{
+ m_ts_name.copy(ts_name_str, ts_name_length, system_charset_info);
+ m_comment.length(0);
+ m_data_file_name.length(0);
m_engine.length(0);
+
+ m_description.length(0);
}
+///////////////////////////////////////////////////////////////////////////
+
/**
Serialize the object.
This method produces the data necessary for materializing the object
on restore (creates object).
- @param[in] thd Thread context.
- @param[out] serialization The data needed to recreate this object.
+ @param[in] thd Thread context.
+ @param[out] os Output stream.
@returns Error status.
@retval FALSE on success
@retval TRUE on error
*/
-bool TablespaceObj::do_serialize(THD *thd, String *serialization)
-{
- DBUG_ENTER("TablespaceObj::serialize()");
- build_serialization();
- serialization->copy(m_create_stmt);
- DBUG_RETURN(FALSE);
-}
-/**
- Materialize the serialization string.
+bool Tablespace_obj::do_serialize(THD *thd, Out_stream &os)
+{
+ DBUG_ENTER("Tablespace_obj::serialize()");
- This method saves serialization string into a member variable.
- Also extracts tablespace engine name from serialization string.
+ os << *get_description();
- @param[in] serialization_version version number of this interface
- @param[in] serialization the string from serialize()
+ DBUG_RETURN(FALSE);
+}
- @todo take serialization_version into account
+///////////////////////////////////////////////////////////////////////////
- @returns Error status.
- @retval FALSE on success
- @retval TRUE on error
-*/
-bool TablespaceObj::materialize(uint serialization_version,
- const String *serialization)
+bool Tablespace_obj::materialize(uint serialization_version,
+ const String *serialization)
{
- DBUG_ENTER("TablespaceObj::materialize()");
- m_create_stmt.copy(*serialization);
- /* Extract engine from create statement */
- String tmp_str= String("=", 1, system_charset_info);
- int pos= m_create_stmt.strrstr(tmp_str, m_create_stmt.length());
- m_engine.copy(m_create_stmt.ptr() + pos + 1, m_create_stmt.length() - pos - 1,
- system_charset_info);
- DBUG_RETURN(FALSE);
+ if (Abstract_obj::materialize(serialization_version, serialization))
+ return TRUE;
+
+ List_iterator_fast<String> it(m_stmt_lst);
+ String *desc= it++;
+
+ DBUG_ASSERT(desc);
+
+ m_description.set(desc->ptr(), desc->length(), desc->charset());
+
+ return FALSE;
}
+///////////////////////////////////////////////////////////////////////////
+
/**
Get a description of the tablespace object.
@@ -2886,171 +2541,115 @@ bool TablespaceObj::materialize(uint ser
@returns Serialization string.
*/
-const String *TablespaceObj::describe()
+
+const String *Tablespace_obj::get_description()
{
- DBUG_ENTER("TablespaceObj::describe()");
- DBUG_RETURN(build_serialization());
-}
+ DBUG_ENTER("Tablespace_obj::get_description()");
-/**
- Build the serialization string.
+ DBUG_ASSERT(m_description.length() ||
+ m_ts_name.length() && m_data_file_name.length());
- This constructs the serialization string for identification
- use in describing tablespace to the user and for creating the
- tablespace.
+ if (m_description.length())
+ DBUG_RETURN(&m_description);
- @todo take serialization_version into account
+ /* Construct the CREATE TABLESPACE command from the variables. */
- @returns Serialization string.
-*/
-const String *TablespaceObj::build_serialization()
-{
- DBUG_ENTER("TablespaceObj::build_serialization()");
+ char query_buffer[QUERY_BUFFER_SIZE];
+ LEX_STRING query;
- if (m_create_stmt.length())
- DBUG_RETURN(&m_create_stmt);
+ query.str= query_buffer;
+ query.length= my_snprintf(query_buffer, QUERY_BUFFER_SIZE,
+ "CREATE TABLESPACE `%.*s` ADD DATAFILE '%.*s' ",
+ (int) m_ts_name.length(),
+ (const char *) m_ts_name.ptr(),
+ (int) m_data_file_name.length(),
+ (const char *) m_data_file_name.ptr());
- /*
- Construct the CREATE TABLESPACE command from the variables.
- */
- m_create_stmt.length(0);
- m_create_stmt.append("CREATE TABLESPACE ");
- if (m_ts_name.length() > 0)
- {
- THD *thd= current_thd;
- append_identifier(thd, &m_create_stmt,
- m_ts_name.c_ptr(), m_ts_name.length());
- }
- m_create_stmt.append(" ADD DATAFILE '");
- m_create_stmt.append(m_datafile);
- if (m_comments.length())
+ m_description.length(0);
+ m_description.append(query.str, query.length);
+
+ if (m_comment.length())
{
- m_create_stmt.append("' COMMENT = '");
- m_create_stmt.append(m_comments);
+ m_description.append("COMMENT = '");
+ m_description.append(m_comment);
+ m_description.append("' ");
}
- m_create_stmt.append("' ENGINE=");
- m_create_stmt.append(m_engine);
- DBUG_RETURN(&m_create_stmt);
-}
-/**
- Create the object.
-
- This method uses serialization string in a query and executes it.
+ m_description.append("ENGINE = ");
+ m_description.append(m_engine);
- @param[in] thd Thread context.
-
- @returns Error status.
- @retval FALSE on success
- @retval TRUE on error
-*/
-bool TablespaceObj::do_execute(THD *thd)
-{
- DBUG_ENTER("TablespaceObj::execute()");
- build_serialization(); // Build the CREATE command.
- DBUG_RETURN(silent_exec(thd, &m_create_stmt));
+ DBUG_RETURN(&m_description);
}
///////////////////////////////////////////////////////////////////////////
-//
-// Implementation: DbGrantObj class.
-//
/////////////////////////////////////////////////////////////////////////////
-DbGrantObj::DbGrantObj(const String *grantee,
- const String *db_name,
- const String *priv_type)
-{
- // copy strings to newly allocated memory
- m_db_name.copy(*db_name);
- m_grantee.copy(*grantee);
- m_name.copy(*grantee);
- m_priv_type.copy(*priv_type);
-}
-
-/**
- Serialize the object.
+void Grant_obj::generate_unique_id(const String *user_name,
+ const String *host_name,
+ String *id)
+{
+ static unsigned long id_counter= 0;
- This method produces the data necessary for materializing the object
- on restore (creates object).
+ id->length(0);
- @param[in] thd Thread context.
- @param[out] serialization The data needed to recreate this object.
+ if (user_name->length() && host_name->length())
+ {
+ id->append(*user_name);
+ id->append('@');
+ id->append(*host_name);
+ }
+ else
+ id->append("<no_name>");
- @note this method will return an error if the db_name is either
- mysql or information_schema as these are not objects that
- should be recreated using this interface.
+ char buf[10];
+ snprintf(buf, 10, " %08lu", ++id_counter);
- @returns Error status.
- @retval FALSE on success
- @retval TRUE on error
-*/
-bool DbGrantObj::do_serialize(THD *thd, String *serialization)
-{
- DBUG_ENTER("DbGrantObj::do_serialize()");
- serialization->length(0);
- serialization->append("GRANT ");
- serialization->append(m_priv_type);
- serialization->append(" ON ");
- serialization->append(m_db_name);
- serialization->append(".* TO ");
- serialization->append(m_grantee);
- DBUG_RETURN(0);
+ id->append(buf, 10);
}
-/**
- Materialize the serialization string.
+Grant_obj::Grant_obj(const char *user_name_str, int user_name_length,
+ const char *host_name_str, int host_name_length,
+ const char *priv_type_str, int priv_type_length,
+ const char *db_name_str, int db_name_length,
+ const char *table_name_str, int table_name_length,
+ const char *column_name_str, int column_name_length)
+{
+ m_user_name.copy(user_name_str, user_name_length, system_charset_info);
+ m_host_name.copy(host_name_str, host_name_length, system_charset_info);
- This method saves serialization string into a member variable.
+ /* Grant info. */
- @param[in] serialization_version version number of this interface
- @param[in] serialization the string from serialize()
+ m_grant_info.append(priv_type_str, priv_type_length);
- @todo take serialization_version into account
+ if (column_name_length)
+ {
+ m_grant_info.append('(');
+ m_grant_info.append(column_name_str, column_name_length);
+ m_grant_info.append(')');
+ }
- @returns Error status.
- @retval FALSE on success
- @retval TRUE on error
-*/
-bool DbGrantObj::materialize(uint serialization_version,
- const String *serialization)
-{
- DBUG_ENTER("DbGrantObj::materialize()");
- m_grant_stmt.copy(*serialization);
- DBUG_RETURN(0);
-}
+ m_grant_info.append(" ON ");
-/**
- Create the object.
+ m_grant_info.append(db_name_str, db_name_length);
+ m_grant_info.append('.');
- This method uses serialization string in a query and executes it.
+ if (table_name_length)
+ m_grant_info.append(table_name_str, table_name_length);
+ else
+ m_grant_info.append('*');
- @param[in] thd Thread context.
+ /* Id. */
- @returns Error status.
- @retval FALSE on success
- @retval TRUE on error
-*/
-bool DbGrantObj::do_execute(THD *thd)
-{
- DBUG_ENTER("DbGrantObj::do_execute()");
- DBUG_RETURN(execute_with_ctx(thd, &m_grant_stmt, true));
+ generate_unique_id(&m_user_name, &m_host_name, &m_id);
}
-///////////////////////////////////////////////////////////////////////////
-//
-// Implementation: TblGrantObj class.
-//
-/////////////////////////////////////////////////////////////////////////////
-
-TblGrantObj::TblGrantObj(const String *grantee,
- const String *db_name,
- const String *table_name,
- const String *priv_type)
-: DbGrantObj(grantee, db_name, priv_type)
+Grant_obj::Grant_obj(const char *name_str, int name_length)
{
- // copy strings to newly allocated memory
- m_table_name.copy(*table_name);
+ m_user_name.length(0);
+ m_host_name.length(0);
+ m_grant_info.length(0);
+
+ m_id.copy(name_str, name_length, system_charset_info);
}
/**
@@ -3059,8 +2658,8 @@ TblGrantObj::TblGrantObj(const String *g
This method produces the data necessary for materializing the object
on restore (creates object).
- @param[in] thd Thread context.
- @param[out] serialization The data needed to recreate this object.
+ @param[in] thd Thread context.
+ @param[out] os Output stream.
@note this method will return an error if the db_name is either
mysql or information_schema as these are not objects that
@@ -3070,127 +2669,168 @@ TblGrantObj::TblGrantObj(const String *g
@retval FALSE on success
@retval TRUE on error
*/
-bool TblGrantObj::do_serialize(THD *thd, String *serialization)
+
+bool Grant_obj::do_serialize(THD *thd, Out_stream &os)
{
- DBUG_ENTER("TblGrantObj::do_serialize()");
- serialization->length(0);
- serialization->append("GRANT ");
- serialization->append(m_priv_type);
- serialization->append(" ON ");
- serialization->append(m_db_name);
- serialization->append(".");
- serialization->append(m_table_name);
- serialization->append(" TO ");
- serialization->append(m_grantee);
- DBUG_RETURN(0);
-}
+ DBUG_ENTER("Grant_obj::do_serialize()");
-///////////////////////////////////////////////////////////////////////////
-//
-// Implementation: ColGrantObj class.
-//
-/////////////////////////////////////////////////////////////////////////////
+ os <<
+ m_user_name <<
+ m_host_name <<
+ m_grant_info <<
+ "SET @saved_cs_client = @@character_set_client" <<
+ "SET character_set_client= binary" <<
+ Fmt("GRANT %.*s TO '%.*s'@'%.*s'",
+ STR(m_grant_info), STR(m_user_name), STR(m_host_name)) <<
+ "SET character_set_client= @saved_cs_client";
-ColGrantObj::ColGrantObj(const String *grantee,
- const String *db_name,
- const String *table_name,
- const String *col_name,
- const String *priv_type)
-: TblGrantObj(grantee, db_name, table_name, priv_type)
-{
- // copy strings to newly allocated memory
- m_col_name.copy(*col_name);
+ DBUG_RETURN(FALSE);
}
-/**
- Serialize the object.
+bool Grant_obj::do_materialize(In_stream *is)
+{
+ LEX_STRING user_name;
+ LEX_STRING host_name;
+ LEX_STRING grant_info;
- This method produces the data necessary for materializing the object
- on restore (creates object).
+ if (is->next(&user_name))
+ return TRUE; /* Can not decode user name. */
- @param[in] thd Thread context.
- @param[out] serialization The data needed to recreate this object.
+ if (is->next(&host_name))
+ return TRUE; /* Can not decode host name. */
- @note this method will return an error if the db_name is either
- mysql or information_schema as these are not objects that
- should be recreated using this interface.
+ if (is->next(&grant_info))
+ return TRUE; /* Can not decode grant info. */
- @returns Error status.
- @retval FALSE on success
- @retval TRUE on error
-*/
-bool ColGrantObj::do_serialize(THD *thd, String *serialization)
-{
- DBUG_ENTER("ColGrantObj::do_serialize()");
- serialization->length(0);
- serialization->append("GRANT ");
- serialization->append(m_priv_type);
- serialization->append("(");
- serialization->append(m_col_name);
- serialization->append(") ON ");
- serialization->append(m_db_name);
- serialization->append(".");
- serialization->append(m_table_name);
- serialization->append(" TO ");
- serialization->append(m_grantee);
- DBUG_RETURN(0);
+ m_user_name.copy(user_name.str, user_name.length, system_charset_info);
+ m_host_name.copy(host_name.str, host_name.length, system_charset_info);
+ m_grant_info.copy(grant_info.str, grant_info.length, system_charset_info);
+
+ return Abstract_obj::do_materialize(is);
}
///////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
Obj *get_database(const String *db_name)
{
- return new DatabaseObj(db_name);
+ return new Database_obj(db_name->ptr(), db_name->length());
}
Obj *get_table(const String *db_name,
const String *table_name)
{
- return new TableObj(db_name, table_name, false);
+ return new Table_obj(db_name->ptr(), db_name->length(),
+ table_name->ptr(), table_name->length());
}
Obj *get_view(const String *db_name,
const String *view_name)
{
- return new TableObj(db_name, view_name, true);
+ return new View_obj(db_name->ptr(), db_name->length(),
+ view_name->ptr(), view_name->length());
}
Obj *get_trigger(const String *db_name,
const String *trigger_name)
{
- return new TriggerObj(db_name, trigger_name);
+ return new Trigger_obj(db_name->ptr(), db_name->length(),
+ trigger_name->ptr(), trigger_name->length());
}
Obj *get_stored_procedure(const String *db_name,
const String *sp_name)
{
- return new StoredProcObj(db_name, sp_name);
+ return new Stored_proc_obj(db_name->ptr(), db_name->length(),
+ sp_name->ptr(), sp_name->length());
}
Obj *get_stored_function(const String *db_name,
const String *sf_name)
{
- return new StoredFuncObj(db_name, sf_name);
+ return new Stored_func_obj(db_name->ptr(), db_name->length(),
+ sf_name->ptr(), sf_name->length());
}
Obj *get_event(const String *db_name,
const String *event_name)
{
#ifdef HAVE_EVENT_SCHEDULER
- return new EventObj(db_name, event_name);
+ return new Event_obj(db_name->ptr(), db_name->length(),
+ event_name->ptr(), event_name->length());
#else
return NULL;
#endif
}
+///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
+
+Obj_iterator *get_databases(THD *thd)
+{
+ return Database_iterator::create(thd);
+}
+
+Obj_iterator *get_db_tables(THD *thd, const String *db_name)
+{
+ return Db_tables_iterator::create(thd, db_name);
+}
+
+Obj_iterator *get_db_views(THD *thd, const String *db_name)
+{
+ return Db_views_iterator::create(thd, db_name);
+}
+
+Obj_iterator *get_db_triggers(THD *thd, const String *db_name)
+{
+ return Db_trigger_iterator::create(thd, db_name);
+}
+
+Obj_iterator *get_db_stored_procedures(THD *thd, const String *db_name)
+{
+ return Db_stored_proc_iterator::create(thd, db_name);
+}
+
+Obj_iterator *get_db_stored_functions(THD *thd, const String *db_name)
+{
+ return Db_stored_func_iterator::create(thd, db_name);
+}
+
+Obj_iterator *get_db_events(THD *thd, const String *db_name)
+{
+ return Db_event_iterator::create(thd, db_name);
+}
+
+Obj_iterator *get_all_db_grants(THD *thd, const String *db_name)
+{
+ return Grant_iterator::create(thd, db_name);
+}
+
+///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
+
+Obj_iterator* get_view_base_tables(THD *thd,
+ const String *db_name,
+ const String *view_name)
+{
+ return View_base_table_iterator::create(thd, db_name, view_name);
+}
+
+Obj_iterator* get_view_base_views(THD *thd,
+ const String *db_name,
+ const String *view_name)
+{
+ return View_base_view_iterator::create(thd, db_name, view_name);
+}
///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
Obj *materialize_database(const String *db_name,
uint serialization_version,
const String *serialization)
{
- Obj *obj= new DatabaseObj(db_name);
+ Obj *obj= new Database_obj(db_name->ptr(), db_name->length());
obj->materialize(serialization_version, serialization);
return obj;
@@ -3201,7 +2841,8 @@ Obj *materialize_table(const String *db_
uint serialization_version,
const String *serialization)
{
- Obj *obj= new TableObj(db_name, table_name, false);
+ Obj *obj= new Table_obj(db_name->ptr(), db_name->length(),
+ table_name->ptr(), table_name->length());
obj->materialize(serialization_version, serialization);
return obj;
@@ -3212,7 +2853,8 @@ Obj *materialize_view(const String *db_n
uint serialization_version,
const String *serialization)
{
- Obj *obj= new TableObj(db_name, view_name, true);
+ Obj *obj= new View_obj(db_name->ptr(), db_name->length(),
+ view_name->ptr(), view_name->length());
obj->materialize(serialization_version, serialization);
return obj;
@@ -3223,85 +2865,76 @@ Obj *materialize_trigger(const String *d
uint serialization_version,
const String *serialization)
{
- Obj *obj= new TriggerObj(db_name, trigger_name);
+ Obj *obj= new Trigger_obj(db_name->ptr(), db_name->length(),
+ trigger_name->ptr(), trigger_name->length());
obj->materialize(serialization_version, serialization);
return obj;
}
Obj *materialize_stored_procedure(const String *db_name,
- const String *stored_proc_name,
+ const String *sp_name,
uint serialization_version,
const String *serialization)
{
- Obj *obj= new StoredProcObj(db_name, stored_proc_name);
+ Obj *obj= new Stored_proc_obj(db_name->ptr(), db_name->length(),
+ sp_name->ptr(), sp_name->length());
obj->materialize(serialization_version, serialization);
return obj;
}
Obj *materialize_stored_function(const String *db_name,
- const String *stored_func_name,
+ const String *sf_name,
uint serialization_version,
const String *serialization)
{
- Obj *obj= new StoredFuncObj(db_name, stored_func_name);
+ Obj *obj= new Stored_func_obj(db_name->ptr(), db_name->length(),
+ sf_name->ptr(), sf_name->length());
obj->materialize(serialization_version, serialization);
return obj;
}
#ifdef HAVE_EVENT_SCHEDULER
+
Obj *materialize_event(const String *db_name,
const String *event_name,
uint serialization_version,
const String *serialization)
{
- Obj *obj= new EventObj(db_name, event_name);
+ Obj *obj= new Event_obj(db_name->ptr(), db_name->length(),
+ event_name->ptr(), event_name->length());
obj->materialize(serialization_version, serialization);
return obj;
}
+
#endif
Obj *materialize_tablespace(const String *ts_name,
uint serialization_version,
const String *serialization)
{
- Obj *obj= new TablespaceObj(ts_name);
+ Obj *obj= new Tablespace_obj(ts_name->ptr(), ts_name->length());
obj->materialize(serialization_version, serialization);
return obj;
}
-Obj *get_db_grant(const String *grantee,
- const String *db_name)
-{
- String priv_type;
- priv_type.length(0);
-
- return new DbGrantObj(grantee, db_name, &priv_type);
-}
-
Obj *materialize_db_grant(const String *db_name,
- const String *grantee,
+ const String *name,
uint serialization_version,
const String *serialization)
{
- /*
- Here we create a grant for the purposes of applying the
- grants. We use DbGrantObj for all types of grants because
- we only have the GRANT statement in the serialization
- string and therefore do not that the 'parts' to create
- the specific types.
- */
- Obj *obj= get_db_grant(grantee, db_name);
+ Obj *obj= new Grant_obj(name->ptr(), name->length());
obj->materialize(serialization_version, serialization);
return obj;
}
///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
bool is_internal_db_name(const String *db_name)
{
@@ -3319,370 +2952,222 @@ bool is_internal_db_name(const String *d
///////////////////////////////////////////////////////////////////////////
-bool check_db_existence(const String *db_name)
+bool check_db_existence(THD *thd, const String *db_name)
{
- return check_db_dir_existence(((String *) db_name)->c_ptr_safe());
+ char query_buffer[QUERY_BUFFER_SIZE];
+ LEX_STRING query;
+
+ query.str= query_buffer;
+ query.length= my_snprintf(query_buffer, QUERY_BUFFER_SIZE,
+ "SHOW CREATE DATABASE `%.*s`",
+ (int) db_name->length(),
+ (const char *) db_name->ptr());
+
+ Ed_result result(thd->mem_root);
+ int rc= run_query(thd, &query, &result);
+
+ /* We're not interested in warnings/errors here. */
+
+ return rc != 0;
}
-/*
- Splits grantee clause into user and host portions. Needed for checking
- to see if user exists on system.
-*/
-int split_user_host(String *grantee, String *user, String *host)
+///////////////////////////////////////////////////////////////////////////
+
+bool check_user_existence(THD *thd, const Obj *obj)
{
- int len= 0;
- int tics= 0;
- char *ptr= 0;
+#ifdef EMBEDDED_LIBRARY
+ return TRUE;
+#else
+ Grant_obj *grant_obj= (Grant_obj *) obj;
- /*
- Since passwords are single byte characters and usernames can be multibyte
- characters and the 0x40 = 64 = @ can occur in the username, we must search
- for the first @ from the right.
- */
- len= grantee->length();
- len--;
- ptr= grantee->c_ptr() + len;
- while ((len > 0) && (*ptr != '@'))
- {
- len--;
- ptr= grantee->c_ptr() + len;
- }
+ char query_buffer[QUERY_BUFFER_SIZE];
+ LEX_STRING query;
- if (ptr == 0)
- return -1;
- len= ptr - grantee->c_ptr();
- user->length(0);
- char *cptr= grantee->c_ptr();
+ query.str= query_buffer;
+ query.length= my_snprintf(query_buffer, QUERY_BUFFER_SIZE,
+ "SELECT 1 "
+ "FROM mysql.user "
+ "WHERE user = '%.*s' AND host = '%.*s'",
+ (int) grant_obj->get_user_name()->length(),
+ (const char *) grant_obj->get_user_name()->ptr(),
+ (int) grant_obj->get_host_name()->length(),
+ (const char *) grant_obj->get_host_name()->ptr());
- /*
- String ' from strings.
- */
- if (strncmp(cptr, "'", 1) == 0)
- {
- cptr++;
- len--;
- tics++;
- }
- user->append(cptr, len - tics);
- len= grantee->length() - len - 1 - tics;
- host->length(0);
+ Ed_result result(thd->mem_root);
- /*
- String ' from strings.
- */
- cptr= ptr + 1;
- tics= 0;
- if (strncmp(cptr, "'", 1) == 0)
- {
- cptr++;
- len--;
- }
- if (strncmp(cptr+len-1, "'", 1) == 0)
- tics++;
- host->append(cptr, len - tics);
- return 0;
-}
-
-bool check_user_existence(THD *thd, const String *grantee)
-{
- String user;
- String host;
- bool user_exists= FALSE;
-
- user.length(0);
- host.length(0);
- if (grantee)
- {
-#ifndef EMBEDDED_LIBRARY
- split_user_host((String *)grantee, &user, &host);
- if (!user.ptr())
- user.append("''");
- user_exists= is_acl_user(host.ptr(), user.ptr());
-#else
- user_exists= TRUE;
-#endif
+ if (run_query(thd, &query, &result) ||
+ result.get_warnings()->elements > 0)
+ {
+ /* Should be no warnings. */
+ sql_print_information("");
+ log_warnings(&result);
+ return FALSE;
}
- return user_exists;
-}
-/**
- Locate the row in the information_schema view for this tablespace.
+ Ed_result_set *rs= result.get_cur_result_set();
- This method returns a row from a tablespace information_schema view
- that matches the tablespace name passed.
+ if (!rs)
+ return FALSE;
- @param[in] thd Thread context
- @param[in] is_table_idx The information schema to search
- @param[in] ts_name The name of the tablespace to find
- @param[in] ts_engine Engine of the tablespace to find
- @param[out] datafile The datafile for the tablespace
- @param[out] comments The comments for the tablespace
-
- @retval FALSE if tablespace exists and no errors
- @retval TRUE if tablespace does not exist or errors
-*/
-static bool find_tablespace_schema_row(THD *thd,
- enum_schema_tables is_table_idx,
- const String *ts_name,
- const String *ts_engine,
- String *datafile,
- String *comments)
-{
- TABLE *is_table;
- handler *ha;
- my_bitmap_map *orig_col;
- LEX_STRING lex_ts_name;
- String found_ts_name, found_ts_engine;
- bool retval= TRUE;
- String data;
- List<LEX_STRING> ts_list;
- DBUG_ENTER("obs::find_tablespace_schema_row()");
+ return rs->data()->elements > 0;
+#endif
+}
- /*
- First, open the IS table.
- */
- lex_ts_name.str= (char *)ts_name->ptr();
- lex_ts_name.length= ts_name->length();
- ts_list.push_back(&lex_ts_name);
+///////////////////////////////////////////////////////////////////////////
- if (InformationSchemaIterator::prepare_is_table(
- thd, &is_table, &ha, &orig_col, is_table_idx, ts_list))
- DBUG_RETURN(TRUE);
+const String *grant_get_user_name(const Obj *obj)
+{
+ return ((Grant_obj *) obj)->get_user_name();
+}
- /* Locate the row in the schema table and retrive the data. */
- switch (is_table_idx) {
- case SCH_TABLESPACES:
- while (!ha->rnd_next(is_table->record[0]))
- {
- is_table->field[IS_TABLESPACES_TABLESPACE_NAME]->val_str(&found_ts_name);
- is_table->field[IS_TABLESPACES_ENGINE]->val_str(&found_ts_engine);
- if (found_ts_name.length() && found_ts_engine.length() &&
- !my_strnncoll(system_charset_info, (const uchar*) found_ts_name.ptr(),
- found_ts_name.length(), (const uchar*) ts_name->ptr(),
- ts_name->length()) &&
- !my_strnncoll(system_charset_info,
- (const uchar*) found_ts_engine.ptr(),
- found_ts_engine.length(),
- (const uchar*) ts_engine->ptr(), ts_engine->length()))
- {
- retval= FALSE;
- is_table->field[IS_TABLESPACES_TABLESPACE_COMMENT]->val_str(&data);
- comments->copy(data);
- DBUG_PRINT("find_tablespace_schema_row", (" Found tablespace %s",
- found_ts_name.ptr()));
- break;
- }
- found_ts_name.length(0);
- found_ts_engine.length(0);
- }
- break;
- case SCH_FILES:
- while (!ha->rnd_next(is_table->record[0]))
- {
- is_table->field[IS_FILES_TABLESPACE_NAME]->val_str(&found_ts_name);
- is_table->field[IS_FILES_ENGINE]->val_str(&found_ts_engine);
- if (found_ts_name.length() && found_ts_engine.length() &&
- !my_strnncoll(system_charset_info, (const uchar*) found_ts_name.ptr(),
- found_ts_name.length(), (const uchar*) ts_name->ptr(),
- ts_name->length()) &&
- !my_strnncoll(system_charset_info,
- (const uchar*) found_ts_engine.ptr(),
- found_ts_engine.length(),
- (const uchar*) ts_engine->ptr(), ts_engine->length()))
- {
- retval= FALSE;
- is_table->field[IS_FILES_FILE_NAME]->val_str(&data);
- datafile->copy(data);
- DBUG_PRINT("find_tablespace_schema_row", (" Found tablespace %s",
- found_ts_name.ptr()));
- break;
- }
- found_ts_name.length(0);
- found_ts_engine.length(0);
- }
- break;
- default:
- DBUG_ASSERT(0);
- break;
- }
+///////////////////////////////////////////////////////////////////////////
- /*
- Cleanup
- */
- ha->ha_rnd_end();
+const String *grant_get_host_name(const Obj *obj)
+{
+ return ((Grant_obj *) obj)->get_host_name();
+}
+
+///////////////////////////////////////////////////////////////////////////
- dbug_tmp_restore_column_map(is_table->read_set, orig_col);
- free_tmp_table(thd, is_table);
- DBUG_RETURN(retval);
+const String *grant_get_grant_info(const Obj *obj)
+{
+ return ((Grant_obj *) obj)->get_grant_info();
}
-/**
- Build a valid tablespace from the information_schema views.
+///////////////////////////////////////////////////////////////////////////
- This method builds a @c TablespaceObj object if the tablespace
- exists on the server.
+Obj *find_tablespace(THD *thd, const String *ts_name)
+{
+ char query_buffer[QUERY_BUFFER_SIZE];
+ LEX_STRING query;
- @param[in] thd Thread context.
- @param[out] TablespaceObj A pointer to a new tablespace object
- @param[in] ts_name The name of the tablespace to find
- @param[in] ts_engine Engine of the tablespace to find
+ query.str= query_buffer;
+ query.length= my_snprintf(query_buffer, QUERY_BUFFER_SIZE,
+ "SELECT t1.tablespace_comment, t2.file_name, t1.engine "
+ "FROM INFORMATION_SCHEMA.TABLESPACES AS t1, "
+ "INFORMATION_SCHEMA.FILES AS t2 "
+ "WHERE t1.tablespace_name = t2.tablespace_name AND "
+ "t1.tablespace_name = '%.*s'",
+ (int) ts_name->length(),
+ (const char *) ts_name->ptr());
- @note Caller is responsible for destroying the tablespace object.
+ Ed_result result(thd->mem_root);
- @retval FALSE if tablespace exists and no errors
- @retval TRUE if tablespace does not exist or errors
-*/
-static bool get_tablespace_from_schema(THD *thd,
- TablespaceObj **ts,
- const String *ts_name,
- const String *ts_engine)
-{
- String datafile;
- String comments;
- DBUG_ENTER("obs::get_tablespace_from_schema()");
+ if (run_query(thd, &query, &result) ||
+ result.get_warnings()->elements > 0)
+ {
+ /* Should be no warnings. */
+ log_warnings(&result);
+ return NULL;
+ }
- /*
- Locate the row in TABLESPACES and get the comments.
- */
- if (find_tablespace_schema_row(thd, SCH_TABLESPACES,
- ts_name, ts_engine, &datafile, &comments))
- DBUG_RETURN(TRUE);
+ if (!result.elements)
+ return NULL;
- /*
- Locate the row in FILES and get the datafile.
- */
- if (find_tablespace_schema_row(thd, SCH_FILES,
- ts_name, ts_engine, &datafile, &comments))
- DBUG_RETURN(TRUE);
+ Ed_result_set *rs= result.get_cur_result_set();
- /*
- The datafile parameter is required.
- */
- if (datafile.length() == 0)
- DBUG_RETURN(TRUE);
+ DBUG_ASSERT(rs->data()->elements == 1);
- DBUG_PRINT("get_tablespace_from_schema", (" Found tablespace %s %s",
- ts_name->ptr(), datafile.ptr()));
+ Ed_row *row= rs->get_cur_row();
- TablespaceObj *ts_local= new TablespaceObj(ts_name);
- *ts= ts_local;
- ts_local->set_datafile(&datafile);
- ts_local->set_comments(&comments);
- ts_local->set_engine(ts_engine);
+ DBUG_ASSERT(row->get_metadata()->get_num_columns() == 3);
- DBUG_RETURN(FALSE);
+ const Ed_column *comment= row->get_column(0);
+ const Ed_column *data_file_name= row->get_column(1);
+ const Ed_column *engine= row->get_column(2);
+
+ return new Tablespace_obj(ts_name->ptr(), ts_name->length(),
+ comment->str, comment->length,
+ data_file_name->str, data_file_name->length,
+ engine->str, engine->length);
}
+///////////////////////////////////////////////////////////////////////////
+
/**
Retrieve the tablespace for a table if it exists
- This method returns a @c TablespaceObj object if the table has a tablespace.
+ This method returns a @c Tablespace_obj object if the table has a tablespace.
- @param[in] thd Thread context.
- @param[in] db_name The database name for the table.
- @param[in] tbl_name The table name.
+ @param[in] thd Thread context.
+ @param[in] db_name The database name for the table.
+ @param[in] table_name The table name.
@note Caller is responsible for destroying the object.
@retval Tablespace object if table uses a tablespace
@retval NULL if table does not use a tablespace
*/
-Obj *get_tablespace_for_table(THD *thd,
- const String *db_name,
- const String *tbl_name)
-{
- TablespaceObj *ts= NULL;
- char path[FN_REFLEN];
- String ts_name, ts_engine;
- const char *ts_name_str= NULL;
- DBUG_ENTER("obs::get_tablespace_for_table()");
- DBUG_PRINT("obs::get_tablespace_for_table", ("name: %s.%s",
- db_name->ptr(), tbl_name->ptr()));
-
- const char *db= db_name->ptr();
- const char *name= tbl_name->ptr();
-
- build_table_filename(path, sizeof(path), db, name, "", 0);
- ts_name.length(0);
- ts_engine.length(0);
-
- TABLE *table= open_temporary_table(thd, path, db, name,
- FALSE /* don't link to thd->temporary_tables */,
- OTM_OPEN);
- if (table)
+Obj *find_tablespace_for_table(THD *thd,
+ const String *db_name,
+ const String *table_name)
+{
+ char query_buffer[QUERY_BUFFER_SIZE];
+ LEX_STRING query;
+
+ query.str= query_buffer;
+ query.length= my_snprintf(query_buffer, QUERY_BUFFER_SIZE,
+ "SELECT t1.tablespace_name, t1.engine, t1.tablespace_comment, t2.file_name "
+ "FROM INFORMATION_SCHEMA.TABLESPACES AS t1, "
+ "INFORMATION_SCHEMA.FILES AS t2, "
+ "INFORMATION_SCHEMA.TABLES AS t3 "
+ "WHERE t1.tablespace_name = t2.tablespace_name AND "
+ "t2.tablespace_name = t3.tablespace_name AND "
+ "t3.table_schema = '%.*s' AND "
+ "t3.table_name = '%.*s'",
+ (int) db_name->length(),
+ (const char *) db_name->ptr(),
+ (int) table_name->length(),
+ (const char *) table_name->ptr());
+
+ Ed_result result(thd->mem_root);
+
+ if (run_query(thd, &query, &result) ||
+ result.get_warnings()->elements > 0)
{
- if ((ts_name_str= table->file->get_tablespace_name()))
- {
- ts_name.append(ts_name_str);
- ts_name.set_charset(system_charset_info);
- ts_engine.append(table->file->engine_name()->str);
- ts_engine.set_charset(system_charset_info);
- }
- intern_close_table(table);
- my_free(table, MYF(0));
+ /* Should be no warnings. */
+ log_warnings(&result);
+ return NULL;
}
- else
- goto end;
- /*
- Now open the information_schema table and get the tablespace information.
- */
- if (ts_name_str)
- get_tablespace_from_schema(thd, &ts, &ts_name, &ts_engine);
-end:
- DBUG_RETURN(ts);
-}
+ if (!result.elements)
+ return NULL;
-/**
- Determine if tablespace exists.
+ Ed_result_set *rs= result.get_cur_result_set();
- This method determines if a materialized tablespace exists on the
- system. This compares the name and all saved attributes of the
- tablespace. A FALSE return would mean either the tablespace does
- not exist or the tablespace attributes are different.
+ if (!rs->data()->elements)
+ return NULL;
- @param[in] Obj The TablspaceObj pointer to compare.
+ DBUG_ASSERT(rs->data()->elements == 1);
- @retval TRUE if it exists
- @retval FALSE if it does not exist
-*/
-bool tablespace_exists(THD *thd,
- Obj *ts)
-{
- TablespaceObj *other_ts= NULL, *this_ts= static_cast<TablespaceObj*>(ts);
- bool retval= FALSE;
- DBUG_ENTER("obs::tablespace_exists()");
- get_tablespace_from_schema(thd, &other_ts, this_ts->get_name(),
- this_ts->get_engine());
- if (!other_ts)
- DBUG_RETURN(retval);
- retval= (my_strcasecmp(system_charset_info,
- other_ts->build_serialization()->ptr(),
- ((TablespaceObj *)ts)->build_serialization()->ptr()) == 0);
- delete other_ts;
- DBUG_RETURN(retval);
-}
+ Ed_row *row= rs->get_cur_row();
-/**
- Is there a tablespace with the given name?
+ DBUG_ASSERT(row->get_metadata()->get_num_columns() == 4);
- This method determines if the tablespace referenced by name exists on the
- system. Returns a TablespaceObj if it exists or NULL if it doesn't.
+ const Ed_column *ts_name= row->get_column(0);
+ const Ed_column *engine= row->get_column(1);
+ const Ed_column *comment= row->get_column(2);
+ const Ed_column *data_file_name= row->get_column(3);
- @param[in] Obj The TablspaceObj pointer to compare.
+ return new Tablespace_obj(ts_name->str, ts_name->length,
+ comment->str, comment->length,
+ data_file_name->str, data_file_name->length,
+ engine->str, engine->length);
+}
- @note Caller is responsible for destroying the tablespace object.
+///////////////////////////////////////////////////////////////////////////
- @returns the tablespace if found or NULL if not found
-*/
-Obj *is_tablespace(THD *thd, Obj *ts)
+bool compare_tablespace_attributes(Obj *ts1, Obj *ts2)
{
- TablespaceObj *other_ts= NULL, *this_ts= static_cast<TablespaceObj*>(ts);
- DBUG_ENTER("obs::is_tablespace()");
- get_tablespace_from_schema(thd, &other_ts, this_ts->get_name(),
- this_ts->get_engine());
- DBUG_RETURN(other_ts);
+ DBUG_ENTER("obs::compare_tablespace_attributes()");
+
+ Tablespace_obj *o1= (Tablespace_obj *) ts1;
+ Tablespace_obj *o2= (Tablespace_obj *) ts2;
+
+ DBUG_RETURN(my_strcasecmp(system_charset_info,
+ o1->get_description()->ptr(),
+ o2->get_description()->ptr()) == 0);
}
///////////////////////////////////////////////////////////////////////////
@@ -3861,6 +3346,6 @@ int Name_locker::release_name_locks()
DBUG_RETURN(0);
}
-} // obs namespace
-
///////////////////////////////////////////////////////////////////////////
+
+} // obs namespace
=== modified file 'sql/si_objects.h'
--- a/sql/si_objects.h 2008-10-27 13:06:21 +0000
+++ b/sql/si_objects.h 2008-11-13 19:34:18 +0000
@@ -15,38 +15,49 @@
namespace obs {
+///////////////////////////////////////////////////////////////////////////
+
/**
Obj defines the basic set of operations for each database object.
*/
-
class Obj
{
public:
-
- bool serialize(THD *thd, String *serialization);
-
/**
Return the name of the object.
@return object name.
*/
- virtual const String *get_name() = 0;
+ virtual const String *get_name() const = 0;
/**
Return the database name of the object.
@note this is a subject to remove.
*/
- virtual const String *get_db_name() = 0;
+ virtual const String *get_db_name() const = 0;
+
+public:
+ /**
+ Serialize an object to a string. The serialization string is opaque
+ object for the client.
+
+ @return Error status.
+ */
+ virtual bool serialize(THD *thd, String *serialization) = 0;
+
+ /**
+ Materialize an object in the database.
- bool execute(THD *thd);
+ @return Error status.
+ */
+ virtual bool execute(THD *thd) = 0;
public:
virtual ~Obj()
{ }
-private:
-
+protected:
/**
Read the object state from a given buffer and restores object state to
the point, where it can be executed.
@@ -61,23 +72,6 @@ private:
virtual bool materialize(uint serialization_version,
const String *serialization) = 0;
- /// Primitive implementing @c serialize() method.
- virtual bool do_serialize(THD *thd, String *serialization) = 0;
-
- /// Primitive implementing @c execute() method.
- virtual bool do_execute(THD *thd) = 0;
-
- /**
- Drop the object.
-
- @param[in] thd Server thread context.
-
- @return error status.
- @retval FALSE on success.
- @retval TRUE on error.
- */
- virtual bool drop(THD *thd) = 0;
-
private:
friend Obj *materialize_database(const String *,
uint,
@@ -124,91 +118,14 @@ private:
};
-
-/**
- Create the object in the database.
-
- @param[in] thd Server thread context.
-
- @return error status.
- @retval FALSE on success.
- @retval TRUE on error.
-
- @note The real work is done inside @c do_execute() primitive which should be
- defied in derived classes. This method prepares appropriate context and calls
- the primitive.
-*/
-inline
-bool Obj::execute(THD *thd)
-{
- ulong saved_sql_mode= thd->variables.sql_mode;
- thd->variables.sql_mode= 0;
-
- set_var_collation_client saved_charset_settings(
- thd->variables.character_set_client,
- thd->variables.character_set_results,
- thd->variables.collation_connection);
-
- set_var_collation_client new_charset_settings(::system_charset_info,
- ::system_charset_info,
- ::system_charset_info);
- new_charset_settings.update(thd);
-
- bool ret= do_execute(thd);
-
- saved_charset_settings.update(thd);
- thd->variables.sql_mode= saved_sql_mode;
-
- return ret;
-}
-
-/**
- Serialize object state into a buffer. The buffer actually should be a
- binary buffer. String class is used here just because we don't have
- convenient primitive for binary buffers.
-
- Serialization format is opaque to the client, i.e. the client should
- not make any assumptions about the format or the content of the
- returned buffer.
-
- Serialization format can be changed in the future versions. However,
- the server must be able to materialize objects coded in any previous
- formats.
-
- @param[in] thd Server thread context.
- @param[in] serialization Buffer to serialize the object
-
- @return error status.
- @retval FALSE on success.
- @retval TRUE on error.
-
- @note The real work is done inside @c do_serialize() primitive which should be
- defied in derived classes. This method prepares appropriate context and calls
- the primitive.
-*/
-inline
-bool Obj::serialize(THD *thd, String *serialization)
-{
- ulong saved_sql_mode= thd->variables.sql_mode;
- thd->variables.sql_mode= 0;
-
- bool ret= do_serialize(thd, serialization);
-
- thd->variables.sql_mode= saved_sql_mode;
-
- return ret;
-}
-
///////////////////////////////////////////////////////////////////////////
/**
Obj_iterator is a basic interface to enumerate the objects.
*/
-
class Obj_iterator
{
public:
-
Obj_iterator()
{ }
@@ -226,40 +143,6 @@ public:
public:
virtual ~Obj_iterator()
{ }
-
-};
-
-/**
- GrantObjIternator is an encapsulation of the three iterators for each level
- of grant supported: database-, table- and routine-, and column-level.
-*/
-class GrantObjIterator : public Obj_iterator
-{
-public:
- GrantObjIterator(THD *thd, const String *db_name);
-
- ~GrantObjIterator()
- {
- delete db_grants;
- delete tbl_grants;
- delete col_grants;
- }
-
- /**
- This operation returns a pointer to the next object in an enumeration.
- It returns NULL if there is no more objects.
-
- The client is responsible to destroy the returned object.
-
- @return a pointer to the object
- @retval NULL if there is no more objects in an enumeration.
- */
- Obj *next();
-
-private:
- Obj_iterator *db_grants; ///< database-level grants
- Obj_iterator *tbl_grants; ///< table- and routine-level grants
- Obj_iterator *col_grants; ///< column-level grants
};
///////////////////////////////////////////////////////////////////////////
@@ -283,7 +166,6 @@ private:
@return a pointer to an instance of Obj representing given database.
*/
-
Obj *get_database(const String *db_name);
/**
@@ -299,7 +181,6 @@ Obj *get_database(const String *db_name)
@return a pointer to an instance of Obj representing given table.
*/
-
Obj *get_table(const String *db_name, const String *table_name);
/**
@@ -315,7 +196,6 @@ Obj *get_table(const String *db_name, co
@return a pointer to an instance of Obj representing given view.
*/
-
Obj *get_view(const String *db_name, const String *view_name);
/**
@@ -331,7 +211,6 @@ Obj *get_view(const String *db_name, con
@return a pointer to an instance of Obj representing given trigger.
*/
-
Obj *get_trigger(const String *db_name, const String *trigger_name);
/**
@@ -349,7 +228,6 @@ Obj *get_trigger(const String *db_name,
@return a pointer to an instance of Obj representing given stored
procedure.
*/
-
Obj *get_stored_procedure(const String *db_name, const String *sp_name);
/**
@@ -367,7 +245,6 @@ Obj *get_stored_procedure(const String *
@return a pointer to an instance of Obj representing given stored
function.
*/
-
Obj *get_stored_function(const String *db_name, const String *sf_name);
/**
@@ -383,7 +260,6 @@ Obj *get_stored_function(const String *d
@return a pointer to an instance of Obj representing given event.
*/
-
Obj *get_event(const String *db_name, const String *event_name);
///////////////////////////////////////////////////////////////////////////
@@ -393,6 +269,8 @@ Obj *get_event(const String *db_name, co
//
// The client is responsible for destroying the returned iterator.
+///////////////////////////////////////////////////////////////////////////
+
/**
Create an iterator over all databases in the server.
@@ -400,7 +278,6 @@ Obj *get_event(const String *db_name, co
@return a pointer to an iterator object.
*/
-
Obj_iterator *get_databases(THD *thd);
/**
@@ -411,7 +288,6 @@ Obj_iterator *get_databases(THD *thd);
@return a pointer to an iterator object.
@retval NULL in case of error.
*/
-
Obj_iterator *get_db_tables(THD *thd, const String *db_name);
/**
@@ -422,7 +298,6 @@ Obj_iterator *get_db_tables(THD *thd, co
@return a pointer to an iterator object.
@retval NULL in case of error.
*/
-
Obj_iterator *get_db_views(THD *thd, const String *db_name);
/**
@@ -433,7 +308,6 @@ Obj_iterator *get_db_views(THD *thd, con
@return a pointer to an iterator object.
@retval NULL in case of error.
*/
-
Obj_iterator *get_db_triggers(THD *thd, const String *db_name);
/**
@@ -444,7 +318,6 @@ Obj_iterator *get_db_triggers(THD *thd,
@return a pointer to an iterator object.
@retval NULL in case of error.
*/
-
Obj_iterator *get_db_stored_procedures(THD *thd, const String *db_name);
/**
@@ -455,7 +328,6 @@ Obj_iterator *get_db_stored_procedures(T
@return a pointer to an iterator object.
@retval NULL in case of error.
*/
-
Obj_iterator *get_db_stored_functions(THD *thd, const String *db_name);
/**
@@ -466,7 +338,6 @@ Obj_iterator *get_db_stored_functions(TH
@return a pointer to an iterator object.
@retval NULL in case of error.
*/
-
Obj_iterator *get_db_events(THD *thd, const String *db_name);
/*
@@ -483,6 +354,8 @@ Obj_iterator *get_all_db_grants(THD *thd
//
// The client is responsible for destroying the returned iterator.
+///////////////////////////////////////////////////////////////////////////
+
/**
Create an iterator overl all base tables in the particular view.
@@ -491,7 +364,6 @@ Obj_iterator *get_all_db_grants(THD *thd
@return a pointer to an iterator object.
@retval NULL in case of error.
*/
-
Obj_iterator* get_view_base_tables(THD *thd,
const String *db_name,
const String *view_name);
@@ -504,7 +376,6 @@ Obj_iterator* get_view_base_tables(THD *
@return a pointer to an iterator object.
@retval NULL in case of error.
*/
-
Obj_iterator* get_view_base_views(THD *thd,
const String *db_name,
const String *view_name);
@@ -516,6 +387,8 @@ Obj_iterator* get_view_base_views(THD *t
//
// The client is responsible for destroying the returned iterator.
+///////////////////////////////////////////////////////////////////////////
+
Obj *materialize_database(const String *db_name,
uint serialization_version,
const String *serialization);
@@ -554,8 +427,8 @@ Obj *materialize_tablespace(const String
uint serialization_version,
const String *serialization);
-Obj *materialize_db_grant(const String *grantee,
- const String *db_name,
+Obj *materialize_db_grant(const String *db_name,
+ const String *name,
uint serialization_version,
const String *serialization);
@@ -565,14 +438,11 @@ Obj *materialize_db_grant(const String *
Check if the given database name is reserved for internal use.
@return
- @retval TRUE if the given database name is reserved for internal use
+ @retval TRUE if the given database name is reserved for internal use.
@retval FALSE otherwise.
*/
-
bool is_internal_db_name(const String *db_name);
-///////////////////////////////////////////////////////////////////////////
-
/**
Check if the given directory actually exists.
@@ -580,42 +450,54 @@ bool is_internal_db_name(const String *d
@retval FALSE on success (the database exists and accessible).
@retval TRUE on error (the database either not exists, or not accessible).
*/
+bool check_db_existence(THD *thd, const String *db_name);
-bool check_db_existence(const String *db_name);
+/**
+ Check if the user is defined on the system.
-/*
- Check if the given user is actually defined on the system.
+ @return
+ @retval TRUE if user is defined
+ @retval FALSE otherwise
+*/
+bool check_user_existence(THD *thd, const Obj *obj);
- @return Existence status.
- @retval TRUE if user is defined on the system.
- @retval FALSE if user does not exist.
+/**
+ Return user name of materialized grant object.
*/
+const String *grant_get_user_name(const Obj *obj);
-bool check_user_existence(THD *thd, const String *grantee);
+/**
+ Return host name of materialized grant object.
+*/
+const String *grant_get_host_name(const Obj *obj);
-/*
- This method returns a @c TablespaceObj object if the table has a tablespace.
+/**
+ Return grant info of materialized grant object.
*/
+const String *grant_get_grant_info(const Obj *obj);
-Obj *get_tablespace_for_table(THD *thd,
- const String *db_name,
- const String *tbl_name);
+/**
+ Determine if the tablespace referenced by name exists on the system.
-/*
- This method determines if a materialized tablespace exists on the
- system. This compares the name and all saved attributes of the
- tablespace. A FALSE return would mean either the tablespace does
- not exist or the tablespace attributes are different.
+ @return a Tablespace_obj if it exists or NULL if it doesn't.
*/
+Obj *find_tablespace(THD *thd, const String *ts_name);
-bool tablespace_exists(THD *thd, Obj *ts);
-
-/*
- This method determines if the tablespace referenced by name exists on the
- system. Returns a TablespaceObj if it exists or NULL if it doesn't.
+/**
+ This method returns a @c Tablespace_obj object if the table has a
+ tablespace.
*/
+Obj *find_tablespace_for_table(THD *thd,
+ const String *db_name,
+ const String *table_name);
-Obj *is_tablespace(THD *thd, Obj *ts);
+/**
+ This method determines if a materialized tablespace exists on the system.
+ This compares the name and all saved attributes of the tablespace. A
+ FALSE return would mean either the tablespace does not exist or the
+ tablespace attributes are different.
+*/
+bool compare_tablespace_attributes(Obj *ts1, Obj *ts2);
///////////////////////////////////////////////////////////////////////////
@@ -623,6 +505,8 @@ Obj *is_tablespace(THD *thd, Obj *ts);
// DDL blocker methods.
//
+///////////////////////////////////////////////////////////////////////////
+
/**
Turn on the ddl blocker.
@@ -664,14 +548,6 @@ void ddl_blocker_exception_on(THD *thd);
void ddl_blocker_exception_off(THD *thd);
/*
- Creates a WHERE clause for information schema table lookups of the
- for FROM INFORMATION_SCHEMA.X WHERE <db_col> IN ('a','b','c').
-*/
-COND *create_db_select_condition(THD *thd,
- TABLE *t,
- List<LEX_STRING> *db_list);
-
-/*
The following class is used to manage name locks on a list of tables.
This class uses a list of type List<Obj> to establish the table list
=== modified file 'sql/sql_class.cc'
--- a/sql/sql_class.cc 2008-11-07 14:04:18 +0000
+++ b/sql/sql_class.cc 2008-11-13 19:34:18 +0000
@@ -400,7 +400,6 @@ Diagnostics_area::reset_diagnostics_area
{
DBUG_ENTER("reset_diagnostics_area");
#ifdef DBUG_OFF
- can_overwrite_status= FALSE;
/** Don't take chances in production */
m_message[0]= '\0';
m_sql_errno= 0;
@@ -409,6 +408,7 @@ Diagnostics_area::reset_diagnostics_area
m_last_insert_id= 0;
m_total_warn_count= 0;
#endif
+ can_overwrite_status= FALSE;
is_sent= FALSE;
/** Tiny reset in debug mode to see garbage right away */
m_status= DA_EMPTY;
@@ -504,6 +504,9 @@ Diagnostics_area::set_error_status(THD *
m_sql_errno= sql_errno_arg;
strmake(m_message, message_arg, sizeof(m_message)-1);
+ if (is_set() && is_sent)
+ is_sent= FALSE;
+
m_status= DA_ERROR;
DBUG_VOID_RETURN;
}
=== modified file 'sql/sql_error.cc'
--- a/sql/sql_error.cc 2008-10-08 15:37:32 +0000
+++ b/sql/sql_error.cc 2008-11-13 19:34:18 +0000
@@ -51,9 +51,9 @@ This file contains the implementation of
got after the query has been executed.
*/
-void MYSQL_ERROR::set_msg(THD *thd, const char *msg_arg)
+void MYSQL_ERROR::set_msg(MEM_ROOT *mem_root, const char *msg_arg)
{
- msg= strdup_root(&thd->warn_root, msg_arg);
+ msg= strdup_root(mem_root, msg_arg);
}
@@ -151,7 +151,8 @@ void push_warning(THD *thd, MYSQL_ERROR:
if (thd->warn_list.elements < thd->variables.max_error_count)
{
/* We have to use warn_root, as mem_root is freed after each query */
- if ((err= new (&thd->warn_root) MYSQL_ERROR(thd, code, level, msg)))
+ if ((err= new (&thd->warn_root) MYSQL_ERROR(&thd->warn_root, code, level,
+ msg)))
thd->warn_list.push_back(err, &thd->warn_root);
}
thd->warn_count[(uint) level]++;
=== modified file 'sql/sql_error.h'
--- a/sql/sql_error.h 2008-07-29 22:03:57 +0000
+++ b/sql/sql_error.h 2008-11-13 19:34:18 +0000
@@ -23,16 +23,23 @@ public:
enum_warning_level level;
char *msg;
- MYSQL_ERROR(THD *thd, uint code_arg, enum_warning_level level_arg,
+ MYSQL_ERROR(MEM_ROOT *mem_root, uint code_arg, enum_warning_level level_arg,
const char *msg_arg)
:code(code_arg), level(level_arg)
{
if (msg_arg)
- set_msg(thd, msg_arg);
+ set_msg(mem_root, msg_arg);
+ }
+
+ MYSQL_ERROR(MEM_ROOT *mem_root, const MYSQL_ERROR *err)
+ :code(err->code), level(err->level)
+ {
+ if (err->msg)
+ set_msg(mem_root, err->msg);
}
private:
- void set_msg(THD *thd, const char *msg_arg);
+ void set_msg(MEM_ROOT *mem_root, const char *msg_arg);
};
void push_warning(THD *thd, MYSQL_ERROR::enum_warning_level level,
=== modified file 'sql/sql_lex.cc'
--- a/sql/sql_lex.cc 2008-10-16 02:13:16 +0000
+++ b/sql/sql_lex.cc 2008-11-13 19:34:18 +0000
@@ -144,6 +144,7 @@ Lex_input_stream::Lex_input_stream(THD *
found_semicolon(NULL),
ignore_space(test(thd->variables.sql_mode & MODE_IGNORE_SPACE)),
stmt_prepare_mode(FALSE),
+ multi_statements(TRUE),
in_comment(NO_COMMENT),
m_underscore_cs(NULL)
{
=== modified file 'sql/sql_lex.h'
--- a/sql/sql_lex.h 2008-11-04 11:30:00 +0000
+++ b/sql/sql_lex.h 2008-11-13 19:34:18 +0000
@@ -1481,6 +1481,11 @@ public:
*/
bool stmt_prepare_mode;
+ /**
+ TRUE if we should allow multi-statements.
+ */
+ bool multi_statements;
+
/** State of the lexical analyser for comments. */
enum_comment_state in_comment;
=== modified file 'sql/sql_parse.cc'
--- a/sql/sql_parse.cc 2008-11-06 18:39:27 +0000
+++ b/sql/sql_parse.cc 2008-11-13 19:34:18 +0000
@@ -1471,8 +1471,7 @@ void log_slow_statement(THD *thd)
thd->variables.long_query_time ||
((thd->server_status &
(SERVER_QUERY_NO_INDEX_USED | SERVER_QUERY_NO_GOOD_INDEX_USED)) &&
- opt_log_queries_not_using_indexes &&
- !(sql_command_flags[thd->lex->sql_command] & CF_STATUS_COMMAND))) &&
+ opt_log_queries_not_using_indexes)) &&
thd->examined_row_count >= thd->variables.min_examined_row_limit)
{
thd_proc_info(thd, "logging slow query");
@@ -2012,9 +2011,6 @@ mysql_execute_command(THD *thd)
if (!(res= check_table_access(thd, SELECT_ACL, all_tables, FALSE, FALSE,
UINT_MAX)))
res= execute_sqlcom_select(thd, all_tables);
- /* Don't log SHOW STATUS commands to slow query log */
- thd->server_status&= ~(SERVER_QUERY_NO_INDEX_USED |
- SERVER_QUERY_NO_GOOD_INDEX_USED);
/*
restore status variables, as we don't want 'show status' to cause
changes
@@ -4578,6 +4574,13 @@ finish:
start_waiting_global_read_lock(thd);
}
+ if (sql_command_flags[thd->lex->sql_command] & CF_STATUS_COMMAND)
+ {
+ /* Don't log SHOW STATUS commands to slow query log */
+ thd->server_status&= ~(SERVER_QUERY_NO_INDEX_USED |
+ SERVER_QUERY_NO_GOOD_INDEX_USED);
+ }
+
/* If commit fails, we should be able to reset the OK status. */
thd->main_da.can_overwrite_status= TRUE;
opt_implicit_commit(thd, CF_IMPLICIT_COMMIT_END);
=== modified file 'sql/sql_prepare.cc'
--- a/sql/sql_prepare.cc 2008-11-06 18:39:27 +0000
+++ b/sql/sql_prepare.cc 2008-11-13 19:34:18 +0000
@@ -127,12 +127,12 @@ class Prepared_statement: public Stateme
public:
enum flag_values
{
- IS_IN_USE= 1
+ IS_IN_USE= 1,
+ IS_SQL_PREPARE= 2,
};
THD *thd;
Select_fetch_protocol_binary result;
- Protocol *protocol;
Item_param **param_array;
uint param_count;
uint last_errno;
@@ -148,7 +148,7 @@ public:
List<LEX_STRING>& varnames,
String *expanded_query);
public:
- Prepared_statement(THD *thd_arg, Protocol *protocol_arg);
+ Prepared_statement(THD *thd_arg);
virtual ~Prepared_statement();
void setup_set_params();
virtual Query_arena::Type type() const;
@@ -156,11 +156,13 @@ public:
bool set_name(LEX_STRING *name);
inline void close_cursor() { delete cursor; cursor= 0; }
inline bool is_in_use() { return flags & (uint) IS_IN_USE; }
- inline bool is_protocol_text() const { return protocol == &thd->protocol_text; }
+ inline bool is_sql_prepare() const { return flags & (uint) IS_SQL_PREPARE; }
+ void set_sql_prepare() { flags|= (uint) IS_SQL_PREPARE; }
bool prepare(const char *packet, uint packet_length);
bool execute_loop(String *expanded_query,
bool open_cursor,
uchar *packet_arg, uchar *packet_end_arg);
+ bool execute_immediate(const char *stmt, uint length);
/* Destroy this statement */
void deallocate();
private:
@@ -1361,7 +1363,7 @@ static int mysql_test_select(Prepared_st
*/
if (unit->prepare(thd, 0, 0))
goto error;
- if (!lex->describe && !stmt->is_protocol_text())
+ if (!lex->describe && !stmt->is_sql_prepare())
{
/* Make copy of item list, as change_columns may change it */
List<Item> fields(lex->select_lex.item_list);
@@ -1995,7 +1997,7 @@ static bool check_prepared_statement(Pre
break;
}
if (res == 0)
- DBUG_RETURN(stmt->is_protocol_text() ?
+ DBUG_RETURN(stmt->is_sql_prepare() ?
FALSE : (send_prep_stmt(stmt, 0) || thd->protocol->flush()));
error:
DBUG_RETURN(TRUE);
@@ -2065,6 +2067,7 @@ static bool init_param_array(Prepared_st
void mysql_stmt_prepare(THD *thd, const char *packet, uint packet_length)
{
+ Protocol *save_protocol= thd->protocol;
Prepared_statement *stmt;
DBUG_ENTER("mysql_stmt_prepare");
@@ -2073,7 +2076,7 @@ void mysql_stmt_prepare(THD *thd, const
/* First of all clear possible warnings from the previous command */
mysql_reset_thd_for_next_command(thd);
- if (! (stmt= new Prepared_statement(thd, &thd->protocol_binary)))
+ if (! (stmt= new Prepared_statement(thd)))
DBUG_VOID_RETURN; /* out of memory: error is set in Sql_alloc */
if (thd->stmt_map.insert(thd, stmt))
@@ -2088,11 +2091,16 @@ void mysql_stmt_prepare(THD *thd, const
sp_cache_flush_obsolete(&thd->sp_proc_cache);
sp_cache_flush_obsolete(&thd->sp_func_cache);
+ thd->protocol= &thd->protocol_binary;
+
if (stmt->prepare(packet, packet_length))
{
/* Statement map deletes statement on erase */
thd->stmt_map.erase(stmt);
}
+
+ thd->protocol= save_protocol;
+
/* check_prepared_statemnt sends the metadata packet in case of success */
DBUG_VOID_RETURN;
}
@@ -2226,7 +2234,7 @@ void mysql_sql_stmt_prepare(THD *thd)
uint query_len;
DBUG_ENTER("mysql_sql_stmt_prepare");
LINT_INIT(query_len);
- DBUG_ASSERT(thd->protocol == &thd->protocol_text);
+ // XXX: DBUG_ASSERT(thd->protocol == &thd->protocol_text);
if ((stmt= (Prepared_statement*) thd->stmt_map.find_by_name(name)))
{
@@ -2244,11 +2252,13 @@ void mysql_sql_stmt_prepare(THD *thd)
}
if (! (query= get_dynamic_sql_string(lex, &query_len)) ||
- ! (stmt= new Prepared_statement(thd, &thd->protocol_text)))
+ ! (stmt= new Prepared_statement(thd)))
{
DBUG_VOID_RETURN; /* out of memory */
}
+ stmt->set_sql_prepare();
+
/* Set the name first, insert should know that this statement has a name */
if (stmt->set_name(name))
{
@@ -2428,6 +2438,7 @@ void mysql_stmt_execute(THD *thd, char *
String expanded_query;
uchar *packet_end= packet + packet_length;
Prepared_statement *stmt;
+ Protocol *save_protocol= thd->protocol;
bool open_cursor;
DBUG_ENTER("mysql_stmt_execute");
@@ -2455,7 +2466,9 @@ void mysql_stmt_execute(THD *thd, char *
open_cursor= test(flags & (ulong) CURSOR_TYPE_READ_ONLY);
+ thd->protocol= &thd->protocol_binary;
stmt->execute_loop(&expanded_query, open_cursor, packet, packet_end);
+ thd->protocol= save_protocol;
DBUG_VOID_RETURN;
}
@@ -2508,7 +2521,6 @@ void mysql_sql_stmt_execute(THD *thd)
DBUG_VOID_RETURN;
}
-
/**
COM_STMT_FETCH handler: fetches requested amount of rows from cursor.
@@ -2751,6 +2763,117 @@ void mysql_stmt_get_longdata(THD *thd, c
DBUG_VOID_RETURN;
}
+/**************************************************************************
+ Execute direct.
+**************************************************************************/
+
+bool save_warn_list(THD *thd,
+ MEM_ROOT *mem_root,
+ List<MYSQL_ERROR> *warn_list)
+{
+ init_sql_alloc(mem_root, ALLOC_ROOT_MIN_BLOCK_SIZE, 0);
+
+ List_iterator_fast<MYSQL_ERROR> it(thd->warn_list);
+
+ while (true)
+ {
+ MYSQL_ERROR *err= it++;
+
+ if (!err)
+ break;
+
+ MYSQL_ERROR *err_copy= new (mem_root) MYSQL_ERROR(mem_root, err);
+
+ if (!err_copy || warn_list->push_back(err_copy, mem_root))
+ return TRUE;
+ }
+}
+
+void restore_warn_list(THD *thd,
+ MEM_ROOT *mem_root,
+ List<MYSQL_ERROR> *warn_list)
+{
+ List_iterator_fast<MYSQL_ERROR> it(*warn_list);
+
+ mysql_reset_errors(thd, TRUE);
+ while (true)
+ {
+ MYSQL_ERROR *err= it++;
+
+ if (!err)
+ break;
+
+ push_warning(thd, err->level, err->code, err->msg);
+ }
+
+ free_root(mem_root, MYF(0));
+}
+
+static bool
+mysql_execute_direct_impl(THD *thd, const LEX_STRING *query, Protocol *p)
+{
+ MEM_ROOT tmp_mem_root;
+ List<MYSQL_ERROR> warn_list_saved;
+
+ if (save_warn_list(thd, &tmp_mem_root, &warn_list_saved))
+ return TRUE;
+
+ mysql_reset_thd_for_next_command(thd);
+ mysql_reset_errors(thd, TRUE);
+
+ Prepared_statement *stmt= new Prepared_statement(thd);
+
+ if (!stmt)
+ return TRUE;
+
+ sp_cache_flush_obsolete(&thd->sp_proc_cache);
+ sp_cache_flush_obsolete(&thd->sp_func_cache);
+
+#if defined(ENABLED_PROFILING)
+ thd->profiling.set_query_source(query->str, query->length);
+#endif
+
+ Protocol *protocol_saved= thd->protocol;
+ thd->protocol= p;
+
+ bool rc= stmt->execute_immediate(query->str, query->length);
+ rc= thd->protocol->on_end_statement() || rc;
+
+ thd->protocol= protocol_saved;
+
+ delete stmt;
+
+ restore_warn_list(thd, &tmp_mem_root, &warn_list_saved);
+
+ return rc;
+}
+
+/**
+ Execute one SQL statement.
+
+ @param thd Thread handle.
+ @param query Query to execute.
+*/
+
+bool mysql_execute_direct(THD *thd, const LEX_STRING *query, Ed_result *result)
+{
+ bool rc;
+
+ if (result)
+ {
+ Protocol_local p(thd, result);
+ rc= mysql_execute_direct_impl(thd, query, &p);
+ }
+ else
+ {
+ Protocol_void p(thd);
+ rc= mysql_execute_direct_impl(thd, query, &p);
+ }
+
+ thd->main_da.reset_diagnostics_area();
+
+ return rc;
+}
/***************************************************************************
Select_fetch_protocol_binary
@@ -2801,12 +2924,11 @@ Select_fetch_protocol_binary::send_data(
Prepared_statement
****************************************************************************/
-Prepared_statement::Prepared_statement(THD *thd_arg, Protocol *protocol_arg)
+Prepared_statement::Prepared_statement(THD *thd_arg)
:Statement(NULL, &main_mem_root,
INITIALIZED, ++thd_arg->statement_id_counter),
thd(thd_arg),
result(thd_arg),
- protocol(protocol_arg),
param_array(0),
param_count(0),
last_errno(0),
@@ -2895,7 +3017,8 @@ void Prepared_statement::cleanup_stmt()
DBUG_ENTER("Prepared_statement::cleanup_stmt");
DBUG_PRINT("enter",("stmt: %p", this));
- DBUG_ASSERT(lex->sphead == 0);
+ delete lex->sphead;
+ lex->sphead= 0;
/* The order is important */
lex->unit.cleanup();
cleanup_items(free_list);
@@ -3008,6 +3131,7 @@ bool Prepared_statement::prepare(const c
Parser_state parser_state(thd, thd->query, thd->query_length);
parser_state.m_lip.stmt_prepare_mode= TRUE;
+ parser_state.m_lip.multi_statements= FALSE;
lex_start(thd);
error= parse_sql(thd, & parser_state, NULL) ||
@@ -3246,6 +3370,73 @@ reexecute:
}
+
+bool
+Prepared_statement::execute_immediate(const char *query, uint length)
+{
+ Statement stmt_backup;
+ bool error;
+
+ state= CONVENTIONAL_EXECUTION;
+
+ if (!(lex = new (mem_root) st_lex_local))
+ return TRUE;
+
+ thd->set_n_backup_statement(this, &stmt_backup);
+
+ if (alloc_query(thd, query, length))
+ {
+ thd->set_statement(&stmt_backup);
+ return TRUE;
+ }
+ /*
+ Expanded query is needed for slow logging, so we want thd->query
+ to point at it even after we restore from backup. This is ok, as
+ expanded query was allocated in thd->mem_root.
+ */
+ stmt_backup.query= thd->query;
+ stmt_backup.query_length= thd->query_length;
+
+ Parser_state parser_state(thd, thd->query, thd->query_length);
+
+ parser_state.m_lip.multi_statements= FALSE;
+ lex_start(thd);
+
+ error= parse_sql(thd, &parser_state, NULL) || thd->is_error();
+
+ if (lex->sql_command == SQLCOM_PREPARE || lex->sql_command == SQLCOM_EXECUTE)
+ {
+ my_error(ER_PS_NO_RECURSION, MYF(0));
+ error= 1;
+ }
+
+ if (error)
+ {
+ thd->set_statement(&stmt_backup);
+ return TRUE;
+ }
+
+ lex->set_trg_event_type_for_tables();
+
+ if (query_cache_send_result_to_client(thd, thd->query,
+ thd->query_length) <= 0)
+ {
+ error= mysql_execute_command(thd);
+ }
+
+ cleanup_stmt();
+ lex_end(thd->lex);
+
+ thd->set_statement(&stmt_backup);
+
+ if (error == 0 && thd->spcont == NULL)
+ general_log_write(thd, COM_STMT_EXECUTE,
+ thd->query, thd->query_length);
+
+ return error;
+}
+
+
/**
Reprepare this prepared statement.
@@ -3269,7 +3460,9 @@ Prepared_statement::reprepare()
bool cur_db_changed;
bool error;
- Prepared_statement copy(thd, &thd->protocol_text);
+ Prepared_statement copy(thd);
+
+ copy.set_sql_prepare(); /* To suppress sending metadata to the client. */
status_var_increment(thd->status_var.com_stmt_reprepare);
@@ -3327,7 +3520,7 @@ bool Prepared_statement::validate_metada
return FALSE -- the metadata of the original SELECT,
if any, has not been sent to the client.
*/
- if (is_protocol_text() || lex->describe)
+ if (is_sql_prepare() || lex->describe)
return FALSE;
if (lex->select_lex.item_list.elements !=
@@ -3390,7 +3583,6 @@ Prepared_statement::swap_prepared_statem
DBUG_ASSERT(thd == copy->thd);
last_error[0]= '\0';
last_errno= 0;
- /* Do not swap protocols, the copy always has protocol_text */
}
@@ -3429,6 +3621,8 @@ bool Prepared_statement::execute(String
LEX_STRING stmt_db_name= { db, db_length };
+ // XXX: DBUG_ASSERT(thd->protocol == &thd->protocol_binary);
+
status_var_increment(thd->status_var.com_stmt_execute);
/* Check if we got an error when sending long data */
@@ -3531,8 +3725,6 @@ bool Prepared_statement::execute(String
thd->stmt_arena= this;
reinit_stmt_before_use(thd, lex);
- thd->protocol= protocol; /* activate stmt protocol */
-
/* Go! */
if (open_cursor)
@@ -3570,8 +3762,6 @@ bool Prepared_statement::execute(String
if (cur_db_changed)
mysql_change_db(thd, &saved_cur_db_name, TRUE);
- thd->protocol= &thd->protocol_text; /* use normal protocol */
-
/* Assert that if an error, no cursor is open */
DBUG_ASSERT(! (error && cursor));
@@ -3585,7 +3775,13 @@ bool Prepared_statement::execute(String
state= Query_arena::EXECUTED;
if (this->lex->sql_command == SQLCOM_CALL)
- protocol->send_out_parameters(&this->lex->param_list);
+ {
+ if (is_sql_prepare())
+ thd->protocol_text.send_out_parameters(&this->lex->param_list);
+ else
+ thd->protocol->send_out_parameters(&this->lex->param_list);
+ }
+
/*
Log COM_EXECUTE to the general log. Note, that in case of SQL
=== modified file 'sql/sql_yacc.yy'
--- a/sql/sql_yacc.yy 2008-11-06 18:39:27 +0000
+++ b/sql/sql_yacc.yy 2008-11-13 19:34:18 +0000
@@ -1485,7 +1485,7 @@ query:
Lex_input_stream *lip = YYLIP;
if ((YYTHD->client_capabilities & CLIENT_MULTI_QUERIES) &&
- ! lip->stmt_prepare_mode &&
+ lip->multi_statements &&
! lip->eof())
{
/*
| Thread |
|---|
| • bzr commit into mysql-6.0-runtime branch (kostja:2745) | Konstantin Osipov | 13 Nov |