summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorunknown <monty@mashka.mysql.fi>2002-09-05 16:17:08 +0300
committerunknown <monty@mashka.mysql.fi>2002-09-05 16:17:08 +0300
commit8f2482d283646d61c6614df39d252e1fd3713f7c (patch)
tree103a1aadee6000a5d09b0ba7c1de75797fb958fa /sql
parent34f299d408e6993cbf9f688aa97a83e4c2932efe (diff)
downloadmariadb-git-8f2482d283646d61c6614df39d252e1fd3713f7c.tar.gz
Fixed searching after ssl directories.
Fixed that GRANT ... REQUIRE options are not forgot when doing new GRANT Changed fn_ext to point at first '.' after directory. FLUSH LOGS removed numerical extension for all future update logs. Fixed the mysqld --help reports right values for --datadir and --bind-address --log-binary=a.b.c now properly strips of .b.c Fix that one can DROP UDF functions that was not loaded at startup Made AND optional in REQUIRE Added REQUIRE NONE BitKeeper/deleted/.del-CodingStyle~1ba7ff62d4cd0ea: Delete: vio/docs/CodingStyle BitKeeper/deleted/.del-COPYING.dbug~ca0c017a4d7e8609: Delete: vio/docs/COPYING.dbug BitKeeper/deleted/.del-COPYING.mysql~471498c82977cd3a: Delete: vio/docs/COPYING.mysql BitKeeper/deleted/.del-README~947354991dc882f8: Delete: vio/docs/README Docs/manual.texi: Changelog acinclude.m4: Fixed searching after ssl directories. client/Makefile.am: Moved openssl include to avoid problem with installed readline include/Makefile.am: Install my_global.h include/violite.h: Fixed that GRANT ... REQUIRE options are not forgot when doing new grant libmysqld/examples/Makefile.am: Moved openssl include to avoid problem with installed readline mysql-test/mysql-test-run.sh: Improved 'which' handling to give error if command is not found mysys/mf_fn_ext.c: Changed fn_ext to point at first '.' after directory. sql/Makefile.am: More comments sql/lex.h: Added NONE as keyword sql/log.cc: FLUSH LOGS removed numerical extension for all future update logs. Simple code cleanup sql/mysqld.cc: Fixed the --help reports right values for --datadir and --bind-address --log-binary=a.b.c now properly strips of .b.c Removed option --skip-external-locking (not needed as this is automatic) sql/repl_failsafe.cc: Moved some common THD initalization to store_globals() sql/slave.cc: Moved openssl include to avoid problem with installed readline sql/sql_acl.cc: Moved openssl include to avoid problem with installed readline sql/sql_acl.h: Updated function prototypes sql/sql_base.cc: Added comment sql/sql_class.cc: Moved openssl include to avoid problem with installed readline. Changed THD::thd to make things work for main thread. sql/sql_class.h: Fixed wrongly removed line (fixes compiler problem on MacOSX) sql/sql_insert.cc: Moved openssl include to avoid problem with installed readline sql/sql_lex.cc: Moved save_to_cache_query=0 to udf detection function to make sql_yacc.yy simpler sql/sql_lex.h: Indentation cleanup sql/sql_parse.cc: Moved openssl include to avoid problem with installed readline. Added THD argument to acl_reload() sql/sql_repl.h: Made opt_bin_logname static sql/sql_udf.cc: Fix that one can DROP UDF functions that was not loaded at startup sql/sql_yacc.yy: made AND optional in REQUIRE Added REQUIRE NONE Fixed that old SSL options are not forgotten when doing new GRANT. sql/udf_example.cc: Improved comments
Diffstat (limited to 'sql')
-rw-r--r--sql/Makefile.am5
-rw-r--r--sql/lex.h1
-rw-r--r--sql/log.cc28
-rw-r--r--sql/mysqld.cc28
-rw-r--r--sql/repl_failsafe.cc2
-rw-r--r--sql/slave.cc2
-rw-r--r--sql/sql_acl.cc190
-rw-r--r--sql/sql_acl.h6
-rw-r--r--sql/sql_base.cc9
-rw-r--r--sql/sql_class.cc12
-rw-r--r--sql/sql_class.h1
-rw-r--r--sql/sql_insert.cc2
-rw-r--r--sql/sql_lex.cc5
-rw-r--r--sql/sql_lex.h2
-rw-r--r--sql/sql_parse.cc7
-rw-r--r--sql/sql_repl.h3
-rw-r--r--sql/sql_udf.cc62
-rw-r--r--sql/sql_yacc.yy56
-rw-r--r--sql/udf_example.cc4
19 files changed, 222 insertions, 203 deletions
diff --git a/sql/Makefile.am b/sql/Makefile.am
index 51c0a0f1fe8..49c0735a990 100644
--- a/sql/Makefile.am
+++ b/sql/Makefile.am
@@ -130,6 +130,11 @@ lex_hash.h: lex.h gen_lex_hash.cc sql_yacc.h
# Hack to ensure that lex_hash.h is built early
sql_lex.o: lex_hash.h
+# For testing of udf_example.so; Works on platforms with gcc
+# (This is not part of our build process but only provided as an example)
+udf_example.so: udf_example.cc
+ $(CXXCOMPILE) -shared -o $@ $<
+
#distclean:
# rm -f lex_hash.h
diff --git a/sql/lex.h b/sql/lex.h
index 0a1505581cd..dba919ce366 100644
--- a/sql/lex.h
+++ b/sql/lex.h
@@ -251,6 +251,7 @@ static SYMBOL symbols[] = {
{ "NEW", SYM(NEW_SYM),0,0},
{ "NCHAR", SYM(NCHAR_SYM),0,0},
{ "NO", SYM(NO_SYM),0,0},
+ { "NONE", SYM(NONE_SYM),0,0},
{ "NOT", SYM(NOT),0,0},
{ "NULL", SYM(NULL_SYM),0,0},
{ "NUMERIC", SYM(NUMERIC_SYM),0,0},
diff --git a/sql/log.cc b/sql/log.cc
index ad06eb6e90c..e42d9ffa2fa 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -108,11 +108,9 @@ MYSQL_LOG::~MYSQL_LOG()
int MYSQL_LOG::generate_new_name(char *new_name, const char *log_name)
{
- if (log_type == LOG_NORMAL)
- fn_format(new_name,log_name,mysql_data_home,"",4);
- else
+ fn_format(new_name,log_name,mysql_data_home,"",4);
+ if (log_type != LOG_NORMAL)
{
- fn_format(new_name,log_name,mysql_data_home,"",4);
if (!fn_ext(log_name)[0])
{
if (find_uniq_filename(new_name))
@@ -798,7 +796,8 @@ void MYSQL_LOG::new_file(bool need_lock)
safe_mutex_assert_owner(&LOCK_log);
safe_mutex_assert_owner(&LOCK_index);
- new_name_ptr= name; // Reuse old name if not binlog
+ // Reuse old name if not binlog and not update log
+ new_name_ptr= name;
/*
Only rotate open logs that are marked non-rotatable
@@ -806,12 +805,17 @@ void MYSQL_LOG::new_file(bool need_lock)
*/
if (!no_rotate)
{
+ /*
+ If user hasn't specified an extension, generate a new log name
+ We have to do this here and not in open as we want to store the
+ new file name in the current binary log file.
+ */
+ if (generate_new_name(new_name, name))
+ goto end;
+ new_name_ptr=new_name;
+
if (log_type == LOG_BIN)
{
- if (generate_new_name(new_name, name))
- goto end; /* Error; Continue using old log file */
-
- new_name_ptr=new_name;
if (!no_auto_events)
{
/*
@@ -823,9 +827,9 @@ void MYSQL_LOG::new_file(bool need_lock)
r.set_log_pos(this);
/*
- Becasue this log rotation could have been initiated by a master of
+ Because this log rotation could have been initiated by a master of
the slave running with log-bin, we set the flag on rotate
- event to prevent inifinite log rotation loop
+ event to prevent infinite log rotation loop
*/
if (thd->slave_thread)
r.flags|= LOG_EVENT_FORCED_ROTATE_F;
@@ -833,7 +837,7 @@ void MYSQL_LOG::new_file(bool need_lock)
bytes_written += r.get_event_len();
}
/*
- Update needs to be signaled even if there is no rotate event
+ Update needs to be signalled even if there is no rotate event
log rotation should give the waiting thread a signal to
discover EOF and move on to the next log.
*/
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 9895897ec0d..68064d41d17 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -384,7 +384,7 @@ bool mysql_embedded=0;
bool mysql_embedded=1;
#endif
-char *opt_bin_logname = 0; // this one needs to be seen in sql_parse.cc
+static char *opt_bin_logname = 0;
char *opt_relay_logname = 0, *opt_relaylog_index_name=0;
char server_version[SERVER_VERSION_LENGTH]=MYSQL_SERVER_VERSION;
const char *first_keyword="first";
@@ -395,6 +395,7 @@ ulong rpl_recovery_rank=0;
my_string mysql_unix_port=NULL, opt_mysql_tmpdir=NULL, mysql_tmpdir=NULL;
ulong my_bind_addr; /* the address we bind to */
+char *my_bind_addr_str;
DATE_FORMAT dayord;
double log_10[32]; /* 10 potences */
I_List<THD> threads,thread_cache;
@@ -1744,10 +1745,10 @@ bool open_log(MYSQL_LOG *log, const char *hostname,
first change fn_format() to cut the file name if it's too long.
*/
strmake(tmp,hostname,FN_REFLEN-5);
- strmov(strcend(tmp,'.'),extension);
+ strmov(fn_ext(tmp),extension);
opt_name=tmp;
}
- // get rid of extention if the log is binary to avoid problems
+ // get rid of extension if the log is binary to avoid problems
if (type == LOG_BIN)
{
char *p = fn_ext(opt_name);
@@ -1814,7 +1815,7 @@ int main(int argc, char **argv)
if (gethostname(glob_hostname,sizeof(glob_hostname)-4) < 0)
strmov(glob_hostname,"mysql");
strmake(pidfile_name, glob_hostname, sizeof(pidfile_name)-5);
- strmov(strcend(pidfile_name,'.'),".pid"); // Add extension
+ strmov(fn_ext(pidfile_name),".pid"); // Add proper extension
#ifndef DBUG_OFF
strxmov(strend(server_version),MYSQL_SERVER_SUFFIX,"-debug",NullS);
#else
@@ -2077,16 +2078,6 @@ The server will not act as a slave.");
}
if (opt_bin_log)
{
- if (!opt_bin_logname)
- {
- char tmp[FN_REFLEN];
- /* TODO: The following should be using fn_format(); We just need to
- first change fn_format() to cut the file name if it's too long.
- */
- strmake(tmp,glob_hostname,FN_REFLEN-5);
- strmov(strcend(tmp,'.'),"-bin");
- opt_bin_logname=my_strdup(tmp,MYF(MY_WME));
- }
open_log(&mysql_bin_log, glob_hostname, opt_bin_logname, "-bin",
opt_binlog_index_name,LOG_BIN);
using_update_log=1;
@@ -2957,9 +2948,9 @@ struct my_option my_long_options[] =
{"binlog-ignore-db", OPT_BINLOG_IGNORE_DB,
"Tells the master that updates to the given database should not be logged tothe binary log",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
- {"bind-address", OPT_BIND_ADDRESS, "Ip address to bind to",
- (gptr*) &my_bind_addr, (gptr*) &my_bind_addr, 0, GET_STR, REQUIRED_ARG, 0,
- 0, 0, 0, 0, 0},
+ {"bind-address", OPT_BIND_ADDRESS, "IP address to bind to",
+ (gptr*) &my_bind_addr_str, (gptr*) &my_bind_addr_str, 0, GET_STR,
+ REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"bootstrap", OPT_BOOTSTRAP, "Used by mysql installation scripts", 0, 0, 0,
GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
#ifdef __WIN__
@@ -3276,9 +3267,6 @@ struct my_option my_long_options[] =
{"skip-locking", OPT_SKIP_LOCK,
"Deprecated option, use --skip-external-locking instead",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"skip-external-locking", OPT_SKIP_LOCK, "Do not use system (external) locking",
- (gptr*) &opt_external_locking, (gptr*) &opt_external_locking,
- 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"skip-host-cache", OPT_SKIP_HOST_CACHE, "Don't cache host names", 0, 0, 0,
GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"skip-name-resolve", OPT_SKIP_RESOLVE,
diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc
index 0c537da474e..232c3de2570 100644
--- a/sql/repl_failsafe.cc
+++ b/sql/repl_failsafe.cc
@@ -75,8 +75,6 @@ static int init_failsafe_rpl_thread(THD* thd)
DBUG_RETURN(-1);
}
- thd->mysys_var=my_thread_var;
- thd->dbug_thread_id=my_thread_id();
#if !defined(__WIN__) && !defined(OS2)
sigset_t set;
VOID(sigemptyset(&set)); // Get mask in use
diff --git a/sql/slave.cc b/sql/slave.cc
index 6173c8ecf4c..7a1a1e2a6ef 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -1539,8 +1539,6 @@ static int init_slave_thread(THD* thd, SLAVE_THD_TYPE thd_type)
DBUG_RETURN(-1);
}
- thd->mysys_var=my_thread_var;
- thd->dbug_thread_id=my_thread_id();
#if !defined(__WIN__) && !defined(OS2)
sigset_t set;
VOID(sigemptyset(&set)); // Get mask in use
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index 5e32da07aad..519ac0e7ce2 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -64,10 +64,8 @@ public:
USER_RESOURCES user_resource;
char *user,*password;
ulong salt[2];
-#ifdef HAVE_OPENSSL
enum SSL_type ssl_type;
const char *ssl_cipher, *x509_issuer, *x509_subject;
-#endif /* HAVE_OPENSSL */
};
@@ -142,12 +140,27 @@ static void init_update_queries(void)
uc_update_queries[SQLCOM_MULTI_UPDATE]=1;
}
-int acl_init(bool dont_read_acl_tables)
+/*
+ Read grant privileges from the privilege tables in the 'mysql' database.
+
+ SYNOPSIS
+ acl_init()
+ dont_read_acl_tables Set to 1 if run with --skip-grant
+
+ RETURN VALUES
+ 0 ok
+ 1 Could not initialize grant's
+*/
+
+
+my_bool acl_init(bool dont_read_acl_tables)
{
- THD *thd;
+ THD *thd, *org_thd;
TABLE_LIST tables[3];
TABLE *table;
READ_RECORD read_record_info;
+ MYSQL_LOCK *lock;
+ my_bool return_val=1;
DBUG_ENTER("acl_init");
if (!acl_cache)
@@ -157,13 +170,15 @@ int acl_init(bool dont_read_acl_tables)
if (dont_read_acl_tables)
DBUG_RETURN(0); /* purecov: tested */
+ /*
+ To be able to run this from boot, we allocate a temporary THD
+ */
+ org_thd=current_thd; // Save for restore
if (!(thd=new THD))
DBUG_RETURN(1); /* purecov: inspected */
+ thd->store_globals();
+
acl_cache->clear(1); // Clear locked hostname cache
- thd->version=refresh_version;
- thd->mysys_var=my_thread_var;
- thd->current_tablenr=0;
- thd->open_tables=0;
thd->db= my_strdup("mysql",MYF(0));
thd->db_length=5; // Safety
bzero((char*) &tables,sizeof(tables));
@@ -176,22 +191,13 @@ int acl_init(bool dont_read_acl_tables)
tables[0].db=tables[1].db=tables[2].db=thd->db;
if (open_tables(thd,tables))
- {
- close_thread_tables(thd); /* purecov: inspected */
- delete thd; /* purecov: inspected */
- DBUG_RETURN(1); /* purecov: inspected */
- }
+ goto end;
TABLE *ptr[3]; // Lock tables for quick update
ptr[0]= tables[0].table;
ptr[1]= tables[1].table;
ptr[2]= tables[2].table;
- MYSQL_LOCK *lock=mysql_lock_tables(thd,ptr,3);
- if (!lock)
- {
- close_thread_tables(thd); /* purecov: inspected */
- delete thd; /* purecov: inspected */
- DBUG_RETURN(1); /* purecov: inspected */
- }
+ if (!(lock=mysql_lock_tables(thd,ptr,3)))
+ goto end;
init_sql_alloc(&mem,1024,0);
init_read_record(&read_record_info,thd,table= tables[0].table,NULL,1,0);
@@ -259,7 +265,6 @@ int acl_init(bool dont_read_acl_tables)
(uint) strlen(user.host.hostname) : 0);
if (table->fields >= 31) /* Starting from 4.0.2 we have more fields */
{
-#ifdef HAVE_OPENSSL
char *ssl_type=get_field(&mem, table, 24);
if (!ssl_type)
user.ssl_type=SSL_TYPE_NONE;
@@ -273,7 +278,7 @@ int acl_init(bool dont_read_acl_tables)
user.ssl_cipher= get_field(&mem, table, 25);
user.x509_issuer= get_field(&mem, table, 26);
user.x509_subject= get_field(&mem, table, 27);
-#endif
+
char *ptr = get_field(&mem, table, 28);
user.user_resource.questions=atoi(ptr);
ptr = get_field(&mem, table, 29);
@@ -286,9 +291,7 @@ int acl_init(bool dont_read_acl_tables)
}
else
{
-#ifdef HAVE_OPENSSL
user.ssl_type=SSL_TYPE_NONE;
-#endif
bzero(&(user.user_resource),sizeof(user.user_resource));
#ifndef TO_BE_REMOVED
if (table->fields <= 13)
@@ -346,12 +349,17 @@ int acl_init(bool dont_read_acl_tables)
init_check_host();
mysql_unlock_tables(thd, lock);
+ initialized=1;
init_update_queries();
thd->version--; // Force close to free memory
+ return_val=0;
+
+end:
close_thread_tables(thd);
delete thd;
- initialized=1;
- DBUG_RETURN(0);
+ if (org_thd)
+ org_thd->store_globals(); /* purecov: inspected */
+ DBUG_RETURN(return_val);
}
@@ -374,18 +382,18 @@ void acl_free(bool end)
/* Reload acl list if possible */
-void acl_reload(void)
+void acl_reload(THD *thd)
{
DYNAMIC_ARRAY old_acl_hosts,old_acl_users,old_acl_dbs;
MEM_ROOT old_mem;
bool old_initialized;
DBUG_ENTER("acl_reload");
- if (current_thd && current_thd->locked_tables)
+ if (thd && thd->locked_tables)
{ // Can't have locked tables here
- current_thd->lock=current_thd->locked_tables;
- current_thd->locked_tables=0;
- close_thread_tables(current_thd);
+ thd->lock=thd->locked_tables;
+ thd->locked_tables=0;
+ close_thread_tables(thd);
}
if ((old_initialized=initialized))
VOID(pthread_mutex_lock(&acl_cache->lock));
@@ -399,7 +407,7 @@ void acl_reload(void)
if (acl_init(0))
{ // Error. Revert to old list
- acl_free(); /* purecov: inspected */
+ acl_free(); /* purecov: inspected */
acl_hosts=old_acl_hosts;
acl_users=old_acl_users;
acl_dbs=old_acl_dbs;
@@ -536,6 +544,7 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
if X509 certificate attributes are OK
*/
switch (acl_user->ssl_type) {
+ case SSL_TYPE_NOT_SPECIFIED: // Impossible
case SSL_TYPE_NONE: /* SSL is not required to connect */
user_access=acl_user->access;
break;
@@ -559,15 +568,17 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
use.
*/
if (acl_user->ssl_cipher)
+ {
DBUG_PRINT("info",("comparing ciphers: '%s' and '%s'",
acl_user->ssl_cipher,
SSL_get_cipher(vio->ssl_)));
- if (!strcmp(acl_user->ssl_cipher,SSL_get_cipher(vio->ssl_)))
- user_access=acl_user->access;
- else
- {
- user_access=NO_ACCESS;
- break;
+ if (!strcmp(acl_user->ssl_cipher,SSL_get_cipher(vio->ssl_)))
+ user_access=acl_user->access;
+ else
+ {
+ user_access=NO_ACCESS;
+ break;
+ }
}
/* Prepare certificate (if exists) */
DBUG_PRINT("info",("checkpoint 1"));
@@ -661,12 +672,16 @@ static void acl_update_user(const char *user, const char *host,
acl_user->user_resource.updates=mqh->updates;
if (mqh->bits & 4)
acl_user->user_resource.connections=mqh->connections;
-#ifdef HAVE_OPENSSL
- acl_user->ssl_type=ssl_type;
- acl_user->ssl_cipher=ssl_cipher;
- acl_user->x509_issuer=x509_issuer;
- acl_user->x509_subject=x509_subject;
-#endif /* HAVE_OPENSSL */
+ if (ssl_type != SSL_TYPE_NOT_SPECIFIED)
+ {
+ acl_user->ssl_type= ssl_type;
+ acl_user->ssl_cipher= (ssl_cipher ? strdup_root(&mem,ssl_cipher) :
+ 0);
+ acl_user->x509_issuer= (x509_issuer ? strdup_root(&mem,x509_issuer) :
+ 0);
+ acl_user->x509_subject= (x509_subject ?
+ strdup_root(&mem,x509_subject) : 0);
+ }
if (password)
{
if (!password[0])
@@ -701,12 +716,11 @@ static void acl_insert_user(const char *user, const char *host,
acl_user.user_resource = *mqh;
acl_user.sort=get_sort(2,acl_user.host.hostname,acl_user.user);
acl_user.hostname_length=(uint) strlen(acl_user.host.hostname);
-#ifdef HAVE_OPENSSL
- acl_user.ssl_type=ssl_type;
- acl_user.ssl_cipher=ssl_cipher;
- acl_user.x509_issuer=x509_issuer;
- acl_user.x509_subject=x509_subject;
-#endif /* HAVE_OPENSSL */
+ acl_user.ssl_type= (ssl_type != SSL_TYPE_NOT_SPECIFIED ?
+ ssl_type : SSL_TYPE_NONE);
+ acl_user.ssl_cipher= ssl_cipher ? strdup_root(&mem,ssl_cipher) : 0;
+ acl_user.x509_issuer= x509_issuer ? strdup_root(&mem,x509_issuer) : 0;
+ acl_user.x509_subject=x509_subject ? strdup_root(&mem,x509_subject) : 0;
if (password)
{
acl_user.password=(char*) ""; // Just point at something
@@ -1295,7 +1309,6 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo,
DBUG_PRINT("info",("table->fields: %d",table->fields));
if (table->fields >= 31) /* From 4.0.0 we have more fields */
{
-#ifdef HAVE_OPENSSL
/* We write down SSL related ACL stuff */
table->field[25]->store("",0);
table->field[26]->store("",0);
@@ -1322,7 +1335,6 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo,
default:
table->field[24]->store("",0);
}
-#endif /* HAVE_OPENSSL */
USER_RESOURCES mqh = thd->lex.mqh;
if (mqh.bits & 1)
@@ -2234,11 +2246,12 @@ void grant_free(void)
/* Init grant array if possible */
-int grant_init (void)
+my_bool grant_init(void)
{
- THD *thd;
+ THD *thd, *org_thd;
TABLE_LIST tables[2];
- int error = 0;
+ MYSQL_LOCK *lock;
+ my_bool return_val= 1;
TABLE *t_table, *c_table;
DBUG_ENTER("grant_init");
@@ -2247,15 +2260,14 @@ int grant_init (void)
(hash_free_key) free_grant_table,0);
init_sql_alloc(&memex,1024,0);
+ /* Don't do anything if running with --skip-grant */
if (!initialized)
DBUG_RETURN(0); /* purecov: tested */
+
+ org_thd=current_thd;
if (!(thd=new THD))
DBUG_RETURN(1); /* purecov: deadcode */
-
- thd->version=refresh_version;
- thd->mysys_var=my_thread_var;
- thd->current_tablenr=0;
- thd->open_tables=0;
+ thd->store_globals();
thd->db= my_strdup("mysql",MYF(0));
thd->db_length=5; // Safety
bzero((char*) &tables,sizeof(tables));
@@ -2266,60 +2278,51 @@ int grant_init (void)
tables[0].db=tables[1].db=thd->db;
if (open_tables(thd,tables))
- { // No grant tables
- close_thread_tables(thd); /* purecov: deadcode */
- delete thd; /* purecov: deadcode */
- DBUG_RETURN(1); /* purecov: deadcode */
- }
+ goto end;
+
TABLE *ptr[2]; // Lock tables for quick update
ptr[0]= tables[0].table;
ptr[1]= tables[1].table;
- MYSQL_LOCK *lock=mysql_lock_tables(thd,ptr,2);
- if (!lock)
- {
- close_thread_tables(thd); /* purecov: deadcode */
- delete thd; /* purecov: deadcode */
- DBUG_RETURN(1); /* purecov: deadcode */
- }
+ if (!(lock=mysql_lock_tables(thd,ptr,2)))
+ goto end;
t_table = tables[0].table; c_table = tables[1].table;
t_table->file->index_init(0);
if (t_table->file->index_first(t_table->record[0]))
{
t_table->file->index_end();
- mysql_unlock_tables(thd, lock);
- thd->version--; // Force close to free memory
- close_thread_tables(thd);
- delete thd;
- DBUG_RETURN(0); // Empty table is ok!
+ goto end_unlock;
}
grant_option= TRUE;
t_table->file->index_end();
- MEM_ROOT *old_root=my_pthread_getspecific_ptr(MEM_ROOT*,THR_MALLOC);
+ /* Will be restored by org_thd->store_globals() */
my_pthread_setspecific_ptr(THR_MALLOC,&memex);
- while (!error)
+ do
{
GRANT_TABLE *mem_check;
if (!(mem_check=new GRANT_TABLE(t_table,c_table)) ||
mem_check->ok() && hash_insert(&hash_tables,(byte*) mem_check))
{
/* This could only happen if we are out memory */
- my_pthread_setspecific_ptr(THR_MALLOC,old_root); /* purecov: deadcode */
grant_option = FALSE; /* purecov: deadcode */
- mysql_unlock_tables(thd, lock); /* purecov: deadcode */
- close_thread_tables(thd); /* purecov: deadcode */
- delete thd; /* purecov: deadcode */
- DBUG_RETURN(1); /* purecov: deadcode */
+ goto end_unlock;
}
- error = t_table->file->index_next(t_table->record[0]);
}
- my_pthread_setspecific_ptr(THR_MALLOC,old_root);
+ while (!t_table->file->index_next(t_table->record[0]));
+
+ return_val=0; // Return ok
+
+end_unlock:
mysql_unlock_tables(thd, lock);
thd->version--; // Force close to free memory
+
+end:
close_thread_tables(thd);
delete thd;
- DBUG_RETURN(0);
+ if (org_thd)
+ org_thd->store_globals();
+ DBUG_RETURN(return_val);
}
@@ -2720,7 +2723,8 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
VOID(pthread_mutex_lock(&acl_cache->lock));
/* Add first global access grants */
- if (acl_user->access || acl_user->password)
+ if (acl_user->access || acl_user->password ||
+ acl_user->ssl_type != SSL_TYPE_NONE)
{
want_access=acl_user->access;
String global(buff,sizeof(buff));
@@ -2759,7 +2763,6 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
global.append(passd_buff);
global.append('\'');
}
-#ifdef HAVE_OPENSSL
/* "show grants" SSL related stuff */
if (acl_user->ssl_type == SSL_TYPE_ANY)
global.append(" REQUIRE SSL",12);
@@ -2772,28 +2775,27 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
if (acl_user->x509_issuer)
{
ssl_options++;
- global.append("ISSUER \"",8);
+ global.append("ISSUER \'",8);
global.append(acl_user->x509_issuer,strlen(acl_user->x509_issuer));
global.append('\'');
}
if (acl_user->x509_subject)
{
if (ssl_options++)
- global.append(" AND ",5);
- global.append("SUBJECT \"",9);
+ global.append(' ');
+ global.append("SUBJECT \'",9);
global.append(acl_user->x509_subject,strlen(acl_user->x509_subject));
global.append('\'');
}
if (acl_user->ssl_cipher)
{
if (ssl_options++)
- global.append(" AND ",5);
+ global.append(' ');
global.append("CIPHER '",8);
global.append(acl_user->ssl_cipher,strlen(acl_user->ssl_cipher));
global.append('\'');
}
}
-#endif /* HAVE_OPENSSL */
if ((want_access & GRANT_ACL) ||
(acl_user->user_resource.questions | acl_user->user_resource.updates |
acl_user->user_resource.connections))
diff --git a/sql/sql_acl.h b/sql/sql_acl.h
index d6cf320c978..0448adc8b1c 100644
--- a/sql/sql_acl.h
+++ b/sql/sql_acl.h
@@ -70,8 +70,8 @@
/* prototypes */
-int acl_init(bool dont_read_acl_tables);
-void acl_reload(void);
+my_bool acl_init(bool dont_read_acl_tables);
+void acl_reload(THD *thd);
void acl_free(bool end=0);
ulong acl_get(const char *host, const char *ip, const char *bin_ip,
const char *user, const char *db);
@@ -87,7 +87,7 @@ int mysql_grant(THD *thd, const char *db, List <LEX_USER> &user_list,
int mysql_table_grant(THD *thd, TABLE_LIST *table, List <LEX_USER> &user_list,
List <LEX_COLUMN> &column_list, ulong rights,
bool revoke);
-int grant_init(void);
+my_bool grant_init(void);
void grant_free(void);
void grant_reload(void);
bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index cfd3daad65c..2578cbb3a52 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -1782,7 +1782,14 @@ int setup_fields(THD *thd, TABLE_LIST *tables, List<Item> &fields,
((Item_field*) item)->table_name,&it))
DBUG_RETURN(-1); /* purecov: inspected */
if (sum_func_list)
- sum_func_list->elements += fields.elements - elem;
+ {
+ /*
+ sum_func_list is a list that has the fields list as a tail.
+ Because of this we have to update the element count also for this
+ list after expanding the '*' entry.
+ */
+ sum_func_list->elements+= fields.elements - elem;
+ }
}
else
{
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 7e03986f4bb..a0dc8253ea4 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -92,6 +92,7 @@ THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0),
query_error=0;
next_insert_id=last_insert_id=0;
open_tables=temporary_tables=handler_tables=0;
+ current_tablenr=0;
handler_items=0;
tmp_table=0;
lock=locked_tables=0;
@@ -136,6 +137,7 @@ THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0),
command=COM_CONNECT;
set_query_id=1;
db_access=NO_ACCESS;
+ version=refresh_version; // For boot
/* Initialize sub structures */
bzero((char*) &mem_root,sizeof(mem_root));
@@ -268,9 +270,13 @@ void THD::awake(bool prepare_to_die)
bool THD::store_globals()
{
- return (my_pthread_setspecific_ptr(THR_THD, this) ||
- my_pthread_setspecific_ptr(THR_MALLOC, &mem_root) ||
- my_pthread_setspecific_ptr(THR_NET, &net));
+ if (my_pthread_setspecific_ptr(THR_THD, this) ||
+ my_pthread_setspecific_ptr(THR_MALLOC, &mem_root) ||
+ my_pthread_setspecific_ptr(THR_NET, &net))
+ return 1;
+ mysys_var=my_thread_var;
+ dbug_thread_id=my_thread_id();
+ return 0;
}
diff --git a/sql/sql_class.h b/sql/sql_class.h
index d101300ba15..3a2d9779eab 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -475,6 +475,7 @@ public:
active_vio = 0;
pthread_mutex_unlock(&LOCK_delete);
}
+ void THD::close_active_vio();
#endif
void awake(bool prepare_to_die);
inline const char* enter_cond(pthread_cond_t *cond, pthread_mutex_t* mutex,
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 5624ef0539c..9b6e6a549c9 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -941,8 +941,6 @@ static pthread_handler_decl(handle_delayed_insert,arg)
strmov(thd->net.last_error,ER(thd->net.last_errno=ER_OUT_OF_RESOURCES));
goto end;
}
- thd->mysys_var=my_thread_var;
- thd->dbug_thread_id=my_thread_id();
#if !defined(__WIN__) && !defined(OS2)
sigset_t set;
VOID(sigemptyset(&set)); // Get mask in use
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 9a6eb05ac5d..854f3924155 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -180,15 +180,14 @@ static int find_keyword(LEX *lex, uint len, bool function)
udf_func *udf;
if (function && using_udf_functions && (udf=find_udf((char*) tok, len)))
{
+ lex->thd->safe_to_cache_query=0;
+ lex->yylval->udf=udf;
switch (udf->returns) {
case STRING_RESULT:
- lex->yylval->udf=udf;
return (udf->type == UDFTYPE_FUNCTION) ? UDF_CHAR_FUNC : UDA_CHAR_SUM;
case REAL_RESULT:
- lex->yylval->udf=udf;
return (udf->type == UDFTYPE_FUNCTION) ? UDF_FLOAT_FUNC : UDA_FLOAT_SUM;
case INT_RESULT:
- lex->yylval->udf=udf;
return (udf->type == UDFTYPE_FUNCTION) ? UDF_INT_FUNC : UDA_INT_SUM;
}
}
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 9be8703b6c5..16ef7e750cd 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -136,7 +136,7 @@ typedef struct st_lex
char *backup_dir; /* For RESTORE/BACKUP */
char* to_log; /* For PURGE MASTER LOGS TO */
char* x509_subject,*x509_issuer,*ssl_cipher;
- enum SSL_type ssl_type; /* defined in violite.h */
+ enum SSL_type ssl_type; /* defined in violite.h */
String *wild;
sql_exchange *exchange;
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index d356f6fa2e7..00e96c8a23c 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -621,9 +621,6 @@ pthread_handler_decl(handle_one_connection,arg)
{
int error;
NET *net= &thd->net;
-
- thd->mysys_var=my_thread_var;
- thd->dbug_thread_id=my_thread_id();
thd->thread_stack= (char*) &thd;
if ((error=check_connections(thd)))
@@ -706,8 +703,6 @@ pthread_handler_decl(handle_bootstrap,arg)
pthread_detach_this_thread();
thd->thread_stack= (char*) &thd;
- thd->mysys_var=my_thread_var;
- thd->dbug_thread_id=my_thread_id();
#if !defined(__WIN__) && !defined(OS2)
sigset_t set;
VOID(sigemptyset(&set)); // Get mask in use
@@ -3324,7 +3319,7 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables)
select_errors=0; /* Write if more errors */
if (options & REFRESH_GRANT)
{
- acl_reload();
+ acl_reload(thd);
grant_reload();
if (mqh_used)
reset_mqh(thd,(LEX_USER *) NULL,true);
diff --git a/sql/sql_repl.h b/sql/sql_repl.h
index 1d919df7309..197fd03ec7c 100644
--- a/sql/sql_repl.h
+++ b/sql/sql_repl.h
@@ -12,8 +12,7 @@ typedef struct st_slave_info
} SLAVE_INFO;
extern my_bool opt_show_slave_auth_info, opt_old_rpl_compat;
-extern char* master_host;
-extern my_string opt_bin_logname, master_info_file;
+extern char *master_host, *master_info_file;
extern bool server_id_supplied;
extern I_List<i_string> binlog_do_db, binlog_ignore_db;
diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc
index 9493f969802..8791f547ea6 100644
--- a/sql/sql_udf.cc
+++ b/sql/sql_udf.cc
@@ -132,13 +132,11 @@ void udf_init()
sql_print_error("Can't allocate memory for udf structures");
hash_free(&udf_hash);
free_root(&mem,MYF(0));
+ delete new_thd;
DBUG_VOID_RETURN;
}
initialized = 1;
- new_thd->mysys_var=my_thread_var;
- new_thd->version = refresh_version; //current_thd->version;
- new_thd->current_tablenr = 0;
- new_thd->open_tables = 0;
+ new_thd->store_globals();
new_thd->db= my_strdup("mysql", MYF(0));
new_thd->db_length=5;
@@ -180,9 +178,10 @@ void udf_init()
{
if (!(dl = dlopen(tmp->dl, RTLD_NOW)))
{
+ /* Print warning to log */
sql_print_error(ER(ER_CANT_OPEN_LIBRARY),
tmp->dl,errno,dlerror());
- del_udf(tmp);
+ /* Keep the udf in the hash so that we can remove it later */
continue;
}
new_dl=1;
@@ -214,16 +213,17 @@ void udf_free()
for (uint idx=0 ; idx < udf_hash.records ; idx++)
{
udf_func *udf=(udf_func*) hash_element(&udf_hash,idx);
- if (udf->dl)
+ if (udf->dlhandle) // Not closed before
{
+ /* Mark all versions using the same handler as closed */
for (uint j=idx+1 ; j < udf_hash.records ; j++)
{
udf_func *tmp=(udf_func*) hash_element(&udf_hash,j);
- if (tmp->dl && !strcmp(udf->dl,tmp->dl))
- tmp->dl=0;
+ if (udf->dlhandle == tmp->dlhandle)
+ tmp->dlhandle=0; // Already closed
}
+ dlclose(udf->dlhandle);
}
- dlclose(udf->dlhandle);
}
hash_free(&udf_hash);
free_root(&mem,MYF(0));
@@ -242,9 +242,9 @@ static void del_udf(udf_func *udf)
else
{
/*
- ** The functions is in use ; Rename the functions instead of removing it.
- ** The functions will be automaticly removed when the least threads
- ** doesn't use it anymore
+ The functions is in use ; Rename the functions instead of removing it.
+ The functions will be automaticly removed when the least threads
+ doesn't use it anymore
*/
char *name= udf->name;
uint name_length=udf->name_length;
@@ -262,6 +262,10 @@ void free_udf(udf_func *udf)
pthread_mutex_lock(&THR_LOCK_udf);
if (!--udf->usage_count)
{
+ /*
+ We come here when someone has deleted the udf function
+ while another thread still was using the udf
+ */
hash_delete(&udf_hash,(byte*) udf);
using_udf_functions=udf_hash.records != 0;
if (!find_udf_dl(udf->dl))
@@ -271,6 +275,7 @@ void free_udf(udf_func *udf)
DBUG_VOID_RETURN;
}
+
/* This is only called if using_udf_functions != 0 */
udf_func *find_udf(const char *name,uint length,bool mark_used)
@@ -282,18 +287,22 @@ udf_func *find_udf(const char *name,uint length,bool mark_used)
pthread_mutex_lock(&THR_LOCK_udf);
udf=(udf_func*) hash_search(&udf_hash,(byte*) name,
length ? length : (uint) strlen(name));
- if (mark_used)
+ if (!udf->dlhandle)
+ udf=0; // Could not be opened
+ else if (mark_used)
udf->usage_count++;
pthread_mutex_unlock(&THR_LOCK_udf);
DBUG_RETURN(udf);
}
+
static void *find_udf_dl(const char *dl)
{
DBUG_ENTER("find_udf_dl");
- /* because only the function name is hashed, we have to search trough
- ** all rows to find the dl.
+ /*
+ Because only the function name is hashed, we have to search trough
+ all rows to find the dl.
*/
for (uint idx=0 ; idx < udf_hash.records ; idx++)
{
@@ -310,7 +319,7 @@ static void *find_udf_dl(const char *dl)
static udf_func *add_udf(char *name, Item_result ret, char *dl,
Item_udftype type)
{
- if (!name || !dl)
+ if (!name || !dl || !(uint) type || (uint) type > (uint) UDFTYPE_AGGREGATE)
return 0;
udf_func *tmp= (udf_func*) alloc_root(&mem, sizeof(udf_func));
if (!tmp)
@@ -362,7 +371,7 @@ int mysql_create_function(THD *thd,udf_func *udf)
}
pthread_mutex_lock(&THR_LOCK_udf);
- if (hash_search(&udf_hash,(byte*) udf->name, udf->name_length))
+ if ((hash_search(&udf_hash,(byte*) udf->name, udf->name_length)))
{
net_printf(&thd->net, ER_UDF_EXISTS, udf->name);
goto err;
@@ -388,8 +397,7 @@ int mysql_create_function(THD *thd,udf_func *udf)
}
udf->name=strdup_root(&mem,udf->name);
udf->dl=strdup_root(&mem,udf->dl);
- if (!udf->name || !udf->dl ||
- !(u_d=add_udf(udf->name,udf->returns,udf->dl,udf->type)))
+ if (!(u_d=add_udf(udf->name,udf->returns,udf->dl,udf->type)))
{
send_error(&thd->net,0); // End of memory
goto err;
@@ -448,13 +456,18 @@ int mysql_drop_function(THD *thd,const char *udf_name)
DBUG_RETURN(1);
}
pthread_mutex_lock(&THR_LOCK_udf);
- if (!(udf=(udf_func*) hash_search(&udf_hash,(byte*) udf_name, (uint) strlen(udf_name))))
+ if (!(udf=(udf_func*) hash_search(&udf_hash,(byte*) udf_name,
+ (uint) strlen(udf_name))))
{
net_printf(&thd->net, ER_FUNCTION_NOT_DEFINED, udf_name);
goto err;
}
del_udf(udf);
- if (!find_udf_dl(udf->dl))
+ /*
+ Close the handle if this was function that was found during boot or
+ CREATE FUNCTION and it's not in use by any other udf function
+ */
+ if (udf->dlhandle && !find_udf_dl(udf->dl))
dlclose(udf->dlhandle);
bzero((char*) &tables,sizeof(tables));
@@ -480,10 +493,3 @@ int mysql_drop_function(THD *thd,const char *udf_name)
}
#endif /* HAVE_DLOPEN */
-
-/*
-** Local variables:
-** tab-width: 8
-** c-basic-offset: 2
-** End:
-*/
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 5f98bcdefd5..6c3b8890c0c 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -126,6 +126,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token MASTER_SYM
%token MAX_SYM
%token MIN_SYM
+%token NONE_SYM
%token OPTIMIZE
%token PURGE
%token REPAIR
@@ -589,7 +590,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
table_to_table_list table_to_table opt_table_list opt_as
handler_rkey_function handler_read_or_scan
single_multi table_wild_list table_wild_one opt_wild union union_list
- precision union_option
+ precision union_option opt_and
END_OF_INPUT
%type <NONE>
@@ -1856,7 +1857,6 @@ simple_expr:
$$ = new Item_sum_udf_str($1, *$3);
else
$$ = new Item_sum_udf_str($1);
- current_thd->safe_to_cache_query=0;
}
| UDA_FLOAT_SUM '(' udf_expr_list ')'
{
@@ -1864,7 +1864,6 @@ simple_expr:
$$ = new Item_sum_udf_float($1, *$3);
else
$$ = new Item_sum_udf_float($1);
- current_thd->safe_to_cache_query=0;
}
| UDA_INT_SUM '(' udf_expr_list ')'
{
@@ -1879,7 +1878,6 @@ simple_expr:
$$ = new Item_func_udf_str($1, *$3);
else
$$ = new Item_func_udf_str($1);
- current_thd->safe_to_cache_query=0;
}
| UDF_FLOAT_FUNC '(' udf_expr_list ')'
{
@@ -1887,7 +1885,6 @@ simple_expr:
$$ = new Item_func_udf_float($1, *$3);
else
$$ = new Item_func_udf_float($1);
- current_thd->safe_to_cache_query=0;
}
| UDF_INT_FUNC '(' udf_expr_list ')'
{
@@ -1895,7 +1892,6 @@ simple_expr:
$$ = new Item_func_udf_int($1, *$3);
else
$$ = new Item_func_udf_int($1);
- current_thd->safe_to_cache_query=0;
}
| UNIQUE_USERS '(' text_literal ',' NUM ',' NUM ',' expr_list ')'
{
@@ -3168,6 +3164,7 @@ keyword:
| NEXT_SYM {}
| NEW_SYM {}
| NO_SYM {}
+ | NONE_SYM {}
| OPEN_SYM {}
| PACK_KEYS_SYM {}
| PASSWORD {}
@@ -3458,13 +3455,13 @@ grant:
GRANT
{
LEX *lex=Lex;
- lex->sql_command = SQLCOM_GRANT;
lex->users_list.empty();
lex->columns.empty();
- lex->grant= lex->grant_tot_col=0;
- lex->select->db=0;
- lex->ssl_type=SSL_TYPE_NONE;
- lex->ssl_cipher=lex->x509_subject=lex->x509_issuer=0;
+ lex->sql_command = SQLCOM_GRANT;
+ lex->grant= lex->grant_tot_col= 0;
+ lex->select->db= 0;
+ lex->ssl_type= SSL_TYPE_NOT_SPECIFIED;
+ lex->ssl_cipher= lex->x509_subject= lex->x509_issuer= 0;
bzero(&(lex->mqh),sizeof(lex->mqh));
}
grant_privileges ON opt_table TO_SYM user_list
@@ -3504,10 +3501,19 @@ grant_privilege:
| REPLICATION CLIENT_SYM { Lex->grant |= REPL_CLIENT_ACL;}
;
-require_list: require_list_element AND require_list
-| require_list_element ;
-require_list_element: SUBJECT_SYM TEXT_STRING
+opt_and:
+ /* empty */ {}
+ | AND {}
+ ;
+
+require_list:
+ require_list_element opt_and require_list
+ | require_list_element
+ ;
+
+require_list_element:
+ SUBJECT_SYM TEXT_STRING
{
LEX *lex=Lex;
if (lex->x509_subject)
@@ -3651,17 +3657,21 @@ column_list_id:
require_clause: /* empty */
| REQUIRE_SYM require_list
- {
- Lex->ssl_type=SSL_TYPE_SPECIFIED;
- }
+ {
+ Lex->ssl_type=SSL_TYPE_SPECIFIED;
+ }
| REQUIRE_SYM SSL_SYM
- {
- Lex->ssl_type=SSL_TYPE_ANY;
- }
+ {
+ Lex->ssl_type=SSL_TYPE_ANY;
+ }
| REQUIRE_SYM X509_SYM
- {
- Lex->ssl_type=SSL_TYPE_X509;
- };
+ {
+ Lex->ssl_type=SSL_TYPE_X509;
+ }
+ | REQUIRE_SYM NONE_SYM
+ {
+ Lex->ssl_type=SSL_TYPE_NONE;
+ }
grant_options:
/* empty */ {}
diff --git a/sql/udf_example.cc b/sql/udf_example.cc
index f5ff9fe67b5..c7b8363f744 100644
--- a/sql/udf_example.cc
+++ b/sql/udf_example.cc
@@ -61,7 +61,7 @@
** On the end is a couple of functions that converts hostnames to ip and
** vice versa.
**
-** A dynamicly loadable file should be compiled sharable
+** A dynamicly loadable file should be compiled shared.
** (something like: gcc -shared -o my_func.so myfunc.cc).
** You can easily get all switches right by doing:
** cd sql ; make udf_example.o
@@ -69,6 +69,8 @@
** the line and add -shared -o udf_example.so to the end of the compile line.
** The resulting library (udf_example.so) should be copied to some dir
** searched by ld. (/usr/lib ?)
+** If you are using gcc, then you should be able to create the udf_example.so
+** by simply doing 'make udf_example.so'.
**
** After the library is made one must notify mysqld about the new
** functions with the commands: