2751 Alexander Nozdrin 2008-11-19
Draft patch for WL#4264.
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/Makefile.am
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/mysql_priv.h.pp
sql/protocol.cc
sql/protocol.h
sql/share/errmsg.txt
sql/si_objects.cc
sql/si_objects.h
sql/sql_lex.cc
sql/sql_lex.h
sql/sql_prepare.cc
sql/sql_yacc.yy
2750 Konstantin Osipov 2008-11-19
Fix a build failure in pushbuild, sapsrv1.
modified:
include/m_string.h
include/my_sys.h
sql/sql_list.h
2749 Konstantin Osipov 2008-11-19
Wl#4264 "Backup: Stabilize Service Interface", a prerequisite patch:
move Warning_info class declaration and implementation from
sql_class.{h,cc} to sql_error.{h,cc} and make sql_error.h a
self-sufficient header.
modified:
sql/sql_class.cc
sql/sql_class.h
sql/sql_error.cc
sql/sql_error.h
sql/sql_list.cc
sql/sql_list.h
2748 Konstantin Osipov 2008-11-18
WL#4264 "Backup: Stabilize Service Interface", a prerequisite
patch: use Protocol::end_statement() instead of net_end_statement().
This allows to intercept OK, EOF and ERROR packets in the protocol,
and thus redirect all interactaion between the client and the server
through the abstraction of this class.
Committing on behalf of Alexander Nozdrin.
modified:
libmysqld/lib_sql.cc
sql/protocol.cc
sql/protocol.h
sql/sp_head.cc
sql/sql_connect.cc
sql/sql_parse.cc
2747 Konstantin Osipov 2008-11-18
WL#4264 "Backup: Stabilize Service Interface", a prerequisite patch:
make THD::warning_info a pointer, so that
it can easily point to an external Warning_info object.
Committing on behalf of Alexander Nozdrin
modified:
libmysqld/emb_qcache.cc
libmysqld/lib_sql.cc
sql/backup/kernel.cc
sql/event_scheduler.cc
sql/field.cc
sql/ha_ndbcluster_binlog.cc
sql/log_event.cc
sql/protocol.cc
sql/set_var.cc
sql/slave.cc
sql/sp.cc
sql/sql_base.cc
sql/sql_class.cc
sql/sql_class.h
sql/sql_error.cc
sql/sql_insert.cc
sql/sql_load.cc
sql/sql_parse.cc
sql/sql_prepare.cc
sql/sql_select.cc
sql/sql_show.cc
sql/sql_table.cc
sql/sql_update.cc
sql/time.cc
2746 Konstantin Osipov 2008-11-18
WL#4264 "Backup: Stabilize Service Interface": update a falcon
test to have "more correct" row numbers in warnings.
Neither old nor new row numbers were meaningful, since the execution
is performing index retrieval, and we get rows in index order.
modified:
mysql-test/suite/falcon/r/falcon_bug_28049.result
mysql-test/suite/falcon/r/falcon_bugs.result
2745 Konstantin Osipov 2008-11-14
A pre-requisite patch for WL#4264 "Backup: Stabilize Service Interface"
Move all warning-related information to Warning_info structure,
to be able to reset and restore this structure.
modified:
libmysqld/emb_qcache.cc
libmysqld/lib_sql.cc
mysql-test/r/query_cache.result
sql/backup/kernel.cc
sql/event_scheduler.cc
sql/field.cc
sql/ha_ndbcluster_binlog.cc
sql/handler.cc
sql/log.cc
sql/log_event.cc
sql/mysqld.cc
sql/protocol.cc
sql/set_var.cc
sql/slave.cc
sql/sp.cc
sql/sp_rcontext.cc
sql/sp_rcontext.h
sql/sql_acl.cc
sql/sql_base.cc
sql/sql_class.cc
sql/sql_class.h
sql/sql_error.cc
sql/sql_error.h
sql/sql_insert.cc
sql/sql_load.cc
sql/sql_parse.cc
sql/sql_prepare.cc
sql/sql_select.cc
sql/sql_show.cc
sql/sql_table.cc
sql/sql_update.cc
sql/time.cc
sql/unireg.cc
=== modified file 'include/m_string.h'
--- a/include/m_string.h 2008-06-26 18:29:30 +0000
+++ b/include/m_string.h 2008-11-19 12:53:52 +0000
@@ -383,4 +383,10 @@ static inline const uchar *skip_trailing
return (end);
}
-#endif
+#ifdef SAFEMALLOC
+#define TRASH(A,B) bfill(A, B, 0x8F)
+#else
+#define TRASH(A,B) /* nothing */
+#endif /* SAFEMALLOC */
+
+#endif /* _m_string_h */
=== modified file 'include/my_sys.h'
--- a/include/my_sys.h 2008-10-20 19:13:22 +0000
+++ b/include/my_sys.h 2008-11-19 12:53:52 +0000
@@ -150,7 +150,6 @@ extern int NEAR my_errno; /* Last error
#define my_memdup(A,B,C) _my_memdup((A),(B), __FILE__,__LINE__,C)
#define my_strdup(A,C) _my_strdup((A), __FILE__,__LINE__,C)
#define my_strndup(A,B,C) _my_strndup((A),(B),__FILE__,__LINE__,C)
-#define TRASH(A,B) bfill(A, B, 0x8F)
#define QUICK_SAFEMALLOC sf_malloc_quick=1
#define NORMAL_SAFEMALLOC sf_malloc_quick=0
extern uint sf_malloc_prehunc,sf_malloc_endhunc,sf_malloc_quick;
@@ -178,7 +177,6 @@ extern char *my_strndup(const char *from
#define CALLER_INFO_PROTO /* nothing */
#define CALLER_INFO /* nothing */
#define ORIG_CALLER_INFO /* nothing */
-#define TRASH(A,B) /* nothing */
#endif
#ifdef HAVE_LARGE_PAGES
=== modified file 'libmysql/libmysql.c'
--- a/libmysql/libmysql.c 2008-10-22 11:51:28 +0000
+++ b/libmysql/libmysql.c 2008-11-19 16:32:01 +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 'libmysqld/emb_qcache.cc'
--- a/libmysqld/emb_qcache.cc 2008-11-14 20:45:00 +0000
+++ b/libmysqld/emb_qcache.cc 2008-11-18 19:41:51 +0000
@@ -484,7 +484,7 @@ int emb_load_querycache_result(THD *thd,
data->embedded_info->prev_ptr= prev_row;
return_ok:
net_send_eof(thd, thd->server_status,
- thd->warning_info.statement_warn_count());
+ thd->warning_info->statement_warn_count());
DBUG_RETURN(0);
err:
DBUG_RETURN(1);
=== modified file 'libmysqld/lib_sql.cc'
--- a/libmysqld/lib_sql.cc 2008-11-14 20:45:00 +0000
+++ b/libmysqld/lib_sql.cc 2008-11-18 20:25:51 +0000
@@ -208,7 +208,7 @@ static my_bool emb_read_prepare_result(M
stmt->stmt_id= thd->client_stmt_id;
stmt->param_count= thd->client_param_count;
stmt->field_count= 0;
- mysql->warning_count= thd->warning_info.statement_warn_count();
+ mysql->warning_count= thd->warning_info->statement_warn_count();
if (thd->first_data)
{
@@ -646,7 +646,7 @@ int check_embedded_connection(MYSQL *mys
strmake(sctx->priv_host, (char*) my_localhost, MAX_HOSTNAME-1);
sctx->priv_user= sctx->user= my_strdup(mysql->user, MYF(0));
result= check_user(thd, COM_CONNECT, NULL, 0, db, true);
- net_end_statement(thd);
+ thd->protocol->end_statement();
emb_read_query_result(mysql);
return result;
}
@@ -971,7 +971,7 @@ bool Protocol::send_result_set_metadata(
if (flags & SEND_EOF)
write_eof_packet(thd, thd->server_status,
- thd->warning_info.statement_warn_count());
+ thd->warning_info->statement_warn_count());
DBUG_RETURN(prepare_for_send(list->elements));
err:
=== 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-19 16:32:01 +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-19 16:32:01 +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-19 16:32:01 +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-19 16:32:01 +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-19 16:32:01 +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-19 16:32:01 +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-19 16:32:01 +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 'mysql-test/suite/falcon/r/falcon_bug_28049.result'
--- a/mysql-test/suite/falcon/r/falcon_bug_28049.result 2007-09-20 15:44:25 +0000
+++ b/mysql-test/suite/falcon/r/falcon_bug_28049.result 2008-11-18 15:42:54 +0000
@@ -2018,69 +2018,69 @@ v
v
999
Warnings:
-Warning 1264 Out of range value for column 's1' at row 3
-Warning 1264 Out of range value for column 's1' at row 3
Warning 1264 Out of range value for column 's1' at row 4
-Warning 1264 Out of range value for column 's1' at row 3
Warning 1264 Out of range value for column 's1' at row 4
-Warning 1264 Out of range value for column 's1' at row 3
+Warning 1264 Out of range value for column 's1' at row 5
Warning 1264 Out of range value for column 's1' at row 4
-Warning 1264 Out of range value for column 's1' at row 3
+Warning 1264 Out of range value for column 's1' at row 5
Warning 1264 Out of range value for column 's1' at row 4
-Warning 1264 Out of range value for column 's1' at row 3
+Warning 1264 Out of range value for column 's1' at row 5
Warning 1264 Out of range value for column 's1' at row 4
-Warning 1264 Out of range value for column 's1' at row 3
+Warning 1264 Out of range value for column 's1' at row 5
Warning 1264 Out of range value for column 's1' at row 4
-Warning 1264 Out of range value for column 's1' at row 3
+Warning 1264 Out of range value for column 's1' at row 5
Warning 1264 Out of range value for column 's1' at row 4
-Warning 1264 Out of range value for column 's1' at row 3
+Warning 1264 Out of range value for column 's1' at row 5
Warning 1264 Out of range value for column 's1' at row 4
-Warning 1264 Out of range value for column 's1' at row 3
+Warning 1264 Out of range value for column 's1' at row 5
Warning 1264 Out of range value for column 's1' at row 4
-Warning 1264 Out of range value for column 's1' at row 3
+Warning 1264 Out of range value for column 's1' at row 5
Warning 1264 Out of range value for column 's1' at row 4
-Warning 1264 Out of range value for column 's1' at row 3
+Warning 1264 Out of range value for column 's1' at row 5
Warning 1264 Out of range value for column 's1' at row 4
-Warning 1264 Out of range value for column 's1' at row 3
+Warning 1264 Out of range value for column 's1' at row 5
Warning 1264 Out of range value for column 's1' at row 4
-Warning 1264 Out of range value for column 's1' at row 3
+Warning 1264 Out of range value for column 's1' at row 5
Warning 1264 Out of range value for column 's1' at row 4
-Warning 1264 Out of range value for column 's1' at row 3
+Warning 1264 Out of range value for column 's1' at row 5
Warning 1264 Out of range value for column 's1' at row 4
-Warning 1264 Out of range value for column 's1' at row 3
+Warning 1264 Out of range value for column 's1' at row 5
Warning 1264 Out of range value for column 's1' at row 4
-Warning 1264 Out of range value for column 's1' at row 3
+Warning 1264 Out of range value for column 's1' at row 5
Warning 1264 Out of range value for column 's1' at row 4
-Warning 1264 Out of range value for column 's1' at row 3
+Warning 1264 Out of range value for column 's1' at row 5
Warning 1264 Out of range value for column 's1' at row 4
-Warning 1264 Out of range value for column 's1' at row 3
+Warning 1264 Out of range value for column 's1' at row 5
Warning 1264 Out of range value for column 's1' at row 4
-Warning 1264 Out of range value for column 's1' at row 3
+Warning 1264 Out of range value for column 's1' at row 5
Warning 1264 Out of range value for column 's1' at row 4
-Warning 1264 Out of range value for column 's1' at row 3
+Warning 1264 Out of range value for column 's1' at row 5
Warning 1264 Out of range value for column 's1' at row 4
-Warning 1264 Out of range value for column 's1' at row 3
+Warning 1264 Out of range value for column 's1' at row 5
Warning 1264 Out of range value for column 's1' at row 4
-Warning 1264 Out of range value for column 's1' at row 3
+Warning 1264 Out of range value for column 's1' at row 5
Warning 1264 Out of range value for column 's1' at row 4
-Warning 1264 Out of range value for column 's1' at row 3
+Warning 1264 Out of range value for column 's1' at row 5
Warning 1264 Out of range value for column 's1' at row 4
-Warning 1264 Out of range value for column 's1' at row 3
+Warning 1264 Out of range value for column 's1' at row 5
Warning 1264 Out of range value for column 's1' at row 4
-Warning 1264 Out of range value for column 's1' at row 3
+Warning 1264 Out of range value for column 's1' at row 5
Warning 1264 Out of range value for column 's1' at row 4
-Warning 1264 Out of range value for column 's1' at row 3
+Warning 1264 Out of range value for column 's1' at row 5
Warning 1264 Out of range value for column 's1' at row 4
-Warning 1264 Out of range value for column 's1' at row 3
+Warning 1264 Out of range value for column 's1' at row 5
Warning 1264 Out of range value for column 's1' at row 4
-Warning 1264 Out of range value for column 's1' at row 3
+Warning 1264 Out of range value for column 's1' at row 5
Warning 1264 Out of range value for column 's1' at row 4
-Warning 1264 Out of range value for column 's1' at row 3
+Warning 1264 Out of range value for column 's1' at row 5
Warning 1264 Out of range value for column 's1' at row 4
-Warning 1264 Out of range value for column 's1' at row 3
+Warning 1264 Out of range value for column 's1' at row 5
Warning 1264 Out of range value for column 's1' at row 4
-Warning 1264 Out of range value for column 's1' at row 2
-Warning 1264 Out of range value for column 's1' at row 3
+Warning 1264 Out of range value for column 's1' at row 5
+Warning 1264 Out of range value for column 's1' at row 4
+Warning 1264 Out of range value for column 's1' at row 5
Warning 1264 Out of range value for column 's1' at row 3
+Warning 1264 Out of range value for column 's1' at row 4
+Warning 1264 Out of range value for column 's1' at row 4
DROP TABLE t1//
DROP PROCEDURE p//
=== modified file 'mysql-test/suite/falcon/r/falcon_bugs.result'
--- a/mysql-test/suite/falcon/r/falcon_bugs.result 2008-10-02 21:05:39 +0000
+++ b/mysql-test/suite/falcon/r/falcon_bugs.result 2008-11-18 15:42:54 +0000
@@ -3183,70 +3183,70 @@ v
v
999
Warnings:
-Warning 1264 Out of range value for column 's1' at row 3
-Warning 1264 Out of range value for column 's1' at row 3
Warning 1264 Out of range value for column 's1' at row 4
-Warning 1264 Out of range value for column 's1' at row 3
Warning 1264 Out of range value for column 's1' at row 4
-Warning 1264 Out of range value for column 's1' at row 3
+Warning 1264 Out of range value for column 's1' at row 5
Warning 1264 Out of range value for column 's1' at row 4
-Warning 1264 Out of range value for column 's1' at row 3
+Warning 1264 Out of range value for column 's1' at row 5
Warning 1264 Out of range value for column 's1' at row 4
-Warning 1264 Out of range value for column 's1' at row 3
+Warning 1264 Out of range value for column 's1' at row 5
Warning 1264 Out of range value for column 's1' at row 4
-Warning 1264 Out of range value for column 's1' at row 3
+Warning 1264 Out of range value for column 's1' at row 5
Warning 1264 Out of range value for column 's1' at row 4
-Warning 1264 Out of range value for column 's1' at row 3
+Warning 1264 Out of range value for column 's1' at row 5
Warning 1264 Out of range value for column 's1' at row 4
-Warning 1264 Out of range value for column 's1' at row 3
+Warning 1264 Out of range value for column 's1' at row 5
Warning 1264 Out of range value for column 's1' at row 4
-Warning 1264 Out of range value for column 's1' at row 3
+Warning 1264 Out of range value for column 's1' at row 5
Warning 1264 Out of range value for column 's1' at row 4
-Warning 1264 Out of range value for column 's1' at row 3
+Warning 1264 Out of range value for column 's1' at row 5
Warning 1264 Out of range value for column 's1' at row 4
-Warning 1264 Out of range value for column 's1' at row 3
+Warning 1264 Out of range value for column 's1' at row 5
Warning 1264 Out of range value for column 's1' at row 4
-Warning 1264 Out of range value for column 's1' at row 3
+Warning 1264 Out of range value for column 's1' at row 5
Warning 1264 Out of range value for column 's1' at row 4
-Warning 1264 Out of range value for column 's1' at row 3
+Warning 1264 Out of range value for column 's1' at row 5
Warning 1264 Out of range value for column 's1' at row 4
-Warning 1264 Out of range value for column 's1' at row 3
+Warning 1264 Out of range value for column 's1' at row 5
Warning 1264 Out of range value for column 's1' at row 4
-Warning 1264 Out of range value for column 's1' at row 3
+Warning 1264 Out of range value for column 's1' at row 5
Warning 1264 Out of range value for column 's1' at row 4
-Warning 1264 Out of range value for column 's1' at row 3
+Warning 1264 Out of range value for column 's1' at row 5
Warning 1264 Out of range value for column 's1' at row 4
-Warning 1264 Out of range value for column 's1' at row 3
+Warning 1264 Out of range value for column 's1' at row 5
Warning 1264 Out of range value for column 's1' at row 4
-Warning 1264 Out of range value for column 's1' at row 3
+Warning 1264 Out of range value for column 's1' at row 5
Warning 1264 Out of range value for column 's1' at row 4
-Warning 1264 Out of range value for column 's1' at row 3
+Warning 1264 Out of range value for column 's1' at row 5
Warning 1264 Out of range value for column 's1' at row 4
-Warning 1264 Out of range value for column 's1' at row 3
+Warning 1264 Out of range value for column 's1' at row 5
Warning 1264 Out of range value for column 's1' at row 4
-Warning 1264 Out of range value for column 's1' at row 3
+Warning 1264 Out of range value for column 's1' at row 5
Warning 1264 Out of range value for column 's1' at row 4
-Warning 1264 Out of range value for column 's1' at row 3
+Warning 1264 Out of range value for column 's1' at row 5
Warning 1264 Out of range value for column 's1' at row 4
-Warning 1264 Out of range value for column 's1' at row 3
+Warning 1264 Out of range value for column 's1' at row 5
Warning 1264 Out of range value for column 's1' at row 4
-Warning 1264 Out of range value for column 's1' at row 3
+Warning 1264 Out of range value for column 's1' at row 5
Warning 1264 Out of range value for column 's1' at row 4
-Warning 1264 Out of range value for column 's1' at row 3
+Warning 1264 Out of range value for column 's1' at row 5
Warning 1264 Out of range value for column 's1' at row 4
-Warning 1264 Out of range value for column 's1' at row 3
+Warning 1264 Out of range value for column 's1' at row 5
Warning 1264 Out of range value for column 's1' at row 4
-Warning 1264 Out of range value for column 's1' at row 3
+Warning 1264 Out of range value for column 's1' at row 5
Warning 1264 Out of range value for column 's1' at row 4
-Warning 1264 Out of range value for column 's1' at row 3
+Warning 1264 Out of range value for column 's1' at row 5
Warning 1264 Out of range value for column 's1' at row 4
-Warning 1264 Out of range value for column 's1' at row 3
+Warning 1264 Out of range value for column 's1' at row 5
Warning 1264 Out of range value for column 's1' at row 4
-Warning 1264 Out of range value for column 's1' at row 3
+Warning 1264 Out of range value for column 's1' at row 5
Warning 1264 Out of range value for column 's1' at row 4
-Warning 1264 Out of range value for column 's1' at row 2
-Warning 1264 Out of range value for column 's1' at row 3
+Warning 1264 Out of range value for column 's1' at row 5
+Warning 1264 Out of range value for column 's1' at row 4
+Warning 1264 Out of range value for column 's1' at row 5
Warning 1264 Out of range value for column 's1' at row 3
+Warning 1264 Out of range value for column 's1' at row 4
+Warning 1264 Out of range value for column 's1' at row 4
DROP TABLE t1//
DROP PROCEDURE p//
*** Bug 216 ***
=== modified file 'sql/Makefile.am'
--- a/sql/Makefile.am 2008-11-06 18:39:27 +0000
+++ b/sql/Makefile.am 2008-11-19 16:32:01 +0000
@@ -57,6 +57,7 @@ SUPPORTING_LIBS = $(top_builddir)/vio/li
$(top_builddir)/strings/libmystrings.a
mysqld_DEPENDENCIES= @mysql_plugin_libs@ $(SUPPORTING_LIBS) backup/libbackup.la libndb.la
LDADD = $(SUPPORTING_LIBS) @ZLIB_LIBS@ @NDB_SCI_LIBS@
+mysqld_CXXFLAGS = -Werror
mysqld_LDADD = libndb.la \
@MYSQLD_EXTRA_LDFLAGS@ \
@pstack_libs@ $(libevent_libs) \
=== 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-19 16:32:01 +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-19 16:32:01 +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-19 16:32:01 +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-19 16:32:01 +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-19 16:32:01 +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-14 20:45:00 +0000
+++ b/sql/backup/kernel.cc 2008-11-19 16:32:01 +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
@@ -490,7 +491,7 @@ int Backup_restore_ctx::prepare(String *
// Prepare error reporting context.
- m_thd->warning_info.opt_clear_warning_info(m_thd->query_id); // Never errors
+ m_thd->warning_info->opt_clear_warning_info(m_thd->query_id); // Never errors
m_thd->no_warnings_for_error= FALSE;
save_errors(); // Never errors
@@ -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-19 16:32:01 +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-19 16:32:01 +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-19 16:32:01 +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/event_scheduler.cc'
--- a/sql/event_scheduler.cc 2008-11-14 20:45:00 +0000
+++ b/sql/event_scheduler.cc 2008-11-18 19:41:51 +0000
@@ -74,7 +74,7 @@ Event_worker_thread::print_warnings(THD
{
MYSQL_ERROR *err;
DBUG_ENTER("evex_print_warnings");
- if (thd->warning_info.is_empty())
+ if (thd->warning_info->is_empty())
DBUG_VOID_RETURN;
char msg_buf[10 * STRING_BUFFER_USUAL_SIZE];
@@ -90,7 +90,7 @@ Event_worker_thread::print_warnings(THD
prefix.append(et->name.str, et->name.length, system_charset_info);
prefix.append("] ", 2);
- List_iterator_fast<MYSQL_ERROR> it(thd->warning_info.warn_list());
+ List_iterator_fast<MYSQL_ERROR> it(thd->warning_info->warn_list());
while ((err= it++))
{
String err_msg(msg_buf, sizeof(msg_buf), system_charset_info);
=== modified file 'sql/field.cc'
--- a/sql/field.cc 2008-11-14 20:45:00 +0000
+++ b/sql/field.cc 2008-11-18 19:41:51 +0000
@@ -1116,7 +1116,7 @@ int Field_num::check_int(CHARSET_INFO *c
ER_TRUNCATED_WRONG_VALUE_FOR_FIELD,
ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD),
"integer", tmp.c_ptr(), field_name,
- table->in_use->warning_info.current_row_for_warning());
+ table->in_use->warning_info->current_row_for_warning());
return 1;
}
/* Test if we have garbage at the end of the given string. */
@@ -2599,7 +2599,7 @@ int Field_new_decimal::store(const char
ER_TRUNCATED_WRONG_VALUE_FOR_FIELD,
ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD),
"decimal", from_as_str.c_ptr(), field_name,
- table->in_use->warning_info.current_row_for_warning());
+ table->in_use->warning_info->current_row_for_warning());
DBUG_RETURN(err);
}
@@ -2622,7 +2622,7 @@ int Field_new_decimal::store(const char
ER_TRUNCATED_WRONG_VALUE_FOR_FIELD,
ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD),
"decimal", from_as_str.c_ptr(), field_name,
- table->in_use->warning_info.current_row_for_warning());
+ table->in_use->warning_info->current_row_for_warning());
my_decimal_set_zero(&decimal_value);
break;
@@ -5168,7 +5168,7 @@ bool Field_time::get_date(MYSQL_TIME *lt
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARN_DATA_OUT_OF_RANGE,
ER(ER_WARN_DATA_OUT_OF_RANGE), field_name,
- thd->warning_info.current_row_for_warning());
+ thd->warning_info->current_row_for_warning());
return 1;
}
tmp=(long) sint3korr(ptr);
@@ -6204,7 +6204,7 @@ check_string_copy_error(Field_str *field
ER_TRUNCATED_WRONG_VALUE_FOR_FIELD,
ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD),
"string", tmp, field->field_name,
- thd->warning_info.current_row_for_warning());
+ thd->warning_info->current_row_for_warning());
return TRUE;
}
@@ -10108,7 +10108,7 @@ Field::set_warning(MYSQL_ERROR::enum_war
{
thd->cuted_fields+= cuted_increment;
push_warning_printf(thd, level, code, ER(code), field_name,
- thd->warning_info.current_row_for_warning());
+ thd->warning_info->current_row_for_warning());
return 0;
}
return level >= MYSQL_ERROR::WARN_LEVEL_WARN;
=== modified file 'sql/ha_ndbcluster_binlog.cc'
--- a/sql/ha_ndbcluster_binlog.cc 2008-11-14 20:45:00 +0000
+++ b/sql/ha_ndbcluster_binlog.cc 2008-11-18 19:41:51 +0000
@@ -1899,7 +1899,7 @@ ndb_binlog_thread_handle_schema_event(TH
"my_errno: %d",
schema->db, schema->name, schema->query,
schema->node_id, my_errno);
- List_iterator_fast<MYSQL_ERROR> it(thd->warning_info.warn_list());
+ List_iterator_fast<MYSQL_ERROR>
it(thd->warning_info->warn_list());
MYSQL_ERROR *err;
while ((err= it++))
sql_print_warning("NDB Binlog: (%d)%s", err->code, err->msg);
@@ -2259,7 +2259,7 @@ ndb_binlog_thread_handle_schema_event_po
"binlog schema event '%s' from node %d. my_errno: %d",
schema->db, schema->name, schema->query,
schema->node_id, my_errno);
- List_iterator_fast<MYSQL_ERROR> it(thd->warning_info.warn_list());
+ List_iterator_fast<MYSQL_ERROR>
it(thd->warning_info->warn_list());
MYSQL_ERROR *err;
while ((err= it++))
sql_print_warning("NDB Binlog: (%d)%s", err->code, err->msg);
@@ -2438,7 +2438,7 @@ ndb_binlog_thread_handle_schema_event_po
"binlog schema event '%s' from node %d. my_errno: %d",
schema->db, schema->name, schema->query,
schema->node_id, my_errno);
- List_iterator_fast<MYSQL_ERROR> it(thd->warning_info.warn_list());
+ List_iterator_fast<MYSQL_ERROR>
it(thd->warning_info->warn_list());
MYSQL_ERROR *err;
while ((err= it++))
sql_print_warning("NDB Binlog: (%d)%s", err->code, err->msg);
=== modified file 'sql/log.cc'
--- a/sql/log.cc 2008-11-14 20:45:00 +0000
+++ b/sql/log.cc 2008-11-19 16:32:01 +0000
@@ -918,8 +918,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/log_event.cc'
--- a/sql/log_event.cc 2008-11-14 20:45:00 +0000
+++ b/sql/log_event.cc 2008-11-18 19:41:51 +0000
@@ -133,7 +133,7 @@ static void inline slave_rows_error_repo
char buff[MAX_SLAVE_ERRMSG], *slider;
const char *buff_end= buff + sizeof(buff);
uint len;
- List_iterator_fast<MYSQL_ERROR> it(thd->warning_info.warn_list());
+ List_iterator_fast<MYSQL_ERROR> it(thd->warning_info->warn_list());
MYSQL_ERROR *err;
buff[0]= 0;
@@ -4369,7 +4369,7 @@ int Load_log_event::do_apply_event(NET*
pthread_mutex_lock(&LOCK_thread_count);
thd->query_id = next_query_id();
pthread_mutex_unlock(&LOCK_thread_count);
- thd->warning_info.opt_clear_warning_info(thd->query_id);
+ thd->warning_info->opt_clear_warning_info(thd->query_id);
TABLE_LIST tables;
bzero((char*) &tables,sizeof(tables));
=== 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-19 16:32:01 +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);
=== modified file 'sql/mysql_priv.h.pp'
--- a/sql/mysql_priv.h.pp 2008-07-11 13:08:06 +0000
+++ b/sql/mysql_priv.h.pp 2008-11-19 16:32:01 +0000
@@ -7672,7 +7672,6 @@ public:
};
void send_warning(THD *thd, uint sql_errno, const char *err=0);
void net_send_error(THD *thd, uint sql_errno=0, const char *err=0);
-void net_end_statement(THD *thd);
In_C_you_should_use_my_bool_instead() send_old_password_request(THD *thd);
uchar *net_store_data(uchar *to,const uchar *from, size_t length);
uchar *net_store_data(uchar *to,int32 from);
=== modified file 'sql/protocol.cc'
--- a/sql/protocol.cc 2008-11-14 20:45:00 +0000
+++ b/sql/protocol.cc 2008-11-19 16:32:01 +0000
@@ -28,9 +28,10 @@
#include <stdarg.h>
static const unsigned int PACKET_BUFFER_EXTRA_ALLOC= 1024;
-/* Declared non-static only because of the embedded library. */
void net_send_error_packet(THD *thd, uint sql_errno, const char *err);
+/* Declared non-static only because of the embedded library. */
void net_send_ok(THD *, uint, uint, ha_rows, ulonglong, const char *);
+/* Declared non-static only because of the embedded library. */
void net_send_eof(THD *thd, uint server_status, uint statement_warn_count);
#ifndef EMBEDDED_LIBRARY
static void write_eof_packet(THD *thd, NET *net,
@@ -417,6 +418,12 @@ static uchar *net_store_length_fast(ucha
packet is "buffered" in the diagnostics area and sent to the client
in the end of statement.
+ @note This method defines a template, but delegates actual
+ sending of data to virtual Protocol::send_{ok,eof,error}. This
+ allows for implementation of protocols that "intercept" ok/eof/error
+ messages, and store them in memory, etc, instead of sending to
+ the client.
+
@pre The diagnostics area is assigned or disabled. It can not be empty
-- we assume that every SQL statement or COM_* command
generates OK, ERROR, or EOF status.
@@ -431,41 +438,38 @@ static uchar *net_store_length_fast(ucha
Diagnostics_area::is_sent is set for debugging purposes only.
*/
-void net_end_statement(THD *thd)
+void Protocol::end_statement()
{
- DBUG_ENTER("net_end_statement");
+ DBUG_ENTER("Protocol::end_statement");
DBUG_ASSERT(! thd->main_da.is_sent);
/* Can not be true, but do not take chances in production. */
if (thd->main_da.is_sent)
- return;
+ DBUG_VOID_RETURN;
switch (thd->main_da.status()) {
case Diagnostics_area::DA_ERROR:
/* The query failed, send error to log and abort bootstrap. */
- net_send_error(thd,
- thd->main_da.sql_errno(),
- thd->main_da.message());
+ send_error(thd->main_da.sql_errno(),
+ thd->main_da.message());
break;
case Diagnostics_area::DA_EOF:
- net_send_eof(thd,
- thd->main_da.server_status(),
- thd->main_da.statement_warn_count());
+ send_eof(thd->main_da.server_status(),
+ thd->main_da.statement_warn_count());
break;
case Diagnostics_area::DA_OK:
- net_send_ok(thd,
- thd->main_da.server_status(),
- thd->main_da.statement_warn_count(),
- thd->main_da.affected_rows(),
- thd->main_da.last_insert_id(),
- thd->main_da.message());
+ send_ok(thd->main_da.server_status(),
+ thd->main_da.statement_warn_count(),
+ thd->main_da.affected_rows(),
+ thd->main_da.last_insert_id(),
+ thd->main_da.message());
break;
case Diagnostics_area::DA_DISABLED:
break;
case Diagnostics_area::DA_EMPTY:
default:
DBUG_ASSERT(0);
- net_send_ok(thd, thd->server_status, 0, 0, 0, NULL);
+ send_ok(thd->server_status, 0, 0, 0, NULL);
break;
}
thd->main_da.is_sent= TRUE;
@@ -473,6 +477,60 @@ void net_end_statement(THD *thd)
}
+/**
+ A default implementation of "OK" packet response to the client.
+
+ Currently this implementation is re-used by both network-oriented
+ protocols -- the binary and text one. They do not differ
+ in their OK packet format, which allows for a significant simplification
+ on client side.
+*/
+
+void Protocol::send_ok(uint server_status, uint statement_warn_count,
+ ha_rows affected_rows, ulonglong last_insert_id,
+ const char *message)
+{
+ DBUG_ENTER("Protocol::send_ok");
+
+ net_send_ok(thd, server_status, statement_warn_count, affected_rows,
+ last_insert_id, message);
+
+ DBUG_VOID_RETURN;
+}
+
+
+/**
+ A default implementation of "EOF" packet response to the client.
+
+ Binary and text protocol do not differ in their EOF packet format.
+*/
+
+void Protocol::send_eof(uint server_status, uint statement_warn_count)
+{
+ DBUG_ENTER("Protocol::send_eof");
+
+ net_send_eof(thd, server_status, statement_warn_count);
+
+ DBUG_VOID_RETURN;
+}
+
+
+/**
+ A default implementation of "ERROR" packet response to the client.
+
+ Binary and text protocol do not differ in ERROR packet format.
+*/
+
+void Protocol::send_error(uint sql_errno, const char *err_msg)
+{
+ DBUG_ENTER("Protocol::send_error");
+
+ net_send_error_packet(thd, sql_errno, err_msg);
+
+ DBUG_VOID_RETURN;
+}
+
+
/****************************************************************************
Functions used by the protocol functions (like net_send_ok) to store
strings and numbers in the header result packet.
@@ -702,7 +760,7 @@ bool Protocol::send_result_set_metadata(
Send no warning information, as it will be sent at statement end.
*/
write_eof_packet(thd, &thd->net, thd->server_status,
- thd->warning_info.statement_warn_count());
+ thd->warning_info->statement_warn_count());
}
DBUG_RETURN(prepare_for_send(list->elements));
@@ -800,7 +858,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 +1474,460 @@ bool Protocol_binary::send_out_parameter
return FALSE;
}
+
+///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
+
+Ed_result::Ed_result(MEM_ROOT *mem_root) :
+ m_mem_root(mem_root),
+ m_current_result_set(NULL),
+ m_status(Diagnostics_area::DA_EMPTY),
+ m_server_status(0),
+ m_affected_rows(0),
+ m_last_insert_id(0),
+ m_sql_errno(0),
+ m_warning_info_saved(NULL)
+{
+ 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_current_result_set= rs;
+
+ return push_back(rs, m_mem_root) ? TRUE : FALSE;
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+void Ed_result::send_ok(THD *thd,
+ uint server_status, uint statement_warn_count,
+ ha_rows affected_rows, ulonglong last_insert_id,
+ const char *message)
+{
+ DBUG_ENTER("Ed_result::send_ok()");
+ DBUG_ASSERT(m_status == Diagnostics_area::DA_EMPTY);
+
+ m_status= thd->main_da.status();
+ DBUG_ASSERT(m_status == Diagnostics_area::DA_OK);
+
+ DBUG_ASSERT(m_warning_info.statement_warn_count() == statement_warn_count);
+
+ m_server_status= server_status;
+ m_affected_rows= affected_rows;
+ m_last_insert_id= last_insert_id;
+
+ strmake(m_message, message, sizeof (m_message) - 1);
+
+ DBUG_VOID_RETURN;
+}
+
+void Ed_result::send_eof(THD *thd, uint server_status,
+ uint statement_warn_count)
+{
+ DBUG_ENTER("Ed_result::send_eof");
+ DBUG_ASSERT(m_status == Diagnostics_area::DA_EMPTY);
+
+ m_status= thd->main_da.status();
+ DBUG_ASSERT(m_status == Diagnostics_area::DA_EOF);
+
+ DBUG_ASSERT(m_warning_info.statement_warn_count() == statement_warn_count);
+
+ m_server_status= server_status;
+
+ DBUG_VOID_RETURN;
+}
+
+void Ed_result::send_error(THD *thd, uint sql_errno, const char *err_msg)
+{
+ DBUG_ENTER("Ed_result::send_error()");
+ DBUG_ASSERT(m_status == Diagnostics_area::DA_EMPTY);
+
+ m_status= thd->main_da.status();
+ DBUG_ASSERT(m_status == Diagnostics_area::DA_ERROR);
+
+ m_sql_errno= sql_errno;
+ strmake(m_message, err_msg, sizeof (m_message) - 1);
+
+ DBUG_VOID_RETURN;
+}
+
+void Ed_result::begin_statement(THD *thd)
+{
+ DBUG_ASSERT(!m_warning_info_saved);
+
+ m_warning_info_saved= thd->warning_info;
+ thd->warning_info= &m_warning_info;
+}
+
+void Ed_result::end_statement(THD *thd)
+{
+ DBUG_ASSERT(m_warning_info_saved);
+ thd->warning_info= m_warning_info_saved;
+}
+
+///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
+
+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_current_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_current_column_index >= m_metadata->get_num_columns())
+ return TRUE;
+
+ ++m_current_column_index;
+
+ return FALSE;
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+bool Ed_row::add_column(const void *data_ptr, int data_length)
+{
+ if (m_current_column_index >= m_metadata->get_num_columns())
+ return TRUE;
+
+ m_columns[m_current_column_index++].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();
+ Ed_row *row= rs->get_cur_row();
+
+ /* TODO: check medata type. */
+
+ 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();
+ Ed_row *row= rs->get_cur_row();
+
+ /* TODO: check medata type. */
+
+ 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();
+ Ed_row *row= rs->get_cur_row();
+
+ /* TODO: check medata type. */
+
+ 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();
+ Ed_row *row= rs->get_cur_row();
+
+ /* TODO: check medata type. */
+
+ 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();
+ Ed_row *row= rs->get_cur_row();
+
+ /* TODO: check medata type. */
+
+ 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();
+ Ed_row *row= rs->get_cur_row();
+
+ /* TODO: check medata type. */
+
+ 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();
+ Ed_row *row= rs->get_cur_row();
+
+ /* TODO: check medata type. */
+
+ 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();
+ Ed_row *row= rs->get_cur_row();
+
+ /* TODO: check medata type. */
+
+ 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();
+ Ed_row *row= rs->get_cur_row();
+
+ /* TODO: check medata type. */
+
+ 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();
+ Ed_row *row= rs->get_cur_row();
+
+ /* TODO: check medata type. */
+
+ 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;
+}
+
+void Protocol_local::send_ok(uint server_status, uint statement_warn_count,
+ ha_rows affected_rows, ulonglong last_insert_id,
+ const char *message)
+{
+ m_result->send_ok(thd, server_status, statement_warn_count,
+ affected_rows, last_insert_id, message);
+}
+
+void Protocol_local::send_eof(uint server_status, uint statement_warn_count)
+{
+ m_result->send_eof(thd, server_status, statement_warn_count);
+}
+
+void Protocol_local::send_error(uint sql_errno, const char *err_msg)
+{
+ m_result->send_error(thd, sql_errno, err_msg);
+}
+
+#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-19 16:32:01 +0000
@@ -17,6 +17,7 @@
#pragma interface /* gcc class implementation */
#endif
+#include "sql_error.h"
class i_string;
class THD;
@@ -47,6 +48,15 @@ protected:
CHARSET_INFO *fromcs, CHARSET_INFO *tocs);
bool store_string_aux(const char *from, size_t length,
CHARSET_INFO *fromcs, CHARSET_INFO *tocs);
+
+ virtual void send_ok(uint server_status, uint statement_warn_count,
+ ha_rows affected_rows, ulonglong last_insert_id,
+ const char *message);
+
+ virtual void send_eof(uint server_status, uint statement_warn_count);
+
+ virtual void send_error(uint sql_errno, const char *err_msg);
+
public:
Protocol() {}
Protocol(THD *thd_arg) { init(thd_arg); }
@@ -114,6 +124,8 @@ public:
*/
};
virtual enum enum_protocol_type type()= 0;
+
+ void end_statement();
};
@@ -185,9 +197,270 @@ public:
void send_warning(THD *thd, uint sql_errno, const char *err=0);
void net_send_error(THD *thd, uint sql_errno=0, const char *err=0);
-void net_end_statement(THD *thd);
bool send_old_password_request(THD *thd);
uchar *net_store_data(uchar *to,const uchar *from, size_t length);
uchar *net_store_data(uchar *to,int32 from);
uchar *net_store_data(uchar *to,longlong from);
+///////////////////////////////////////////////////////////////////////////
+
+/**
+ 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_current_column_index() const
+ { return m_current_column_index; }
+
+private:
+ inline Ed_row(MEM_ROOT *mem_root,
+ const Ed_result_set_metadata *metadata) :
+ m_mem_root(mem_root),
+ m_metadata(metadata),
+ m_current_column_index(0)
+ { }
+
+ bool init();
+
+private:
+ MEM_ROOT *m_mem_root;
+ const Ed_result_set_metadata *m_metadata;
+ Ed_column *m_columns;
+ int m_current_column_index;
+};
+
+///////////////////////////////////////////////////////////////////////////
+
+/**
+ 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_current_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_current_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_current_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_current_result_set; }
+
+ bool add_result_set(List<Item> *col_metadata);
+
+public:
+ void send_ok(THD *thd, uint server_status, uint statement_warn_count,
+ ha_rows affected_rows, ulonglong last_insert_id,
+ const char *message);
+
+ void send_eof(THD *thd, uint server_status, uint statement_warn_count);
+
+ void send_error(THD *thd, uint sql_errno, const char *err_msg);
+
+ void begin_statement(THD *thd);
+ void end_statement(THD *thd);
+
+public:
+ inline uint get_status() const { return m_status; }
+ inline uint get_server_status() const { return m_server_status; }
+ 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 uint get_statement_warn_count() const
+ { return m_warning_info.statement_warn_count(); }
+
+ inline List<MYSQL_ERROR> &get_warnings()
+ { return m_warning_info.warn_list(); }
+
+private:
+ MEM_ROOT *m_mem_root;
+ Ed_result_set *m_current_result_set;
+
+private:
+ uint m_status;
+ uint m_server_status;
+ ha_rows m_affected_rows;
+ ulonglong m_last_insert_id;
+ uint m_sql_errno;
+ char m_message[MYSQL_ERRMSG_SIZE];
+
+ Warning_info m_warning_info;
+ Warning_info *m_warning_info_saved;
+};
+
+///////////////////////////////////////////////////////////////////////////
+
+/**
+ 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 */ };
+
+protected:
+ virtual void send_ok(uint server_status, uint statement_warn_count,
+ ha_rows affected_rows, ulonglong last_insert_id,
+ const char *message);
+
+ virtual void send_eof(uint server_status, uint statement_warn_count);
+
+ virtual void send_error(uint sql_errno, const char *err_msg);
+
+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/set_var.cc'
--- a/sql/set_var.cc 2008-11-14 20:45:00 +0000
+++ b/sql/set_var.cc 2008-11-18 19:41:51 +0000
@@ -3434,14 +3434,14 @@ static int check_pseudo_thread_id(THD *t
static uchar *get_warning_count(THD *thd)
{
- thd->sys_var_tmp.long_value= thd->warning_info.warn_count();
+ thd->sys_var_tmp.long_value= thd->warning_info->warn_count();
return (uchar*) &thd->sys_var_tmp.long_value;
}
static uchar *get_error_count(THD *thd)
{
- thd->sys_var_tmp.long_value= thd->warning_info.error_count();
+ thd->sys_var_tmp.long_value= thd->warning_info->error_count();
return (uchar*) &thd->sys_var_tmp.long_value;
}
=== 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-19 16:32:01 +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-19 16:32:01 +0000
@@ -26,1611 +26,1310 @@
#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
+///////////////////////////////////////////////////////////////////////////
+//
+// Type identifiers in INFORMATION_SCHEMA.
+//
+///////////////////////////////////////////////////////////////////////////
+
+const LEX_STRING IS_TYPE_TABLE= { C_STRING_WITH_LEN("BASE TABLE") };
+const LEX_STRING IS_TYPE_VIEW= { C_STRING_WITH_LEN("VIEW") };
-/**
- Execute the SQL string passed.
+///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
- This is a private helper function to the implementation.
-*/
-int silent_exec(THD *thd, String *query)
+bool run_query(THD *thd, const LEX_STRING *query, Ed_result *result)
{
- Vio *save_vio= thd->net.vio;
+ DBUG_ENTER("run_query()");
+ DBUG_PRINT("run_query",
+ ("query: %.*s",
+ (int) query->length, (const char *) query->str));
- DBUG_PRINT("si_objects",("executing %s",query->c_ptr()));
+ 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;
- /*
- 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);
+ thd->variables.sql_mode= 0;
/*
- @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.
+ Temporary tables should be ignored while looking for table structures.
+ Backup wants to backup ordinary tables, not temporary ones.
*/
- thd->DDL_exception= TRUE;
+ TABLE *tmp_tables_saved= thd->temporary_tables;
+ thd->temporary_tables= NULL;
+
+ /* A query is in UTF8 (internal character set). */
+ thd->variables.character_set_client= system_charset_info;
/*
- Note: This is a copy and paste from the code in sql_parse.cc.
- See "case COM_QUERY:".
+ Ed_results should be fetched without any conversion (in the original
+ character set) in order to preserve object definition query intact.
*/
- 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);
+ thd->variables.character_set_results= &my_charset_bin;
+ thd->variables.collation_connection= system_charset_info;
+ thd->update_charset();
- /* 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);
- }
+ bool rc= mysql_execute_direct(thd, query, result);
- close_thread_tables(thd);
+ 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();
- thd->net.vio= save_vio;
+ thd->temporary_tables= tmp_tables_saved;
- if (thd->is_error())
+ 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,
+ uint table_name_length)
{
- 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;
+ db_name.copy(db_name_str, db_name_length, system_charset_info);
+ table_name.copy(table_name_str, table_name_length, system_charset_info);
+
+ key.length(0);
+ key.append(db_name);
+ key.append(".");
+ key.append(table_name);
}
- return 0;
+public:
+ String db_name;
+ String table_name;
+
+ String key;
+};
+
+///////////////////////////////////////////////////////////////////////////
+
+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();
}
-/*
- 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 Table_name_key::delete_key(void *data)
{
- 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();
+ Table_name_key *tnk= (Table_name_key *) data;
+ delete tnk;
+}
- /*
- 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("'; ");
+class Fmt
+{
+public:
+ Fmt(const char *format, ...);
- /*
- append collation_connection information
- */
- string->append("SET COLLATION_CONNECTION = '");
- string->append(sp_ctx->get_connection_cl()->name);
- string->append("'; ");
+public:
+ const char *str() const { return m_buffer; }
+ int length() const { return m_length; }
- /*
- append collation_connection information
- */
- string->append("SET COLLATION_DATABASE = '");
- string->append(sp_ctx->get_db_cl()->name);
- string->append("'; ");
+private:
+ char m_buffer[QUERY_BUFFER_SIZE];
+ int m_length;
+};
- string->append(sp->m_defstr.str);
- }
- else
- {
- string->length(0);
- ret= TRUE;
- }
- if (type == TYPE_ENUM_PROCEDURE)
- thd->variables.max_sp_recursion_depth--;
- DBUG_RETURN(ret);
+///////////////////////////////////////////////////////////////////////////
+
+Fmt::Fmt(const char *format, ...)
+{
+ va_list args;
+
+ va_start(args, format);
+ m_length= my_vsnprintf(m_buffer, sizeof (m_buffer), format, args);
+ va_end(args);
}
-/*
- 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)
+class Out_stream
{
- 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()");
+public:
+ Out_stream(String *serialization) :
+ m_serialization(serialization)
+ { }
- /*
- 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;
+public:
+ 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);
- /*
- Preserve timezone.
- */
- if (save_timezone)
- tm_zone= thd->variables.time_zone;
+private:
+ String *m_serialization;
+};
- 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;
+Out_stream &Out_stream::operator <<(const char *query)
+{
+ LEX_STRING str= { (char *) query, strlen(query) };
+ return Out_stream::operator <<(&str);
+}
- /*
- Restore timezone.
- */
- if (save_timezone)
- thd->variables.time_zone= tm_zone;
+///////////////////////////////////////////////////////////////////////////
- DBUG_RETURN(ret);
+Out_stream &Out_stream::operator <<(const LEX_STRING *query)
+{
+ char chunk_buffer[QUERY_BUFFER_SIZE];
+ LEX_STRING chunk;
+
+ 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);
+
+ m_serialization->append(chunk.str, chunk.length);
+
+ return *this;
}
-/*
- Drops an object.
+///////////////////////////////////////////////////////////////////////////
- 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)
+Out_stream &Out_stream::operator <<(const String &query)
{
- 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(".");
- }
- append_identifier(thd, &cmd, name2->c_ptr(), name2->length());
- DBUG_RETURN(silent_exec(thd, &cmd));
+ LEX_STRING str= { (char *) query.ptr(), query.length() };
+ return Out_stream::operator <<(&str);
}
-/**
- 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
+Out_stream &Out_stream::operator <<(const Fmt &query)
+{
+ LEX_STRING str= { (char *) query.str(), query.length() };
+ return Out_stream::operator <<(&str);
+}
- @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)
+class In_stream
{
- TABLE *t;
- TABLE_LIST arg;
- my_bitmap_map *old_map;
-
- bzero( &arg, sizeof(TABLE_LIST) );
+public:
+ 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())
+ { }
- // set context for create_schema_table call
- arg.schema_table= st;
- arg.alias= NULL;
- arg.select_lex= NULL;
+public:
+ uint serialization_version() const { return m_serialization_version; }
+public:
+ bool next(LEX_STRING *chunk);
- t= create_schema_table(thd,&arg); // Note: callers must free t.
+private:
+ uint m_serialization_version;
+ const String *m_serialization;
+ const char *m_read_ptr;
+ const char *m_end_ptr;
+};
- if( !t ) return NULL; // error!
+///////////////////////////////////////////////////////////////////////////
- /*
- Temporarily set thd->lex->wild to NULL to keep st->fill_table
- happy.
- */
- ::String *wild= thd->lex->wild;
- ::enum_sql_command command= thd->lex->sql_command;
+bool In_stream::next(LEX_STRING *chunk)
+{
+ if (m_read_ptr >= m_end_ptr)
+ return TRUE;
- thd->lex->wild = NULL;
- thd->lex->sql_command = enum_sql_command(0);
+ const char *delimiter_ptr=
+ my_strchr(system_charset_info, m_read_ptr, m_end_ptr, ' ');
- // context for fill_table
- arg.table= t;
+ if (!delimiter_ptr)
+ {
+ m_read_ptr= m_end_ptr;
+ return TRUE;
+ }
- old_map= tmp_use_all_columns(t, t->read_set);
+ char buffer[STRING_BUFFER_USUAL_SIZE];
+ int n= delimiter_ptr - m_read_ptr;
- /*
- Create a selection condition only if db_list is defined.
- */
- if (db_list)
- st->fill_table(thd, &arg, obs::create_db_select_condition(thd, t, db_list));
- else
- st->fill_table(thd, &arg, NULL);
+ memcpy(buffer, m_read_ptr, n);
+ buffer[n]= 0;
- tmp_restore_column_map(t->read_set, old_map);
+ chunk->str= (char *) delimiter_ptr + 1;
+ chunk->length= atoi(buffer);
- // undo changes to thd->lex
- thd->lex->wild= wild;
- thd->lex->sql_command= command;
+ m_read_ptr+= n /* chunk length */
+ + 1 /* delimiter (a space) */
+ + chunk->length /* chunk */
+ + 1; /* chunk delimiter (\n) */
- return t;
+ return FALSE;
}
-/*
- 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;
+///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
+
+#define STR(x) x.length(), x.ptr()
+#define LXS(x) x->length, x->str
+
+///////////////////////////////////////////////////////////////////////////
+
}
///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
-struct Table_name_key
+namespace obs {
+
+///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
+
+class Abstract_obj : public Obj
{
- Table_name_key(const char *db_name_str,
- uint db_name_length,
- const char *table_name_str,
- uint table_name_length)
- {
- db_name.copy(db_name_str, db_name_length, system_charset_info);
- table_name.copy(table_name_str, table_name_length, system_charset_info);
+public:
+ virtual bool serialize(THD *thd, String *serialization);
- key.length(0);
- key.append(db_name);
- key.append(".");
- key.append(table_name);
- }
+ virtual bool execute(THD *thd);
- String db_name;
- String table_name;
+protected:
+ virtual bool materialize(uint serialization_version,
+ const String *serialization);
- String key;
+ virtual bool do_materialize(In_stream *is);
+
+ /**
+ Primitive implementing @c serialize() method.
+ */
+ virtual bool do_serialize(THD *thd, Out_stream &os) = 0;
+
+protected:
+ MEM_ROOT m_mem_root; /* This mem-root is for keeping stmt list. */
+ List<String> m_stmt_lst;
+
+protected:
+ Abstract_obj();
+ virtual ~Abstract_obj();
+
+private:
+ Abstract_obj(const Abstract_obj &);
+ Abstract_obj &operator =(const Abstract_obj &);
};
-uchar *
-get_table_name_key(const uchar *record,
- size_t *key_length,
- my_bool not_used __attribute__((unused)))
+///////////////////////////////////////////////////////////////////////////
+
+Abstract_obj::Abstract_obj()
{
- Table_name_key *tnk= (Table_name_key *) record;
- *key_length= tnk->key.length();
- return (uchar *) tnk->key.c_ptr_safe();
+ init_sql_alloc(&m_mem_root, ALLOC_ROOT_MIN_BLOCK_SIZE, 0);
}
-void delete_table_name_key(void *data)
+///////////////////////////////////////////////////////////////////////////
+
+Abstract_obj::~Abstract_obj()
{
- Table_name_key *tnk= (Table_name_key *) data;
- delete tnk;
+ free_root(&m_mem_root, MYF(0));
}
+///////////////////////////////////////////////////////////////////////////
+
+/**
+ 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.
+*/
+
+bool Abstract_obj::serialize(THD *thd, String *serialization)
+{
+ ulong saved_sql_mode= thd->variables.sql_mode;
+ thd->variables.sql_mode= 0;
+
+ Out_stream os(serialization);
+
+ bool ret= do_serialize(thd, os);
+
+ thd->variables.sql_mode= saved_sql_mode;
+
+ return ret;
}
///////////////////////////////////////////////////////////////////////////
-namespace obs {
-
/**
- Build a where clause for list of databases.
+ Create the object in the database.
- 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()");
+ @param[in] thd Server thread context.
+ @return error status.
+ @retval FALSE on success.
+ @retval TRUE on error.
+*/
+
+bool Abstract_obj::execute(THD *thd)
+{
/*
- If no list of databases, just return NULL
+ 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.
*/
- if (!db_list->elements)
- DBUG_RETURN(NULL);
+
+ ulong saved_sql_mode= thd->variables.sql_mode;
+ thd->variables.sql_mode= 0;
/*
- Build an inclusion list in the form of 'a', 'b', etc.
+ NOTE: other session variables are not preserved, so backup query must
+ take care to clean up the environment after itself.
*/
- while ((db= it++))
+
+ bool rc;
+ List_iterator_fast<String> it(m_stmt_lst);
+ while (true)
{
- 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);
+ String *stmt= it++;
+
+ if (!stmt)
+ break;
+
+ LEX_STRING query= { (char *) stmt->ptr(), stmt->length() };
+
+ rc= mysql_execute_direct(thd, &query, NULL);
+
+ /* Ignore warnings from materialization for now. */
+
+ if (rc)
+ break;
}
- /*
- 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);
+ thd->variables.sql_mode= saved_sql_mode;
- /*
- 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();
+ return rc == TRUE;
+}
- DBUG_RETURN(in_cond);
+///////////////////////////////////////////////////////////////////////////
+
+bool Abstract_obj::materialize(uint serialization_version,
+ const String *serialization)
+{
+ m_stmt_lst.delete_elements();
+
+ In_stream is(serialization_version, serialization);
+
+ return do_materialize(&is);
}
///////////////////////////////////////////////////////////////////////////
-//
-// Implementation: object impl classes.
-//
+bool Abstract_obj::do_materialize(In_stream *is)
+{
+ while (true)
+ {
+ LEX_STRING stmt;
+
+ if (is->next(&stmt))
+ break;
+
+ String *s= new (&m_mem_root) String();
+
+ if (!s ||
+ s->copy(stmt.str, stmt.length, system_charset_info) ||
+ m_stmt_lst.push_back(s))
+ return TRUE;
+ }
+
+ return FALSE;
+}
///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
/**
- @class DatabaseObj
+ @class Database_obj
This class provides an abstraction to a database object for creation and
capture of the creation data.
*/
-class DatabaseObj : public Obj
+
+class Database_obj : public Abstract_obj
{
public:
- DatabaseObj(const String *db_name);
+ Database_obj(const char *db_name_str, int db_name_length);
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;
- }
+ virtual inline const String *get_name() const { return &m_db_name; }
+ virtual inline const String *get_db_name() const { return &m_db_name; }
private:
- // These attributes are to be used only for serialization.
+ /* 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);
-
-private:
- // These attributes are to be used only for materialization.
- String m_create_stmt;
+ virtual bool do_serialize(THD *thd, Out_stream &os);
};
///////////////////////////////////////////////////////////////////////////
/**
- @class TableObj
+ @class Table_obj
This class provides an abstraction to a table object for creation and
capture of the creation data.
*/
-class TableObj : public Obj
+
+class Table_obj : public Abstract_obj
{
public:
- TableObj(const String *db_name,
- const String *table_name,
- bool table_is_view);
+ Table_obj(const char *db_name_str, int db_name_length,
+ const char *table_name_str, int table_name_length);
public:
- virtual bool materialize(uint serialization_version,
- const String *serialization);
-
- const String* get_name()
- { return &m_table_name; }
-
- const String *get_db_name()
- {
- return &m_db_name;
- }
+ virtual inline const String *get_name() const { return &m_table_name; }
+ virtual inline const String *get_db_name() const { return &m_db_name; }
private:
- // These attributes are to be used only for serialization.
+ /* These attributes are to be used only for serialization. */
String m_db_name;
String m_table_name;
- bool m_table_is_view;
- bool drop(THD *thd);
- virtual bool do_serialize(THD *thd, String *serialization);
- virtual bool do_execute(THD *thd);
+ virtual bool do_serialize(THD *thd, Out_stream &os);
+};
-private:
- // These attributes are to be used only for materialization.
- String m_create_stmt;
+///////////////////////////////////////////////////////////////////////////
+
+/**
+ @class View_obj
+
+ This class provides an abstraction to a view object for creation and
+ capture of the creation data.
+*/
+
+class View_obj : public Abstract_obj
+{
+public:
+ View_obj(const char *db_name_str, int db_name_length,
+ const char *view_name_str, int view_name_length);
+
+public:
+ virtual inline const String *get_name() const { return &m_view_name; }
+ virtual inline const String *get_db_name() const { return &m_db_name; }
private:
- bool serialize_table(THD *thd, String *serialization);
- bool serialize_view(THD *thd, String *serialization);
+ /* These attributes are to be used only for serialization. */
+ String m_db_name;
+ String m_view_name;
+
+ virtual bool do_serialize(THD *thd, Out_stream &os);
};
///////////////////////////////////////////////////////////////////////////
/**
- @class TriggerObj
+ @class Trigger_obj
This class provides an abstraction to a trigger object for creation and
capture of the creation data.
*/
-class TriggerObj : public Obj
+
+class Trigger_obj : public Abstract_obj
{
public:
- TriggerObj(const String *db_name,
- const String *trigger_name);
+ Trigger_obj(const char *db_name_str, int db_name_length,
+ const char *trigger_name_str, int trigger_name_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;
- }
+ virtual inline const String *get_name() const { return &m_trigger_name; }
+ virtual inline const String *get_db_name() const { return &m_db_name; }
private:
- // These attributes are to be used only for serialization.
+ /* 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);
-
-private:
- // These attributes are to be used only for materialization.
- String m_create_stmt;
+ virtual bool do_serialize(THD *thd, Out_stream &os);
};
///////////////////////////////////////////////////////////////////////////
/**
- @class StoredProcObj
+ @class Stored_proc_obj
This class provides an abstraction to a stored procedure object for creation
and capture of the creation data.
*/
-class StoredProcObj : public Obj
+
+class Stored_proc_obj : public Abstract_obj
{
public:
- StoredProcObj(const String *db_name,
- const String *stored_proc_name);
+ Stored_proc_obj(const char *db_name_str, int db_name_length,
+ const char *sp_name_str, int sp_name_length);
public:
- virtual bool materialize(uint serialization_version,
- const String *serialization);
-
- const String* get_name()
- { return &m_stored_proc_name; }
-
- const String *get_db_name()
- {
- return &m_db_name;
- }
+ 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.
+ /* These attributes are to be used only for serialization. */
String m_db_name;
- String m_stored_proc_name;
+ String m_sp_name;
- bool drop(THD *thd);
- virtual bool do_serialize(THD *thd, String *serialization);
- virtual bool do_execute(THD *thd);
-
-private:
- // These attributes are to be used only for materialization.
- String m_create_stmt;
+ virtual bool do_serialize(THD *thd, Out_stream &os);
};
///////////////////////////////////////////////////////////////////////////
/**
- @class StoredFuncObj
+ @class Stored_func_obj
This class provides an abstraction to a stored function object for creation
and capture of the creation data.
*/
-class StoredFuncObj : public Obj
+
+class Stored_func_obj : public Abstract_obj
{
public:
- StoredFuncObj(const String *db_name,
- const String *stored_func_name);
+ Stored_func_obj(const char *db_name_str, int db_name_length,
+ const char *sf_name_str, int sf_name_length);
public:
- virtual bool materialize(uint serialization_version,
- const String *serialization);
-
- const String* get_name()
- { return &m_stored_func_name; }
-
- const String *get_db_name()
- {
- return &m_db_name;
- }
+ 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.
+ /* These attributes are to be used only for serialization. */
String m_db_name;
- String m_stored_func_name;
-
- bool drop(THD *thd);
- virtual bool do_serialize(THD *thd, String *serialization);
- virtual bool do_execute(THD *thd);
+ String m_sf_name;
-private:
- // These attributes are to be used only for materialization.
- String m_create_stmt;
+ virtual bool do_serialize(THD *thd, Out_stream &os);
};
///////////////////////////////////////////////////////////////////////////
+
#ifdef HAVE_EVENT_SCHEDULER
+
/**
- @class EventObj
+ @class Event_obj
This class provides an abstraction to a event object for creation and capture
of the creation data.
*/
-class EventObj : public Obj
+
+class Event_obj : public Abstract_obj
{
public:
- EventObj(const String *db_name,
- const String *event_name);
+ Event_obj(const char *db_name_str, int db_name_length,
+ const char *event_name_str, int event_name_length);
public:
- virtual bool materialize(uint serialization_version,
- const String *serialization);
-
- const String* get_name()
- { return &m_event_name; }
-
- const String *get_db_name()
- {
- return &m_db_name;
- }
+ 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.
+ /* These attributes are to be used only for serialization. */
String m_db_name;
String m_event_name;
- bool drop(THD *thd);
- virtual bool do_serialize(THD *thd, String *serialization);
- virtual bool do_execute(THD *thd);
-
-private:
- // These attributes are to be used only for materialization.
- String m_create_stmt;
+ virtual bool do_serialize(THD *thd, Out_stream &os);
};
-#endif // HAVE_EVENT_SCHEDULER
+
+#endif // HAVE_EVENT_SCHEDULER
+
+///////////////////////////////////////////////////////////////////////////
/**
- @class TablespaceObj
+ @class Tablespace_obj
- This class provides an abstraction to a user object for creation and
- capture of the creation data.
+ This class provides an abstraction to a user object for creation and
+ capture of the creation data.
*/
-class TablespaceObj : public Obj
-{
-public:
- TablespaceObj(const String *ts_name);
+class Tablespace_obj : public Abstract_obj
+{
public:
- virtual bool do_serialize(THD *thd, String *serialization);
-
- virtual bool materialize(uint serialization_version,
- const String *serialization);
-
- virtual bool do_execute(THD *thd);
-
- const String *describe();
-
- const String *build_serialization();
-
- /*
- The get_db_name primitive is not used for tablespaces.
- */
- const String *get_db_name() { return 0; }
-
- const String* get_name()
- { return &m_ts_name; }
+ 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);
- const String* get_datafile()
- { return &m_datafile; }
+ Tablespace_obj(const char *ts_name_str, int ts_name_length);
- const String* get_comments()
- { return &m_comments; }
-
- const String* get_engine()
- { return &m_engine; }
+public:
+ virtual inline const String *get_name() const { return &m_ts_name; }
+ virtual inline const String *get_db_name() const { return NULL; }
- void set_datafile(const String *df)
- { m_datafile.copy(*df); }
+ const String *get_description();
- void set_comments(const String *c)
- { m_comments.copy(*c); }
+protected:
+ virtual bool do_serialize(THD *thd, Out_stream &os);
- void set_engine(const String *engine)
- { m_engine.copy(*engine); }
+ virtual bool materialize(uint serialization_version,
+ const String *serialization);
private:
- // These attributes are to be used only for serialization.
+ /* These attributes are to be used only for serialization. */
String m_ts_name;
- String m_datafile;
- String m_comments;
+ String m_comment;
+ String m_data_file_name;
String m_engine;
- // Drop is not supported by this object.
- bool drop(THD *thd)
- { return 0; }
-
private:
- // These attributes are to be used only for materialization.
- String m_create_stmt;
+ String m_description;
};
+///////////////////////////////////////////////////////////////////////////
+
/**
- @class DbGrantObj
+ @class Grant_obj
- This class provides an abstraction to database-level grants.
- This class will permit the recording and replaying of these
- grants.
+ This class provides an abstraction to grants. This class will permit the
+ recording and replaying of these grants.
*/
-class DbGrantObj : public Obj
+
+class Grant_obj : public Abstract_obj
{
public:
- DbGrantObj(const String *grantee,
- const String *db_name,
- const String *priv_type);
+ static void generate_unique_id(const String *user_name,
+ const String *host_name,
+ String *id);
public:
- virtual bool materialize(uint serialization_version,
- const String *serialization);
+ Grant_obj(const char *id_str, int id_length);
- const String* get_name()
- {
- return &m_name;
- }
+ 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);
- const String *get_db_name()
- {
- return &m_db_name;
- }
+public:
+ virtual bool do_materialize(In_stream *is);
- const String *get_priv_type()
- {
- return &m_priv_type;
- }
+public:
+ virtual inline const String *get_name() const { return &m_id; }
+ virtual inline const String *get_db_name() const { return &m_id; }
-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.
+ 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; }
- bool drop(THD *thd) { return 0; }; // Drop not supported.
- virtual bool do_execute(THD *thd);
+protected:
+ /* 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:
- virtual bool do_serialize(THD *thd, String *serialization);
- // These attributes are to be used only for materialization.
- String m_grant_stmt;
+ virtual bool do_serialize(THD *thd, Out_stream &os);
};
-/**
- @class TblGrantObj
+///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
- This class provides an abstraction to table-level and routine-level grants.
- This class will permit the recording and replaying of these
- grants.
-*/
-class TblGrantObj : public DbGrantObj
+template <typename T>
+T *create_row_set_iterator(THD *thd, const LEX_STRING *query)
{
-public:
- TblGrantObj(const String *grantee,
- const String *db_name,
- const String *table_name,
- const String *priv_type);
-
-public:
+ Ed_result result(thd->mem_root);
- const String *get_table_name()
+ if (run_query(thd, query, &result) ||
+ result.get_warnings().elements > 0)
{
- return &m_table_name;
+ /* Should be no warnings. */
+ return NULL;
}
-protected:
- // These attributes are to be used only for serialization.
- String m_table_name; ///< corresponds with TABLE_NAME in IS tables.
+ DBUG_ASSERT(result.elements == 1);
+ Ed_result_set *rs= result.get_cur_result_set();
-private:
- virtual bool do_serialize(THD *thd, String *serialization);
+ DBUG_ASSERT(rs);
- // These attributes are to be used only for materialization.
- String m_grant_stmt;
-};
+ return new T(rs);
+}
-/**
- @class ColGrantObj
+///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
- This class provides an abstraction to column-level grants.
- This class will permit the recording and replaying of these
- grants.
-*/
-class ColGrantObj : public TblGrantObj
+class Ed_result_set_iterator : public Obj_iterator
{
-public:
- ColGrantObj(const String *grantee,
- const String *db_name,
- const String *table_name,
- const String *col_name,
- const String *priv_type);
-
-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.
-
-private:
- virtual bool do_serialize(THD *thd, String *serialization);
+ inline Ed_result_set_iterator(Ed_result_set *rs);
- // These attributes are to be used only for materialization.
- String m_grant_stmt;
+protected:
+ Ed_result_set *m_rs;
+ List_iterator_fast<Ed_row> m_row_it;
};
///////////////////////////////////////////////////////////////////////////
-//
-// Implementation: iterator impl classes.
-//
+inline Ed_result_set_iterator::Ed_result_set_iterator(Ed_result_set *rs)
+ : m_rs(rs),
+ m_row_it(*rs->data())
+{ }
///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
-class InformationSchemaIterator : public Obj_iterator
+class Database_iterator : public Ed_result_set_iterator
{
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)
- { }
+ static Database_iterator *create(THD *thd);
- virtual ~InformationSchemaIterator();
+public:
+ inline Database_iterator(Ed_result_set *rs)
+ :Ed_result_set_iterator(rs)
+ { }
public:
virtual Obj *next();
-
-protected:
- virtual Obj *create_obj(TABLE *t) = 0;
- THD *m_thd;
-
-private:
- TABLE *m_is_table;
- handler *m_ha;
- my_bitmap_map *m_orig_columns;
-
};
///////////////////////////////////////////////////////////////////////////
-class ObjIteratorDummyImpl : Obj_iterator
+Database_iterator *Database_iterator::create(THD *thd)
{
-public:
- ObjIteratorDummyImpl() { return; }
- virtual ~ObjIteratorDummyImpl() { return; }
- virtual Obj *next() { return NULL; }
+ 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 Obj *create_obj(TABLE *t) { return NULL; }
-
-};
+ return create_row_set_iterator<Database_iterator>(thd, &query);
+}
///////////////////////////////////////////////////////////////////////////
-class DatabaseIterator : public InformationSchemaIterator
-{
-public:
- DatabaseIterator(THD *thd,
- TABLE *is_table,
- handler *ha,
- my_bitmap_map *orig_columns) :
- InformationSchemaIterator(thd, is_table, ha, orig_columns)
- { }
-protected:
- virtual DatabaseObj *create_obj(TABLE *t);
-};
+template
+Database_iterator *
+create_row_set_iterator<Database_iterator>(THD *thd, const LEX_STRING *query);
///////////////////////////////////////////////////////////////////////////
-class DbTablesIterator : public InformationSchemaIterator
+Obj *Database_iterator::next()
{
-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);
- }
-
-protected:
- virtual TableObj *create_obj(TABLE *t);
-
- virtual bool is_type_accepted(const String *type) const;
+ Ed_row *row= m_row_it++;
- virtual bool is_engine_accepted(const String *engine) const;
+ if (!row)
+ return NULL;
- virtual TableObj *create_table_obj(const String *db_name,
- const String *table_name) const;
+ DBUG_ASSERT(row->get_metadata()->get_num_columns() == 1);
+ const Ed_column *db_name= row->get_column(0);
-private:
- String m_db_name;
-};
+ return new Database_obj(db_name->str, db_name->length);
+}
///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
-class DbViewsIterator : public DbTablesIterator
+class Db_tables_iterator : public Ed_result_set_iterator
{
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)
- { }
+ static Db_tables_iterator *create(THD *thd, const String *db_name);
-protected:
- virtual bool is_type_accepted(const String *type) const;
-
- virtual bool is_engine_accepted(const String *engine) const
- {
- return true;
- }
+public:
+ inline Db_tables_iterator(Ed_result_set *rs)
+ :Ed_result_set_iterator(rs)
+ { }
- virtual TableObj *create_table_obj(const String *db_name,
- const String *table_name) const;
+public:
+ virtual Obj *next();
};
///////////////////////////////////////////////////////////////////////////
-class DbTriggerIterator : public InformationSchemaIterator
+Db_tables_iterator *Db_tables_iterator::create(THD *thd, const String *db_name)
{
-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);
- }
+ char query_buffer[QUERY_BUFFER_SIZE];
+ LEX_STRING query;
-protected:
- virtual TriggerObj *create_obj(TABLE *t);
+ 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:
- String m_db_name;
-};
+ return create_row_set_iterator<Db_tables_iterator>(thd, &query);
+}
///////////////////////////////////////////////////////////////////////////
-class DbStoredProcIterator : public InformationSchemaIterator
-{
-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)
- {
- m_db_name.copy(*db_name);
- }
+template
+Db_tables_iterator *
+create_row_set_iterator<Db_tables_iterator>(THD *thd, const LEX_STRING *query);
-protected:
- virtual Obj *create_obj(TABLE *t);
+///////////////////////////////////////////////////////////////////////////
- virtual bool check_type(const String *sr_type) const;
+Obj *Db_tables_iterator::next()
+{
+ Ed_row *row= m_row_it++;
- virtual Obj *create_sr_object(const String *db_name,
- const String *sr_name);
+ if (!row)
+ return NULL;
-private:
- String m_db_name;
-};
+ DBUG_ASSERT(row->get_metadata()->get_num_columns() == 2);
-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);
- }
+ const Ed_column *db_name= row->get_column(0);
+ const Ed_column *table_name= row->get_column(1);
-protected:
- virtual DbGrantObj *create_obj(TABLE *t);
+ return new Table_obj(db_name->str, db_name->length,
+ table_name->str, table_name->length);
+}
-private:
- String m_db_name;
-};
+///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
-class TblGrantIterator : public InformationSchemaIterator
+class Db_views_iterator : public Ed_result_set_iterator
{
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);
- }
+ static Db_views_iterator *create(THD *thd, const String *db_name);
-protected:
- virtual TblGrantObj *create_obj(TABLE *t);
+public:
+ inline Db_views_iterator(Ed_result_set *rs)
+ :Ed_result_set_iterator(rs)
+ { }
-private:
- String m_db_name;
+public:
+ virtual Obj *next();
};
-class ColGrantIterator : public InformationSchemaIterator
+///////////////////////////////////////////////////////////////////////////
+
+Db_views_iterator *Db_views_iterator::create(THD *thd, const String *db_name)
{
-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);
- }
+ char query_buffer[QUERY_BUFFER_SIZE];
+ LEX_STRING query;
-protected:
- virtual ColGrantObj *create_obj(TABLE *t);
+ 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);
-private:
- String m_db_name;
-};
+ return create_row_set_iterator<Db_views_iterator>(thd, &query);
+}
+///////////////////////////////////////////////////////////////////////////
+
+template
+Db_views_iterator *
+create_row_set_iterator<Db_views_iterator>(THD *thd, const LEX_STRING *query);
///////////////////////////////////////////////////////////////////////////
-class DbStoredFuncIterator : public DbStoredProcIterator
+Obj *Db_views_iterator::next()
{
-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)
- { }
-
-protected:
- virtual bool check_type(const String *sr_type) const;
+ Ed_row *row= m_row_it++;
- virtual Obj *create_sr_object(const String *db_name,
- const String *sr_name);
-};
+ if (!row)
+ return NULL;
-///////////////////////////////////////////////////////////////////////////
-#ifdef HAVE_EVENT_SCHEDULER
-class DbEventIterator : public InformationSchemaIterator
-{
-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);
- }
+ DBUG_ASSERT(row->get_metadata()->get_num_columns() == 2);
-protected:
- virtual EventObj *create_obj(TABLE *t);
+ const Ed_column *db_name= row->get_column(0);
+ const Ed_column *view_name= row->get_column(1);
-private:
- String m_db_name;
-};
-#endif
+ return new View_obj(db_name->str, db_name->length,
+ view_name->str, view_name->length);
+}
///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
-class ViewBaseObjectsIterator : public Obj_iterator
+class Db_trigger_iterator : public Ed_result_set_iterator
{
public:
- enum IteratorType
- {
- GET_BASE_TABLES,
- GET_BASE_VIEWS
- };
+ static Db_trigger_iterator *create(THD *thd, const String *db_name);
public:
- virtual ~ViewBaseObjectsIterator();
+ inline Db_trigger_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_trigger_iterator *Db_trigger_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', 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());
-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_trigger_iterator>(thd, &query);
+}
///////////////////////////////////////////////////////////////////////////
-//
-// Implementation: InformationSchemaIterator class.
-//
+template
+Db_trigger_iterator *
+create_row_set_iterator<Db_trigger_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_trigger_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 (!*ha)
- {
- free_tmp_table(thd, *is_table);
- return TRUE;
- }
+ if (!row)
+ return NULL;
- *orig_columns=
- dbug_tmp_use_all_columns(*is_table, (*is_table)->read_set);
+ DBUG_ASSERT(row->get_metadata()->get_num_columns() == 2);
- 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;
- }
+ const Ed_column *db_name= row->get_column(0);
+ const Ed_column *trigger_name= row->get_column(1);
- return FALSE;
+ return new Trigger_obj(db_name->str, db_name->length,
+ trigger_name->str, trigger_name->length);
}
-InformationSchemaIterator::~InformationSchemaIterator()
-{
- m_ha->ha_rnd_end();
-
- dbug_tmp_restore_column_map(m_is_table->read_set, m_orig_columns);
- free_tmp_table(m_thd, m_is_table);
-}
+///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
-Obj *InformationSchemaIterator::next()
+class Db_stored_proc_iterator : public Ed_result_set_iterator
{
- while (true)
- {
- if (m_ha->rnd_next(m_is_table->record[0]))
- return NULL;
-
- Obj *obj= create_obj(m_is_table);
-
- if (obj)
- return obj;
- }
-}
+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: DatabaseIterator class.
-//
+public:
+ virtual Obj *next();
+};
///////////////////////////////////////////////////////////////////////////
-DatabaseObj* DatabaseIterator::create_obj(TABLE *t)
+Db_stored_proc_iterator *
+Db_stored_proc_iterator::create(THD *thd, const String *db_name)
{
- String name;
-
- t->field[1]->val_str(&name);
+ char query_buffer[QUERY_BUFFER_SIZE];
+ LEX_STRING query;
- DBUG_PRINT("DatabaseIterator::next", (" Found database %s", name.ptr()));
+ 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 new DatabaseObj(&name);
+ return create_row_set_iterator<Db_stored_proc_iterator>(thd, &query);
}
///////////////////////////////////////////////////////////////////////////
-//
-// Implementation: DbTablesIterator class.
-//
+template
+Db_stored_proc_iterator *
+create_row_set_iterator<Db_stored_proc_iterator>(THD *thd,
+ const LEX_STRING *query);
///////////////////////////////////////////////////////////////////////////
-TableObj* DbTablesIterator::create_obj(TABLE *t)
+Obj *Db_stored_proc_iterator::next()
{
- String table_name;
- String db_name;
- String type;
- String engine;
-
- 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);
-
- // Skip tables not from the given database.
+ Ed_row *row= m_row_it++;
- if (db_name != m_db_name)
+ if (!row)
return NULL;
- // Skip tables/views depending on enumerate_views flag.
-
- 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.
-
- if (!is_engine_accepted(&engine))
- return NULL;
+ DBUG_ASSERT(row->get_metadata()->get_num_columns() == 2);
- DBUG_PRINT("DbTablesIterator::next", (" Found table %s.%s",
- db_name.ptr(), table_name.ptr()));
+ const Ed_column *db_name= row->get_column(0);
+ const Ed_column *routine_name= row->get_column(1);
- return create_table_obj(&db_name, &table_name);
+ return new Stored_proc_obj(db_name->str, db_name->length,
+ routine_name->str, routine_name->length);
}
-bool DbTablesIterator::is_type_accepted(const String *type) const
-{
- return my_strcasecmp(system_charset_info,
- ((String *) type)->c_ptr_safe(), "BASE TABLE") == 0;
-}
-
-bool DbTablesIterator::is_engine_accepted(const String *engine) const
-{
- return engine->length() > 0;
-}
+///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
-TableObj *DbTablesIterator::create_table_obj(const String *db_name,
- const String *table_name) const
+class Db_stored_func_iterator : public Ed_result_set_iterator
{
- return new TableObj(db_name, table_name, false);
-}
+public:
+ static Db_stored_func_iterator *create(THD *thd, const String *db_name);
-///////////////////////////////////////////////////////////////////////////
+public:
+ inline Db_stored_func_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_func_iterator *
+Db_stored_func_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 = '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: DbTriggerIterator class.
-//
+template
+Db_stored_func_iterator *
+create_row_set_iterator<Db_stored_func_iterator>(THD *thd,
+ const LEX_STRING *query);
///////////////////////////////////////////////////////////////////////////
-TriggerObj *DbTriggerIterator::create_obj(TABLE *t)
+Obj *Db_stored_func_iterator::next()
{
- String db_name;
- String trigger_name;
+ Ed_row *row= m_row_it++;
- t->field[1]->val_str(&db_name);
- t->field[2]->val_str(&trigger_name);
+ if (!row)
+ return NULL;
- // Skip triggers not from the given database.
+ DBUG_ASSERT(row->get_metadata()->get_num_columns() == 2);
- if (db_name != m_db_name)
- return NULL;
+ const Ed_column *db_name= row->get_column(0);
+ const Ed_column *routine_name= row->get_column(1);
- return new TriggerObj(&db_name, &trigger_name);
+ return new Stored_func_obj(db_name->str, db_name->length,
+ routine_name->str, routine_name->length);
}
///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
-//
-// Implementation: DbStoredProcIterator 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();
+};
///////////////////////////////////////////////////////////////////////////
-Obj *DbStoredProcIterator::create_obj(TABLE *t)
+Db_event_iterator *
+Db_event_iterator::create(THD *thd, const String *db_name)
{
- 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);
+#ifdef HAVE_EVENT_SCHEDULER
- // Skip stored procedure not from the given database.
+ char query_buffer[QUERY_BUFFER_SIZE];
+ LEX_STRING query;
- if (db_name != m_db_name)
- return NULL;
+ 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 (!check_type(&sr_type))
- return NULL;
+ return create_row_set_iterator<Db_event_iterator>(thd, &query);
- return create_sr_object(&db_name, &sr_name);
-}
+#else
-bool DbStoredProcIterator::check_type(const String *sr_type) const
-{
- return
- my_strcasecmp(system_charset_info,
- ((String *) sr_type)->c_ptr_safe(),
- "PROCEDURE") == 0;
-}
+ return NULL;
-Obj *DbStoredProcIterator::create_sr_object(const String *db_name,
- const String *sr_name)
-{
- return new StoredProcObj(db_name, sr_name);
+#endif
}
///////////////////////////////////////////////////////////////////////////
-//
-// Implementation: DbStoredFuncIterator class.
-//
+#ifdef HAVE_EVENT_SCHEDULER
+template
+Db_event_iterator *
+create_row_set_iterator<Db_event_iterator>(THD *thd, const LEX_STRING *query);
+#endif
///////////////////////////////////////////////////////////////////////////
-bool DbStoredFuncIterator::check_type(const String *sr_type) const
+Obj *Db_event_iterator::next()
{
- return
- my_strcasecmp(system_charset_info,
- ((String *) sr_type)->c_ptr_safe(),
- "FUNCTION") == 0;
-}
+#ifdef HAVE_EVENT_SCHEDULER
-Obj *DbStoredFuncIterator::create_sr_object(const String *db_name,
- const String *sr_name)
-{
- return new StoredFuncObj(db_name, sr_name);
-}
+ Ed_row *row= m_row_it++;
-#ifdef HAVE_EVENT_SCHEDULER
-///////////////////////////////////////////////////////////////////////////
+ if (!row)
+ return NULL;
-//
-// Implementation: DbEventIterator class.
-//
+ DBUG_ASSERT(row->get_metadata()->get_num_columns() == 2);
-///////////////////////////////////////////////////////////////////////////
-EventObj *DbEventIterator::create_obj(TABLE *t)
-{
- String db_name;
- String event_name;
+ const Ed_column *db_name= row->get_column(0);
+ const Ed_column *event_name= row->get_column(1);
- t->field[1]->val_str(&db_name);
- t->field[2]->val_str(&event_name);
+ return new Event_obj(db_name->str, db_name->length,
+ event_name->str, event_name->length);
- // Skip event not from the given database.
+#else
- if (db_name != m_db_name)
- return NULL;
+ return NULL;
- return new EventObj(&db_name, &event_name);
-}
#endif
+}
///////////////////////////////////////////////////////////////////////////
-
-//
-// Implementation: DbGrantIterator class.
-//
-
///////////////////////////////////////////////////////////////////////////
-DbGrantObj* DbGrantIterator::create_obj(TABLE *t)
+class View_base_obj_iterator : public Obj_iterator
{
- 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);
+public:
+ View_base_obj_iterator();
+ virtual ~View_base_obj_iterator();
- /*
- 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.
+public:
+ virtual Obj *next();
- 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()));
+protected:
+ template <typename T>
+ static T *create(THD *thd, const String *db_name, const String *view_name);
- /*
- 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
- return NULL;
-}
+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;
-//
-// Implementation: TblGrantIterator class.
-//
+private:
+ HASH *m_table_names;
+ uint m_cur_idx;
+};
///////////////////////////////////////////////////////////////////////////
-TblGrantObj* TblGrantIterator::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 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);
-
- /*
- 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.
+ T *it= new T();
- 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("TblGrantIterator::create", (" Found grant %s %s %s %s",
- db_name.ptr(), grantee.ptr(), tbl_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 TblGrantObj(&grantee, &db_name, &tbl_name, &priv_type);
- else
- return NULL;
- }
- else
+ delete it;
return NULL;
+ }
+
+ return it;
}
///////////////////////////////////////////////////////////////////////////
-//
-// Implementation: ColGrantIterator class.
-//
+View_base_obj_iterator::View_base_obj_iterator() :
+ m_table_names(NULL),
+ m_cur_idx(0)
+{
+}
///////////////////////////////////////////////////////////////////////////
-ColGrantObj* ColGrantIterator::create_obj(TABLE *t)
+View_base_obj_iterator::~View_base_obj_iterator()
{
- 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);
-
- /*
- 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)
- {
- 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()));
+ if (!m_table_names)
+ return;
- /*
- 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
- return NULL;
+ hash_free(m_table_names);
+ delete m_table_names;
}
///////////////////////////////////////////////////////////////////////////
-//
-// Implementation: ViewBaseObjectsIterator class.
-//
-
-///////////////////////////////////////////////////////////////////////////
-
-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 +1345,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 +1372,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 +1390,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 +1405,187 @@ 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;
-}
+///////////////////////////////////////////////////////////////////////////
-/**
- 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.
+Obj *Grant_iterator::next()
+{
+ Ed_row *row= m_row_it++;
- @param[IN] thd Current THD object
- @param[IN] db_name Name of database to get grants
+ if (!row)
+ return NULL;
- @Note The client is responsible for destroying the returned iterator.
+ DBUG_ASSERT(row->get_metadata()->get_num_columns() == 6);
- @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);
+ 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;
+
+ return 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);
}
///////////////////////////////////////////////////////////////////////////
-//
-// 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,133 +1595,88 @@ 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_RETURN(TRUE);
- }
- create.default_table_charset= system_charset_info;
+ DBUG_PRINT("backup",
+ (" Skipping internal database %.*s",
+ m_db_name.length(), m_db_name.ptr()));
- if (check_db_dir_existence(m_db_name.c_ptr()))
- {
- my_error(ER_BAD_DB_ERROR, MYF(0), m_db_name.c_ptr());
DBUG_RETURN(TRUE);
}
- load_db_opt_by_name(thd, m_db_name.c_ptr(), &create);
+ /* Run 'SHOW CREATE' query. */
- serialization->append(STRING_WITH_LEN("CREATE DATABASE "));
- append_identifier(thd, serialization, m_db_name.c_ptr(), m_db_name.length());
+ char query_buffer[QUERY_BUFFER_SIZE];
+ LEX_STRING query;
- 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);
-}
+ 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());
-/**
- Materialize the serialization string.
+ Ed_result result(thd->mem_root);
- This method saves serialization string into a member variable.
+ if (run_query(thd, &query, &result) ||
+ result.get_warnings().elements > 0)
+ {
+ /*
+ There should be no warnings. A warning means that serialization has
+ failed.
+ */
+ DBUG_RETURN(TRUE);
+ }
- @param[in] serialization_version version number of this interface
- @param[in] serialization the string from serialize()
+ /* Generate serialization. */
- @todo take serialization_version into account
+ DBUG_ASSERT(result.elements == 1);
- @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);
-}
+ Ed_result_set *rs= result.get_cur_result_set();
-/**
- Create the object.
+ DBUG_ASSERT(rs);
- This method uses serialization string in a query and executes it.
+ if (rs->data()->elements == 0)
+ DBUG_RETURN(TRUE);
- @param[in] thd Thread context.
+ DBUG_ASSERT(rs->data()->elements == 1);
- @returns Error status.
- @retval FALSE on success
- @retval TRUE on error
-*/
-bool DatabaseObj::do_execute(THD *thd)
-{
- DBUG_ENTER("DatabaseObj::execute()");
- drop(thd);
- DBUG_RETURN(silent_exec(thd, &m_create_stmt));
-}
+ List_iterator_fast<Ed_row> row_it(*rs->data());
+ Ed_row *row= row_it++;
-/**
- Drop the object.
+ DBUG_ASSERT(row->get_metadata()->get_num_columns() == 2);
- This method calls the silent_exec method to execute the query.
+ const Ed_column *create_stmt= row->get_column(1);
- @note This uses "IF EXISTS" and does not return error if
- object does not exist.
+ 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";
- @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 DatabaseObj::drop(THD *thd)
-{
- DBUG_ENTER("DatabaseObj::drop()");
- DBUG_RETURN(drop_object(thd,
- (char *) "DATABASE",
- 0,
- &m_db_name));
+ DBUG_RETURN(FALSE);
}
///////////////////////////////////////////////////////////////////////////
-
-//
-// Implementation: TableObj class.
-//
-
///////////////////////////////////////////////////////////////////////////
-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);
-}
-
-bool TableObj::serialize_table(THD *thd, String *serialization)
+Table_obj::Table_obj(const char *db_name_str, int db_name_length,
+ const char *table_name_str, int table_name_length)
{
- return 0;
+ 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);
}
-bool TableObj::serialize_view(THD *thd, String *serialization)
-{
- return 0;
-}
+///////////////////////////////////////////////////////////////////////////
/**
Serialize the object.
@@ -2083,592 +1684,544 @@ bool TableObj::serialize_view(THD *thd,
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 TableObj::do_serialize(THD *thd, String *serialization)
+
+bool Table_obj::do_serialize(THD *thd, Out_stream &os)
{
- 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;
+ 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()));
- /*
- 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;
+ char query_buffer[QUERY_BUFFER_SIZE];
+ LEX_STRING query;
- /*
- Setup view specific variables and settings
- */
- if (m_table_is_view)
- {
- thd->lex->only_view= 1;
- thd->lex->view_prepare_mode= TRUE; // use prepare mode
- table_list->skip_temporary= 1; // skip temporary tables
- }
+ 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());
- /*
- 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);
- }
+ 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)
{
- View_creation_ctx *creation_ctx= table_list->view_creation_ctx;
-
/*
- append character set client charset information
+ There should be no warnings. A warning means that serialization has
+ failed.
*/
- serialization->append("SET CHARACTER_SET_CLIENT = '");
- serialization->append(creation_ctx->get_client_cs()->csname);
- serialization->append("'; ");
+ DBUG_RETURN(TRUE);
+ }
- /*
- append collation_connection information
- */
- serialization->append("SET COLLATION_CONNECTION = '");
- serialization->append(creation_ctx->get_connection_cl()->name);
- serialization->append("'; ");
+ DBUG_ASSERT(result.elements == 1);
- table_list->view_db= dbname;
- serialization->set_charset(creation_ctx->get_client_cs());
- }
+ Ed_result_set *rs= result.get_cur_result_set();
- /*
- 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);
-}
+ DBUG_ASSERT(rs);
-/**
- Materialize the serialization string.
+ if (rs->data()->elements == 0)
+ DBUG_RETURN(TRUE);
- This method saves serialization string into a member variable.
+ DBUG_ASSERT(rs->data()->elements == 1);
- @param[in] serialization_version version number of this interface
- @param[in] serialization the string from serialize()
+ List_iterator_fast<Ed_row> row_it(*rs->data());
+ Ed_row *row= row_it++;
- @todo take serialization_version into account
+ 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";
- @returns Error status.
- @retval FALSE on success
- @retval TRUE on error
- */
-bool TableObj::materialize(uint serialization_version,
- const String *serialization)
-{
- DBUG_ENTER("TableObj::materialize()");
- m_create_stmt.copy(*serialization);
DBUG_RETURN(FALSE);
}
-/**
- Create the object represented by TableObj in the database.
+///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
- This method uses serialization string in a query and executes it.
+View_obj::View_obj(const char *db_name_str, int db_name_length,
+ const char *view_name_str, int view_name_length)
+{
+ 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);
+}
- @param[in] thd Thread context.
+///////////////////////////////////////////////////////////////////////////
- @returns Error status.
- @retval FALSE on success
- @retval TRUE on error
-*/
-bool TableObj::do_execute(THD *thd)
+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)
{
- DBUG_ENTER("TableObj::execute()");
- drop(thd);
- DBUG_RETURN(silent_exec(thd, &m_create_stmt));
-}
+ char query_buffer[QUERY_BUFFER_SIZE];
+ LEX_STRING query;
-/**
- Drop the object.
+ /* Get a create statement for a view. */
- 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 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());
- @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.
+ */
+ 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));
+ DBUG_ASSERT(result.elements == 1);
+
+ 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;
}
///////////////////////////////////////////////////////////////////////////
-//
-// Implementation: TriggerObj class.
-//
-///////////////////////////////////////////////////////////////////////////
+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);
-TriggerObj::TriggerObj(const String *db_name,
- const String *trigger_name)
-{
- // copy strings to newly allocated memory
- m_db_name.copy(*db_name);
- m_trigger_name.copy(*trigger_name);
-}
+ while (true)
+ {
+ Obj *base_obj= base_object_it->next();
-/**
- Serialize the object.
+ if (!base_obj)
+ break;
- This method produces the data necessary for materializing the object
- on restore (creates object).
+ /* Dump header of base obj stub. */
- @param[in] thd Thread handler.
- @param[out] serialization The data needed to recreate this object.
+ 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());
- @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.
+ Ed_result result(thd->mem_root);
- @returns Error status.
- @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);
+ if (run_query(thd, &query, &result) ||
+ result.get_warnings().elements > 0)
+ {
+ /*
+ There should be no warnings. A warning means that serialization has
+ failed.
+ */
+ delete base_obj;
+ return TRUE;
+ }
- alloc_mdl_locks(lst, thd->mem_root);
+ DBUG_ASSERT(result.elements == 1);
- DBUG_EXECUTE_IF("backup_fail_add_trigger", DBUG_RETURN(TRUE););
- if (open_tables(thd, &lst, &num_tables, 0))
- DBUG_RETURN(TRUE);
+ Ed_result_set *rs= result.get_cur_result_set();
+ DBUG_ASSERT(rs);
- 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);
+ /* Dump structure of base obj stub. */
- /*
- prepend SQL Mode
- */
- serialization->append("SET SQL_MODE = '");
- serialization->append(trg_sql_mode_str.str);
- serialization->append("'; ");
+ List_iterator_fast<Ed_row> row_it(*rs->data());
+ bool first_column= TRUE;
- /*
- append character set client charset information
- */
- serialization->append("SET CHARACTER_SET_CLIENT = '");
- serialization->append(trg_client_cs_name.str);
- serialization->append("'; ");
+ while (true)
+ {
+ Ed_row *row= row_it++;
- /*
- append collation_connection information
- */
- serialization->append("SET COLLATION_CONNECTION = '");
- serialization->append(trg_connection_cl_name.str);
- serialization->append("'; ");
+ if (!row)
+ break;
- /*
- append collation_connection information
- */
- serialization->append("SET COLLATION_DATABASE = '");
- serialization->append(trg_db_cl_name.str);
- serialization->append("'; ");
+ DBUG_ASSERT(row->get_metadata()->get_num_columns() == 6);
- 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);
-}
+ const LEX_STRING *col_name= row->get_column(0);
+ const LEX_STRING *col_type= row->get_column(1);
-/**
- Materialize the serialization string.
+ if (first_column)
+ first_column= FALSE;
+ else
+ base_obj_stmt.append(C_STRING_WITH_LEN(", "));
- This method saves serialization string into a member variable.
+ 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);
+ }
- @param[in] serialization_version version number of this interface
- @param[in] serialization the string from serialize()
+ base_obj_stmt.append(C_STRING_WITH_LEN(") ENGINE = MyISAM"));
- @todo take serialization_version into account
+ os << base_obj_stmt;
- @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);
+ delete base_obj;
+ }
+
+ return FALSE;
}
+///////////////////////////////////////////////////////////////////////////
+
/**
- 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 TriggerObj::do_execute(THD *thd)
+bool View_obj::do_serialize(THD *thd, Out_stream &os)
{
- DBUG_ENTER("TriggerObj::execute()");
- drop(thd);
- DBUG_RETURN(execute_with_ctx(thd, &m_create_stmt, 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()));
-/**
- Drop the object.
+ const LEX_STRING *create_stmt;
+ const LEX_STRING *client_cs_name;
+ const LEX_STRING *connection_cl_name;
- This method calls the silent_exec method to execute the query.
+ if (get_view_create_stmt(thd, this, &create_stmt,
+ &client_cs_name, &connection_cl_name))
+ {
+ DBUG_RETURN(TRUE);
+ }
- @note This uses "IF EXISTS" and does not return error if
- object does not exist.
+ /* Dump the header. */
- @param[in] thd Thread context.
- @param[out] serialization The data needed to recreate this object.
+ os <<
+ "SET @saved_cs_client = @@character_set_client" <<
+ "SET @saved_col_connection = @@collation_connection" <<
+ "SET character_set_client = utf8";
- @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));
-}
+ /* Get view dependencies. */
-///////////////////////////////////////////////////////////////////////////
+ {
+ Obj_iterator *base_table_it=
+ get_view_base_tables(thd, &m_db_name, &m_view_name);
-//
-// Implementation: StoredProcObj class.
-//
+ if (!base_table_it ||
+ dump_base_object_stubs(thd, base_table_it, os))
+ {
+ DBUG_RETURN(TRUE);
+ }
+
+ delete base_table_it;
+ }
+
+ {
+ Obj_iterator *base_view_it=
+ get_view_base_views(thd, &m_db_name, &m_view_name);
+
+ if (!base_view_it ||
+ dump_base_object_stubs(thd, base_view_it, os))
+ {
+ DBUG_RETURN(TRUE);
+ }
+
+ 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);
+}
///////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////
-StoredProcObj::StoredProcObj(const String *db_name,
- const String *stored_proc_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_stored_proc_name.copy(*stored_proc_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 context.
- @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
should be recreated using this interface.
@returns Error status.
+ @retval FALSE on success
+ @retval TRUE on error
*/
-bool StoredProcObj::do_serialize(THD *thd, String *serialization)
+
+bool Trigger_obj::do_serialize(THD *thd, Out_stream &os)
{
- 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);
-}
+ 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()));
-/**
- Materialize the serialization string.
+ DBUG_EXECUTE_IF("backup_fail_add_trigger", DBUG_RETURN(TRUE););
- This method saves serialization string into a member variable.
+ char query_buffer[QUERY_BUFFER_SIZE];
+ LEX_STRING query;
- @param[in] serialization_version version number of this interface
- @param[in] serialization the string from serialize()
+ 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());
- @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.
+ */
+ 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_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_func_name.copy(*stored_func_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
should be recreated using this interface.
@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_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 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.
+ */
+ 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)
+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_event_name.copy(*event_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
@@ -2678,206 +2231,260 @@ EventObj::EventObj(const String *db_name
@retval FALSE on success
@retval TRUE on error
*/
-bool EventObj::do_serialize(THD *thd, String *serialization)
+
+bool Stored_func_obj::do_serialize(THD *thd, Out_stream &os)
{
- 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)
+ 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());
+
+ Ed_result result(thd->mem_root);
+
+ if (run_query(thd, &query, &result) ||
+ result.get_warnings().elements > 0)
{
/*
- Prepend sql_mode command.
+ There should be no warnings. A warning means that serialization has
+ failed.
*/
- serialization->append("SET SQL_MODE = '");
- serialization->append(sql_mode.str);
- serialization->append("'; ");
+ DBUG_RETURN(TRUE);
+ }
- /*
- append time zone information
- */
- serialization->append("SET TIME_ZONE = '");
- const String *tz= et.time_zone->get_name();
- serialization->append(tz->ptr());
- serialization->append("'; ");
+ DBUG_ASSERT(result.elements == 1);
- /*
- append character set client charset information
- */
- serialization->append("SET CHARACTER_SET_CLIENT = '");
- serialization->append(et.creation_ctx->get_client_cs()->csname);
- serialization->append("'; ");
+ Ed_result_set *rs= result.get_cur_result_set();
- /*
- append collation_connection information
- */
- serialization->append("SET COLLATION_CONNECTION = '");
- serialization->append(et.creation_ctx->get_connection_cl()->name);
- serialization->append("'; ");
+ DBUG_ASSERT(rs);
- /*
- append collation_connection information
- */
- serialization->append("SET COLLATION_DATABASE = '");
- serialization->append(et.creation_ctx->get_db_cl()->name);
- serialization->append("'; ");
+ if (rs->data()->elements == 0)
+ DBUG_RETURN(TRUE);
- if (et.get_create_event(thd, serialization))
- DBUG_RETURN(0);
- }
- serialization->set_charset(system_charset_info);
- DBUG_RETURN(0);
-}
+ DBUG_ASSERT(rs->data()->elements == 1);
-/**
- Materialize the serialization string.
+ List_iterator_fast<Ed_row> row_it(*rs->data());
+ Ed_row *row= row_it++;
- This method saves serialization string into a member variable.
+ DBUG_ASSERT(row->get_metadata()->get_num_columns() == 6);
- @param[in] serialization_version version number of this interface
- @param[in] serialization the string from serialize()
+ 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";
- @todo take serialization_version into account
+ DBUG_RETURN(FALSE);
+}
- @returns Error status.
- @retval FALSE on success
- @retval TRUE on error
-*/
-bool EventObj::materialize(uint serialization_version,
- const String *serialization)
+///////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+
+#ifdef HAVE_EVENT_SCHEDULER
+
+Event_obj::Event_obj(const char *db_name_str, int db_name_length,
+ const char *event_name_str, int event_name_length)
{
- DBUG_ENTER("EventObj::materialize()");
- m_create_stmt.copy(*serialization);
- DBUG_RETURN(0);
+ 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);
}
+///////////////////////////////////////////////////////////////////////////
+
/**
- 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[out] os Output stream.
- @param[in] thd Thread context.
+ @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.
@returns Error status.
@retval FALSE on success
@retval TRUE on error
*/
-bool EventObj::do_execute(THD *thd)
+
+bool Event_obj::do_serialize(THD *thd, Out_stream &os)
{
- DBUG_ENTER("EventObj::execute()");
- drop(thd);
- DBUG_RETURN(execute_with_ctx(thd, &m_create_stmt, true));
-}
+ 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());
-/**
- Drop the object.
+ Ed_result result(thd->mem_root);
- This method calls the silent_exec method to execute the query.
+ if (run_query(thd, &query, &result) ||
+ result.get_warnings().elements > 0)
+ {
+ /*
+ There should be no warnings. A warning means that serialization has
+ failed.
+ */
+ DBUG_RETURN(TRUE);
+ }
- @note This uses "IF EXISTS" and does not return error if
- object does not exist.
+ DBUG_ASSERT(result.elements == 1);
- @param[in] thd Thread context.
- @param[out] serialization the data needed to recreate this object
+ Ed_result_set *rs= result.get_cur_result_set();
- @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));
+ DBUG_ASSERT(rs);
+
+ if (rs->data()->elements == 0)
+ DBUG_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() == 7);
+
+ 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";
+
+ DBUG_RETURN(FALSE);
}
+
#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)
+
+bool Tablespace_obj::do_serialize(THD *thd, Out_stream &os)
{
- DBUG_ENTER("TablespaceObj::serialize()");
- build_serialization();
- serialization->copy(m_create_stmt);
+ DBUG_ENTER("Tablespace_obj::serialize()");
+
+ os << *get_description();
+
DBUG_RETURN(FALSE);
}
-/**
- Materialize the serialization string.
+///////////////////////////////////////////////////////////////////////////
- This method saves serialization string into a member variable.
- Also extracts tablespace engine name from serialization string.
+bool Tablespace_obj::materialize(uint serialization_version,
+ const String *serialization)
+{
+ if (Abstract_obj::materialize(serialization_version, serialization))
+ return TRUE;
- @param[in] serialization_version version number of this interface
- @param[in] serialization the string from serialize()
+ List_iterator_fast<String> it(m_stmt_lst);
+ String *desc= it++;
- @todo take serialization_version into account
+ DBUG_ASSERT(desc);
- @returns Error status.
- @retval FALSE on success
- @retval TRUE on error
-*/
-bool TablespaceObj::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);
+ m_description.set(desc->ptr(), desc->length(), desc->charset());
+
+ return FALSE;
}
+///////////////////////////////////////////////////////////////////////////
+
/**
Get a description of the tablespace object.
@@ -2886,171 +2493,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 +2610,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 +2621,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 +2793,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 +2805,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 +2817,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 +2904,218 @@ 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. */
+ 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. */
+ 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. */
+ 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 +3294,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-19 16:32:01 +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.
@@ -662,14 +546,6 @@ void ddl_blocker_exception_on(THD *thd);
@param[in] thd Thread context.
*/
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.
=== modified file 'sql/slave.cc'
--- a/sql/slave.cc 2008-11-14 20:45:00 +0000
+++ b/sql/slave.cc 2008-11-18 19:41:51 +0000
@@ -1670,7 +1670,7 @@ static int has_temporary_error(THD *thd)
/*
currently temporary error set in ndbcluster
*/
- List_iterator_fast<MYSQL_ERROR> it(thd->warning_info.warn_list());
+ List_iterator_fast<MYSQL_ERROR> it(thd->warning_info->warn_list());
MYSQL_ERROR *err;
while ((err= it++))
{
@@ -2610,7 +2610,7 @@ Slave SQL thread aborted. Can't execute
}
/* Print any warnings issued */
- List_iterator_fast<MYSQL_ERROR> it(thd->warning_info.warn_list());
+ List_iterator_fast<MYSQL_ERROR> it(thd->warning_info->warn_list());
MYSQL_ERROR *err;
/*
Added controlled slave thread cancel for replication
=== modified file 'sql/sp.cc'
--- a/sql/sp.cc 2008-11-14 20:45:00 +0000
+++ b/sql/sp.cc 2008-11-18 19:41:51 +0000
@@ -1329,7 +1329,7 @@ sp_exist_routines(THD *thd, TABLE_LIST *
&thd->sp_proc_cache, FALSE) != NULL ||
sp_find_routine(thd, TYPE_ENUM_FUNCTION, name,
&thd->sp_func_cache, FALSE) != NULL;
- thd->warning_info.clear_warning_info(thd->query_id);
+ thd->warning_info->clear_warning_info(thd->query_id);
if (sp_object_found)
{
if (any)
=== modified file 'sql/sp_head.cc'
--- a/sql/sp_head.cc 2008-10-20 19:13:22 +0000
+++ b/sql/sp_head.cc 2008-11-18 20:25:51 +0000
@@ -2847,7 +2847,7 @@ sp_instr_stmt::execute(THD *thd, uint *n
res= m_lex_keeper.reset_lex_and_exec_core(thd, nextp, FALSE, this);
if (thd->main_da.is_eof())
- net_end_statement(thd);
+ thd->protocol->end_statement();
query_cache_end_of_result(thd);
=== modified file 'sql/sql_base.cc'
--- a/sql/sql_base.cc 2008-11-14 20:45:00 +0000
+++ b/sql/sql_base.cc 2008-11-18 19:41:51 +0000
@@ -602,7 +602,7 @@ static TABLE_SHARE
DBUG_RETURN(0);
}
/* Table existed in engine. Let's open it */
- thd->warning_info.clear_warning_info(thd->query_id);
+ thd->warning_info->clear_warning_info(thd->query_id);
thd->clear_error(); // Clear error message
DBUG_RETURN(get_table_share(thd, table_list, key, key_length,
db_flags, error));
@@ -3483,7 +3483,7 @@ recover_from_failed_open_table_attempt(T
ha_create_table_from_engine(thd, table->db, table->table_name);
pthread_mutex_unlock(&LOCK_open);
- thd->warning_info.clear_warning_info(thd->query_id);
+ thd->warning_info->clear_warning_info(thd->query_id);
thd->clear_error(); // Clear error message
mdl_release_lock(&thd->mdl_context, table->mdl_lock_data);
mdl_remove_lock(&thd->mdl_context, table->mdl_lock_data);
=== modified file 'sql/sql_class.cc'
--- a/sql/sql_class.cc 2008-11-14 20:45:00 +0000
+++ b/sql/sql_class.cc 2008-11-18 22:30:59 +0000
@@ -304,7 +304,7 @@ int thd_tx_isolation(const THD *thd)
extern "C"
void thd_inc_row_count(THD *thd)
{
- thd->warning_info.inc_current_row_for_warning();
+ thd->warning_info->inc_current_row_for_warning();
}
@@ -436,7 +436,7 @@ Diagnostics_area::set_ok_status(THD *thd
return;
m_server_status= thd->server_status;
- m_statement_warn_count= thd->warning_info.statement_warn_count();
+ m_statement_warn_count= thd->warning_info->statement_warn_count();
m_affected_rows= affected_rows_arg;
m_last_insert_id= last_insert_id_arg;
if (message_arg)
@@ -472,7 +472,7 @@ Diagnostics_area::set_eof_status(THD *th
anyway.
*/
m_statement_warn_count= (thd->spcont ?
- 0 : thd->warning_info.statement_warn_count());
+ 0 : thd->warning_info->statement_warn_count());
m_status= DA_EOF;
DBUG_VOID_RETURN;
@@ -526,59 +526,6 @@ Diagnostics_area::disable_status()
}
-Warning_info::Warning_info(query_id_t warn_id_arg)
- :m_statement_warn_count(0),
- m_current_row_for_warning(1),
- m_warn_id(warn_id_arg)
-{
- /* Initialize sub structures */
- init_sql_alloc(&m_warn_root, WARN_ALLOC_BLOCK_SIZE, WARN_ALLOC_PREALLOC_SIZE);
- m_warn_list.empty();
- bzero((char*) m_warn_count, sizeof(m_warn_count));
-}
-
-
-Warning_info::~Warning_info()
-{
- free_root(&m_warn_root,MYF(0));
-}
-
-
-/**
- Reset the warning information of this connection.
-*/
-
-void Warning_info::clear_warning_info(query_id_t warn_id_arg)
-{
- m_warn_id= warn_id_arg;
- free_root(&m_warn_root, MYF(0));
- bzero((char*) m_warn_count, sizeof(m_warn_count));
- m_warn_list.empty();
- m_statement_warn_count= 0;
- m_current_row_for_warning= 1; /* Start counting from the first row */
-}
-
-
-/**
- Add a warning to the list of warnings. Increment the respective
- counters.
-*/
-
-void Warning_info::push_warning(THD *thd,
- MYSQL_ERROR::enum_warning_level level,
- uint code, const char *msg)
-{
- if (m_warn_list.elements < thd->variables.max_error_count)
- {
- MYSQL_ERROR *err;
- if ((err= new (&m_warn_root) MYSQL_ERROR(&m_warn_root, level, code, msg)))
- m_warn_list.push_back(err, &m_warn_root);
- }
- m_warn_count[(uint) level]++;
- m_statement_warn_count++;
-}
-
-
THD::THD()
:Statement(&main_lex, &main_mem_root, CONVENTIONAL_EXECUTION,
/* statement id */ 0),
@@ -592,7 +539,8 @@ THD::THD()
first_successful_insert_id_in_prev_stmt_for_binlog(0),
first_successful_insert_id_in_cur_stmt(0),
stmt_depends_on_first_successful_insert_id_in_prev_stmt(FALSE),
- warning_info(0),
+ main_warning_info(0),
+ warning_info(&main_warning_info),
global_read_lock(0),
is_fatal_error(0),
transaction_rollback_request(0),
=== modified file 'sql/sql_class.h'
--- a/sql/sql_class.h 2008-11-14 20:45:00 +0000
+++ b/sql/sql_class.h 2008-11-18 22:30:59 +0000
@@ -1261,120 +1261,6 @@ private:
*/
};
-
-/**
- Information about warnings of the current connection.
-*/
-
-class Warning_info
-{
- /** A memory root to allocate warnings and errors */
- MEM_ROOT m_warn_root;
- /** List of warnings of all severities (levels). */
- List <MYSQL_ERROR> m_warn_list;
- /** A break down of the number of warnings per severity (level). */
- uint m_warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_END];
- /**
- The number of warnings of the current statement. Warning_info
- life cycle differs from statement life cycle -- it may span
- multiple statements. In that case we get
- m_statement_warn_count 0, whereas m_warn_list is not empty.
- */
- uint m_statement_warn_count;
- /*
- Row counter, to print in errors and warnings. Not increased in
- create_sort_index(); may differ from examined_row_count.
- */
- ulong m_current_row_for_warning;
- /** Used to optionally clear warnings only once per statement. */
- query_id_t m_warn_id;
-
-private:
- Warning_info(const Warning_info &rhs); /* Not implemented */
- Warning_info& operator=(const Warning_info &rhs); /* Not implemented */
-public:
-
- Warning_info(query_id_t warn_id_arg);
- /* Do nothing - used to initialize a backup info */
- Warning_info() { clear_alloc_root(&m_warn_root); }
- ~Warning_info();
-
- /**
- Reset the warning information. Clear all warnings,
- the number of warnings, reset current row counter
- to point to the first row.
- */
- void clear_warning_info(query_id_t warn_id_arg);
- /**
- Only clear warning info if haven't yet done that already
- for the current query. Allows to be issued at any time
- during the query, without risk of clearing some warnings
- that have been generated by the current statement.
-
- @todo: This is a sign of sloppy coding. Instead we need to
- designate one place in a statement life cycle where we call
- clear_warning_info().
- */
- void opt_clear_warning_info(query_id_t query_id)
- {
- if (query_id != m_warn_id)
- clear_warning_info(query_id);
- }
-
- /**
- Reset between two COM_ commands. Warnings are preserved
- between commands, but statement_warn_count indicates
- the number of warnings of this particular statement only.
- */
- void reset_for_next_command() { m_statement_warn_count= 0; }
-
- /**
- Used for @@warning_count system variable, which prints
- the number of rows returned by SHOW WARNINGS.
- */
- ulong warn_count() const
- {
- /*
- This may be higher than warn_list.elements if we have
- had more warnings than thd->variables.max_error_count.
- */
- return (m_warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_NOTE] +
- m_warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_ERROR] +
- m_warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_WARN]);
- }
-
- /**
- This is for iteration purposes. We return a non-constant reference
- since List doesn't have constant iterators.
- */
- List<MYSQL_ERROR> &warn_list() { return m_warn_list; }
-
- /**
- The number of errors, or number of rows returned by SHOW ERRORS,
- also the value of session variable @@error_count.
- */
- ulong error_count() const
- {
- return m_warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_ERROR];
- }
-
- /** Do we have any errors and warnings that we can *show*? */
- bool is_empty() const { return m_warn_list.elements == 0; }
-
- /** Increment the current row counter to point at the next row. */
- void inc_current_row_for_warning() { m_current_row_for_warning++; }
- /** Reset the current row counter. Start counting from the first row. */
- void reset_current_row_for_warning() { m_current_row_for_warning= 1; }
- /** Return the current counter value. */
- ulong current_row_for_warning() const { return m_current_row_for_warning; }
-
- ulong statement_warn_count() const { return m_statement_warn_count; }
-
- /** Add a new warning to the current list. */
- void push_warning(THD *thd, MYSQL_ERROR::enum_warning_level level,
- uint code, const char *msg);
-};
-
/**
Tables that were locked with LOCK TABLES statement.
@@ -1904,7 +1790,8 @@ public:
table_map used_tables;
USER_CONN *user_connect;
CHARSET_INFO *db_charset;
- Warning_info warning_info;
+ Warning_info main_warning_info;
+ Warning_info *warning_info;
Diagnostics_area main_da;
#if defined(ENABLED_PROFILING)
PROFILING profiling;
=== modified file 'sql/sql_connect.cc'
--- a/sql/sql_connect.cc 2008-10-17 17:47:16 +0000
+++ b/sql/sql_connect.cc 2008-11-18 20:25:51 +0000
@@ -983,7 +983,7 @@ bool login_connection(THD *thd)
lex_start(thd);
error= check_connection(thd);
- net_end_statement(thd);
+ thd->protocol->end_statement();
if (error)
{ // Wrong permissions
=== modified file 'sql/sql_error.cc'
--- a/sql/sql_error.cc 2008-11-14 20:45:00 +0000
+++ b/sql/sql_error.cc 2008-11-18 22:30:59 +0000
@@ -41,6 +41,7 @@ This file contains the implementation of
***********************************************************************/
+#include "sql_error.h"
#include "mysql_priv.h"
#include "sp_rcontext.h"
@@ -52,6 +53,59 @@ void MYSQL_ERROR::set_msg(MEM_ROOT *warn
}
+Warning_info::Warning_info(ulonglong warn_id_arg)
+ :m_statement_warn_count(0),
+ m_current_row_for_warning(1),
+ m_warn_id(warn_id_arg)
+{
+ /* Initialize sub structures */
+ init_sql_alloc(&m_warn_root, WARN_ALLOC_BLOCK_SIZE, WARN_ALLOC_PREALLOC_SIZE);
+ m_warn_list.empty();
+ bzero((char*) m_warn_count, sizeof(m_warn_count));
+}
+
+
+Warning_info::~Warning_info()
+{
+ free_root(&m_warn_root,MYF(0));
+}
+
+
+/**
+ Reset the warning information of this connection.
+*/
+
+void Warning_info::clear_warning_info(ulonglong warn_id_arg)
+{
+ m_warn_id= warn_id_arg;
+ free_root(&m_warn_root, MYF(0));
+ bzero((char*) m_warn_count, sizeof(m_warn_count));
+ m_warn_list.empty();
+ m_statement_warn_count= 0;
+ m_current_row_for_warning= 1; /* Start counting from the first row */
+}
+
+
+/**
+ Add a warning to the list of warnings. Increment the respective
+ counters.
+*/
+
+void Warning_info::push_warning(THD *thd,
+ MYSQL_ERROR::enum_warning_level level,
+ uint code, const char *msg)
+{
+ if (m_warn_list.elements < thd->variables.max_error_count)
+ {
+ MYSQL_ERROR *err;
+ if ((err= new (&m_warn_root) MYSQL_ERROR(&m_warn_root, level, code, msg)))
+ m_warn_list.push_back(err, &m_warn_root);
+ }
+ m_warn_count[(uint) level]++;
+ m_statement_warn_count++;
+}
+
+
/*
Push the warning/error to error list if there is still room in the list
@@ -77,7 +131,7 @@ void push_warning(THD *thd, MYSQL_ERROR:
DBUG_VOID_RETURN;
if (! thd->spcont)
- thd->warning_info.opt_clear_warning_info(thd->query_id);
+ thd->warning_info->opt_clear_warning_info(thd->query_id);
thd->got_warning= 1;
@@ -111,7 +165,7 @@ void push_warning(THD *thd, MYSQL_ERROR:
}
query_cache_abort(&thd->query_cache_tls);
- thd->warning_info.push_warning(thd, level, code, msg);
+ thd->warning_info->push_warning(thd, level, code, msg);
DBUG_VOID_RETURN;
}
@@ -191,7 +245,7 @@ bool mysqld_show_warnings(THD *thd, ulon
unit->set_limit(sel);
- List_iterator_fast<MYSQL_ERROR> it(thd->warning_info.warn_list());
+ List_iterator_fast<MYSQL_ERROR> it(thd->warning_info->warn_list());
while ((err= it++))
{
/* Skip levels that the user is not interested in */
=== modified file 'sql/sql_error.h'
--- a/sql/sql_error.h 2008-11-14 20:45:00 +0000
+++ b/sql/sql_error.h 2008-11-18 22:30:59 +0000
@@ -13,6 +13,16 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+#ifndef SQL_ERROR_H
+#define SQL_ERROR_H
+
+#include "sql_list.h" /* Sql_alloc, MEM_ROOT */
+#include "m_string.h" /* LEX_STRING */
+
+class THD;
+
+///////////////////////////////////////////////////////////////////////////
+
class MYSQL_ERROR: public Sql_alloc
{
public:
@@ -35,6 +45,123 @@ private:
void set_msg(MEM_ROOT *warn_root, const char *msg_arg);
};
+///////////////////////////////////////////////////////////////////////////
+
+/**
+ Information about warnings of the current connection.
+*/
+
+class Warning_info
+{
+ /** A memory root to allocate warnings and errors */
+ MEM_ROOT m_warn_root;
+ /** List of warnings of all severities (levels). */
+ List <MYSQL_ERROR> m_warn_list;
+ /** A break down of the number of warnings per severity (level). */
+ uint m_warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_END];
+ /**
+ The number of warnings of the current statement. Warning_info
+ life cycle differs from statement life cycle -- it may span
+ multiple statements. In that case we get
+ m_statement_warn_count 0, whereas m_warn_list is not empty.
+ */
+ uint m_statement_warn_count;
+ /*
+ Row counter, to print in errors and warnings. Not increased in
+ create_sort_index(); may differ from examined_row_count.
+ */
+ ulong m_current_row_for_warning;
+ /** Used to optionally clear warnings only once per statement. */
+ ulonglong m_warn_id;
+
+private:
+ Warning_info(const Warning_info &rhs); /* Not implemented */
+ Warning_info& operator=(const Warning_info &rhs); /* Not implemented */
+public:
+
+ Warning_info(ulonglong warn_id_arg);
+ /* Do nothing - used to initialize a backup info */
+ Warning_info() { clear_alloc_root(&m_warn_root); }
+ ~Warning_info();
+
+ /**
+ Reset the warning information. Clear all warnings,
+ the number of warnings, reset current row counter
+ to point to the first row.
+ */
+ void clear_warning_info(ulonglong warn_id_arg);
+ /**
+ Only clear warning info if haven't yet done that already
+ for the current query. Allows to be issued at any time
+ during the query, without risk of clearing some warnings
+ that have been generated by the current statement.
+
+ @todo: This is a sign of sloppy coding. Instead we need to
+ designate one place in a statement life cycle where we call
+ clear_warning_info().
+ */
+ void opt_clear_warning_info(ulonglong query_id)
+ {
+ if (query_id != m_warn_id)
+ clear_warning_info(query_id);
+ }
+
+ /**
+ Reset between two COM_ commands. Warnings are preserved
+ between commands, but statement_warn_count indicates
+ the number of warnings of this particular statement only.
+ */
+ void reset_for_next_command() { m_statement_warn_count= 0; }
+
+ /**
+ Used for @@warning_count system variable, which prints
+ the number of rows returned by SHOW WARNINGS.
+ */
+ ulong warn_count() const
+ {
+ /*
+ This may be higher than warn_list.elements if we have
+ had more warnings than thd->variables.max_error_count.
+ */
+ return (m_warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_NOTE] +
+ m_warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_ERROR] +
+ m_warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_WARN]);
+ }
+
+ /**
+ This is for iteration purposes. We return a non-constant reference
+ since List doesn't have constant iterators.
+ */
+ List<MYSQL_ERROR> &warn_list() { return m_warn_list; }
+
+ /**
+ The number of errors, or number of rows returned by SHOW ERRORS,
+ also the value of session variable @@error_count.
+ */
+ ulong error_count() const
+ {
+ return m_warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_ERROR];
+ }
+
+ /** Do we have any errors and warnings that we can *show*? */
+ bool is_empty() const { return m_warn_list.elements == 0; }
+
+ /** Increment the current row counter to point at the next row. */
+ void inc_current_row_for_warning() { m_current_row_for_warning++; }
+ /** Reset the current row counter. Start counting from the first row. */
+ void reset_current_row_for_warning() { m_current_row_for_warning= 1; }
+ /** Return the current counter value. */
+ ulong current_row_for_warning() const { return m_current_row_for_warning; }
+
+ ulong statement_warn_count() const { return m_statement_warn_count; }
+
+ /** Add a new warning to the current list. */
+ void push_warning(THD *thd, MYSQL_ERROR::enum_warning_level level,
+ uint code, const char *msg);
+};
+
+///////////////////////////////////////////////////////////////////////////
+
void push_warning(THD *thd, MYSQL_ERROR::enum_warning_level level,
uint code, const char *msg);
void push_warning_printf(THD *thd, MYSQL_ERROR::enum_warning_level level,
@@ -42,3 +169,5 @@ void push_warning_printf(THD *thd, MYSQL
bool mysqld_show_warnings(THD *thd, ulong levels_to_show);
extern const LEX_STRING warning_level_names[];
+
+#endif // SQL_ERROR_H
=== modified file 'sql/sql_insert.cc'
--- a/sql/sql_insert.cc 2008-11-14 20:45:00 +0000
+++ b/sql/sql_insert.cc 2008-11-18 19:41:51 +0000
@@ -835,7 +835,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *t
error=write_record(thd, table ,&info);
if (error)
break;
- thd->warning_info.inc_current_row_for_warning();
+ thd->warning_info->inc_current_row_for_warning();
}
free_underlaid_joins(thd, &thd->lex->select_lex);
=== 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-19 16:32:01 +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-19 16:32:01 +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_list.cc'
--- a/sql/sql_list.cc 2007-05-28 11:30:01 +0000
+++ b/sql/sql_list.cc 2008-11-18 22:30:59 +0000
@@ -18,7 +18,7 @@
#pragma implementation // gcc: Class implementation
#endif
-#include "mysql_priv.h"
+#include "sql_list.h"
list_node end_of_list;
=== modified file 'sql/sql_list.h'
--- a/sql/sql_list.h 2008-08-20 10:29:58 +0000
+++ b/sql/sql_list.h 2008-11-19 12:53:52 +0000
@@ -15,10 +15,16 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+#include "my_global.h"
+#include "my_sys.h" /* for MEM_ROOT, operator new */
+#include "m_string.h" /* for TRASH */
+
#ifdef USE_PRAGMA_INTERFACE
#pragma interface /* gcc class implementation */
#endif
+
+void *sql_alloc(size_t);
/* mysql standard class memory allocator */
=== modified file 'sql/sql_load.cc'
--- a/sql/sql_load.cc 2008-11-14 20:45:00 +0000
+++ b/sql/sql_load.cc 2008-11-18 19:41:51 +0000
@@ -645,7 +645,7 @@ read_fixed_length(THD *thd, COPY_INFO &i
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARN_TOO_FEW_RECORDS,
ER(ER_WARN_TOO_FEW_RECORDS),
- thd->warning_info.current_row_for_warning());
+ thd->warning_info->current_row_for_warning());
if (!field->maybe_null() && field->type() == FIELD_TYPE_TIMESTAMP)
((Field_timestamp*) field)->set_time();
}
@@ -669,7 +669,7 @@ read_fixed_length(THD *thd, COPY_INFO &i
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARN_TOO_MANY_RECORDS,
ER(ER_WARN_TOO_MANY_RECORDS),
- thd->warning_info.current_row_for_warning());
+ thd->warning_info->current_row_for_warning());
}
if (thd->killed ||
@@ -705,9 +705,9 @@ read_fixed_length(THD *thd, COPY_INFO &i
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARN_TOO_MANY_RECORDS,
ER(ER_WARN_TOO_MANY_RECORDS),
- thd->warning_info.current_row_for_warning());
+ thd->warning_info->current_row_for_warning());
}
- thd->warning_info.inc_current_row_for_warning();
+ thd->warning_info->inc_current_row_for_warning();
continue_loop:;
}
DBUG_RETURN(test(read_info.error));
@@ -771,7 +771,7 @@ read_sep_field(THD *thd, COPY_INFO &info
if (field->reset())
{
my_error(ER_WARN_NULL_TO_NOTNULL, MYF(0), field->field_name,
- thd->warning_info.current_row_for_warning());
+ thd->warning_info->current_row_for_warning());
DBUG_RETURN(1);
}
field->set_null();
@@ -839,7 +839,7 @@ read_sep_field(THD *thd, COPY_INFO &info
if (field->reset())
{
my_error(ER_WARN_NULL_TO_NOTNULL, MYF(0),field->field_name,
- thd->warning_info.current_row_for_warning());
+ thd->warning_info->current_row_for_warning());
DBUG_RETURN(1);
}
if (!field->maybe_null() && field->type() ==
FIELD_TYPE_TIMESTAMP)
@@ -854,7 +854,7 @@ read_sep_field(THD *thd, COPY_INFO &info
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARN_TOO_FEW_RECORDS,
ER(ER_WARN_TOO_FEW_RECORDS),
- thd->warning_info.current_row_for_warning());
+ thd->warning_info->current_row_for_warning());
}
else if (item->type() == Item::STRING_ITEM)
{
@@ -900,11 +900,11 @@ read_sep_field(THD *thd, COPY_INFO &info
thd->cuted_fields++; /* To long row */
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARN_TOO_MANY_RECORDS, ER(ER_WARN_TOO_MANY_RECORDS),
- thd->warning_info.current_row_for_warning());
+ thd->warning_info->current_row_for_warning());
if (thd->killed)
DBUG_RETURN(1);
}
- thd->warning_info.inc_current_row_for_warning();
+ thd->warning_info->inc_current_row_for_warning();
continue_loop:;
}
DBUG_RETURN(test(read_info.error));
@@ -1038,7 +1038,7 @@ read_xml_field(THD *thd, COPY_INFO &info
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARN_TOO_FEW_RECORDS,
ER(ER_WARN_TOO_FEW_RECORDS),
- thd->warning_info.current_row_for_warning());
+ thd->warning_info->current_row_for_warning());
}
else
((Item_user_var_as_out_param *)item)->set_null_value(cs);
@@ -1069,7 +1069,7 @@ read_xml_field(THD *thd, COPY_INFO &info
its default value at the beginning of each loop iteration.
*/
thd->transaction.stmt.modified_non_trans_table= no_trans_update_stmt;
- thd->warning_info.inc_current_row_for_warning();
+ thd->warning_info->inc_current_row_for_warning();
continue_loop:;
}
DBUG_RETURN(test(read_info.error));
=== modified file 'sql/sql_parse.cc'
--- a/sql/sql_parse.cc 2008-11-14 20:45:00 +0000
+++ b/sql/sql_parse.cc 2008-11-18 20:25:51 +0000
@@ -450,7 +450,7 @@ pthread_handler_t handle_bootstrap(void
/* purecov: begin tested */
if (net_realloc(&(thd->net), 2 * thd->net.max_packet))
{
- net_end_statement(thd);
+ thd->protocol->end_statement();
bootstrap_error= 1;
break;
}
@@ -492,7 +492,7 @@ pthread_handler_t handle_bootstrap(void
close_thread_tables(thd); // Free tables
bootstrap_error= thd->is_error();
- net_end_statement(thd);
+ thd->protocol->end_statement();
#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER)
thd->profiling.finish_current_query();
@@ -642,7 +642,7 @@ bool do_command(THD *thd)
/* The error must be set. */
DBUG_ASSERT(thd->is_error());
- net_end_statement(thd);
+ thd->protocol->end_statement();
if (net->error != 3)
{
@@ -1013,7 +1013,7 @@ bool dispatch_command(enum enum_server_c
ha_maria::implicit_commit(thd, FALSE);
#endif
- net_end_statement(thd);
+ thd->protocol->end_statement();
query_cache_end_of_result(thd);
/*
Multiple queries exits, execute them individually
@@ -1399,7 +1399,7 @@ bool dispatch_command(enum enum_server_c
ha_maria::implicit_commit(thd, FALSE);
#endif
- net_end_statement(thd);
+ thd->protocol->end_statement();
query_cache_end_of_result(thd);
thd->proc_info= "closing tables";
@@ -1412,7 +1412,7 @@ bool dispatch_command(enum enum_server_c
0,0,0,0,
thd->query,thd->query_length,
thd->variables.character_set_client,
- thd->warning_info.current_row_for_warning());
+ thd->warning_info->current_row_for_warning());
}
log_slow_statement(thd);
@@ -1851,7 +1851,7 @@ mysql_execute_command(THD *thd)
Don't reset warnings when executing a stored routine.
*/
if ((all_tables || !lex->is_single_level_stmt()) && !thd->spcont)
- thd->warning_info.opt_clear_warning_info(thd->query_id);
+ thd->warning_info->opt_clear_warning_info(thd->query_id);
#ifdef HAVE_REPLICATION
if (unlikely(thd->slave_thread))
@@ -4156,7 +4156,7 @@ create_sp_error:
else
sp= sp_find_routine(thd, TYPE_ENUM_FUNCTION, lex->spname,
&thd->sp_func_cache, FALSE);
- thd->warning_info.opt_clear_warning_info(thd->query_id);
+ thd->warning_info->opt_clear_warning_info(thd->query_id);
if (! sp)
{
if (lex->spname->m_db.str)
@@ -4276,7 +4276,7 @@ create_sp_error:
}
sp_result= sp_routine_exists_in_table(thd, type, lex->spname);
- thd->warning_info.opt_clear_warning_info(thd->query_id);
+ thd->warning_info->opt_clear_warning_info(thd->query_id);
if (sp_result == SP_OK)
{
char *db= lex->spname->m_db.str;
@@ -5367,7 +5367,7 @@ void mysql_reset_thd_for_next_command(TH
}
thd->clear_error();
thd->main_da.reset_diagnostics_area();
- thd->warning_info.reset_for_next_command();
+ thd->warning_info->reset_for_next_command();
thd->rand_used= 0;
thd->sent_row_count= thd->examined_row_count= 0;
thd->thd_marker.emb_on_expr_nest= NULL;
=== modified file 'sql/sql_prepare.cc'
--- a/sql/sql_prepare.cc 2008-11-14 20:45:00 +0000
+++ b/sql/sql_prepare.cc 2008-11-19 16:32:01 +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:
@@ -248,7 +250,7 @@ static bool send_prep_stmt(Prepared_stat
int2store(buff+5, columns);
int2store(buff+7, stmt->param_count);
buff[9]= 0; // Guard against a 4.1 client
- tmp= min(stmt->thd->warning_info.statement_warn_count(), 65535);
+ tmp= min(stmt->thd->warning_info->statement_warn_count(), 65535);
int2store(buff+10, tmp);
/*
@@ -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);
@@ -1839,7 +1841,7 @@ static bool check_prepared_statement(Pre
/* Reset warning count for each query that uses tables */
if ((tables || !lex->is_single_level_stmt()) && !thd->spcont)
- thd->warning_info.opt_clear_warning_info(thd->query_id);
+ thd->warning_info->opt_clear_warning_info(thd->query_id);
switch (sql_command) {
case SQLCOM_REPLACE:
@@ -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,6 @@ 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);
if ((stmt= (Prepared_statement*) thd->stmt_map.find_by_name(name)))
{
@@ -2244,11 +2251,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 +2437,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 +2465,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 +2520,6 @@ void mysql_sql_stmt_execute(THD *thd)
DBUG_VOID_RETURN;
}
-
/**
COM_STMT_FETCH handler: fetches requested amount of rows from cursor.
@@ -2801,12 +2812,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 +2905,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 +3019,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) ||
@@ -3245,6 +3257,117 @@ reexecute:
return error;
}
+/**
+ 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)
+{
+ DBUG_ASSERT(result);
+
+ mysql_reset_thd_for_next_command(thd);
+
+ 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;
+ Protocol_local p(thd, result);
+
+ thd->protocol= &p;
+
+ result->begin_statement(thd);
+ bool rc= stmt->execute_immediate(query->str, query->length);
+ result->end_statement(thd);
+
+ p.end_statement();
+
+ thd->protocol= protocol_saved;
+
+ delete stmt;
+
+ thd->main_da.reset_diagnostics_area();
+
+ return rc;
+}
+
+
+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 +3392,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);
@@ -3298,7 +3423,7 @@ Prepared_statement::reprepare()
Sic: we can't simply silence warnings during reprepare, because if
it's failed, we need to return all the warnings to the user.
*/
- thd->warning_info.clear_warning_info(thd->query_id);
+ thd->warning_info->clear_warning_info(thd->query_id);
}
return error;
}
@@ -3327,7 +3452,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 +3515,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 */
}
@@ -3531,8 +3655,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 +3692,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 +3705,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_select.cc'
--- a/sql/sql_select.cc 2008-11-14 20:45:00 +0000
+++ b/sql/sql_select.cc 2008-11-18 19:41:51 +0000
@@ -13717,7 +13717,7 @@ sub_select(JOIN *join,JOIN_TAB *join_tab
/* Set first_unmatched for the last inner table of this group */
join_tab->last_inner->first_unmatched= join_tab;
}
- join->thd->warning_info.reset_current_row_for_warning();
+ join->thd->warning_info->reset_current_row_for_warning();
error= (*join_tab->read_first_record)(join_tab);
rc= evaluate_join_record(join, join_tab, error);
@@ -13969,7 +13969,7 @@ evaluate_join_record(JOIN *join, JOIN_TA
enum enum_nested_loop_state rc;
/* A match from join_tab is found for the current partial join. */
rc= (*join_tab->next_select)(join, join_tab+1, 0);
- join->thd->warning_info.inc_current_row_for_warning();
+ join->thd->warning_info->inc_current_row_for_warning();
if (rc != NESTED_LOOP_OK && rc != NESTED_LOOP_NO_MORE_ROWS)
return rc;
if (return_tab < join->return_tab)
@@ -13987,7 +13987,7 @@ evaluate_join_record(JOIN *join, JOIN_TA
}
else
{
- join->thd->warning_info.inc_current_row_for_warning();
+ join->thd->warning_info->inc_current_row_for_warning();
join_tab->read_record.file->unlock_row();
}
}
@@ -13998,7 +13998,7 @@ evaluate_join_record(JOIN *join, JOIN_TA
with the beginning coinciding with the current partial join.
*/
join->examined_rows++;
- join->thd->warning_info.inc_current_row_for_warning();
+ join->thd->warning_info->inc_current_row_for_warning();
join_tab->read_record.file->unlock_row();
}
return NESTED_LOOP_OK;
=== modified file 'sql/sql_show.cc'
--- a/sql/sql_show.cc 2008-11-14 20:45:00 +0000
+++ b/sql/sql_show.cc 2008-11-18 19:41:51 +0000
@@ -516,7 +516,7 @@ mysqld_show_create(THD *thd, TABLE_LIST
issue a warning with 'warning' level status in
case of invalid view and last error is ER_VIEW_INVALID
*/
- thd->warning_info.clear_warning_info(thd->query_id);
+ thd->warning_info->clear_warning_info(thd->query_id);
thd->clear_error();
push_warning_printf(thd,MYSQL_ERROR::WARN_LEVEL_WARN,
=== modified file 'sql/sql_table.cc'
--- a/sql/sql_table.cc 2008-11-14 20:45:00 +0000
+++ b/sql/sql_table.cc 2008-11-18 19:41:51 +0000
@@ -4289,7 +4289,7 @@ static bool mysql_admin_table(THD* thd,
if (!table->table)
{
DBUG_PRINT("admin", ("open table failed"));
- if (thd->warning_info.is_empty())
+ if (thd->warning_info->is_empty())
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_CHECK_NO_SUCH_TABLE, ER(ER_CHECK_NO_SUCH_TABLE));
/* if it was a view will check md5 sum */
@@ -4397,7 +4397,7 @@ send_result:
lex->cleanup_after_one_table_open();
thd->clear_error(); // these errors shouldn't get client
{
- List_iterator_fast<MYSQL_ERROR> it(thd->warning_info.warn_list());
+ List_iterator_fast<MYSQL_ERROR> it(thd->warning_info->warn_list());
MYSQL_ERROR *err;
while ((err= it++))
{
@@ -4411,7 +4411,7 @@ send_result:
if (protocol->write())
goto err;
}
- thd->warning_info.clear_warning_info(thd->query_id);
+ thd->warning_info->clear_warning_info(thd->query_id);
}
protocol->prepare_for_resend();
protocol->store(table_name, system_charset_info);
@@ -7237,7 +7237,7 @@ err:
Report error here.
*/
if (alter_info->error_if_not_empty &&
- thd->warning_info.current_row_for_warning())
+ thd->warning_info->current_row_for_warning())
{
const char *f_val= 0;
enum enum_mysql_timestamp_type t_type= MYSQL_TIMESTAMP_DATE;
@@ -7409,7 +7409,7 @@ copy_data_between_tables(TABLE *from,TAB
errpos= 4;
if (ignore)
to->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
- thd->warning_info.reset_current_row_for_warning();
+ thd->warning_info->reset_current_row_for_warning();
restore_record(to, s->default_values); // Create empty record
while (!(error=info.read_record(&info)))
{
@@ -7468,7 +7468,7 @@ copy_data_between_tables(TABLE *from,TAB
}
else
found_count++;
- thd->warning_info.inc_current_row_for_warning();
+ thd->warning_info->inc_current_row_for_warning();
}
err:
=== modified file 'sql/sql_update.cc'
--- a/sql/sql_update.cc 2008-11-14 20:45:00 +0000
+++ b/sql/sql_update.cc 2008-11-18 19:41:51 +0000
@@ -727,7 +727,7 @@ int mysql_update(THD *thd,
}
else
table->file->unlock_row();
- thd->warning_info.inc_current_row_for_warning();
+ thd->warning_info->inc_current_row_for_warning();
}
dup_key_found= 0;
/*
=== 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-19 16:32:01 +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())
{
/*
=== modified file 'sql/time.cc'
--- a/sql/time.cc 2008-11-14 20:45:00 +0000
+++ b/sql/time.cc 2008-11-18 19:41:51 +0000
@@ -748,7 +748,7 @@ void make_truncated_value_warning(THD *t
cs->cset->snprintf(cs, warn_buff, sizeof(warn_buff),
ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD),
type_str, str.c_ptr(), field_name,
- (ulong) thd->warning_info.current_row_for_warning());
+ (ulong) thd->warning_info->current_row_for_warning());
else
{
if (time_type > MYSQL_TIMESTAMP_ERROR)
| Thread |
|---|
| • bzr push into mysql-6.0-runtime branch (alik:2745 to 2751) WL#4264 | Alexander Nozdrin | 19 Nov |