Bug #38452 ERROR 1123 Can't initialize function ': Error message format should be improved
Submitted: 30 Jul 2008 10:26 Modified: 19 Aug 2008 12:40
Reporter: Roland Bouman Email Updates:
Status: Verified Impact on me:
None 
Category:MySQL Server: Errors Severity:S4 (Feature request)
Version:5.0 OS:Any
Assigned to: CPU Architecture:Any
Triage: Triaged: D5 (Feature request)

[30 Jul 2008 10:26] Roland Bouman
Description:
UDF implementors can set the error message in the init function. The documentation explains that the message should not be longer than 80 bytes. The rationale is that the message should fit on a standard terminal.

In the olden days (MySQL 5.0.15 ?) the displayed error message would be like this:
"
ERROR:
<message-buffer>
"

However, in current versions, the error message format is like this:

"
ERROR 1123 (HY000): Can't initialize function '<udf-name>'; <message-buffer>
"
(Note that this error is used in multiple places, blurring the distinction between "there is some systemic error with this UDF" and "The UDF implementor is throwing an error"  -

roland@roland-laptop:~/mysql-5.1.26-rc$ grep -Rn "ER_CANT_INITIALIZE_UDF" sql/*
sql/item_func.cc:2944:      my_error(ER_CANT_INITIALIZE_UDF, MYF(0),
sql/item_func.cc:2963:    my_error(ER_CANT_INITIALIZE_UDF, MYF(0),
sql/sql_plugin.cc:1660:    my_error(ER_CANT_INITIALIZE_UDF, MYF(0), name->str,
sql/sql_udf.cc:406:      my_error(ER_CANT_INITIALIZE_UDF, MYF(0),
)

So apparently it has been chosen that it's ok if the message is longer than 80 bytes. Now, this is great. But for some reason, the format of the error message is defined as:

"Can't initialize function '%-.192s'; %-.80s"

This does not make sense IMO. AFAIK, the function identifier can currently be at most 64 bytes. The buffer passed to the UDF init function is sized MYSQL_ERRMSG_SIZE, which is 512 bytes as far as I know.

So from my perspective, the message format does a disservice to UDF implementors by truncating the error message for no good reason. I can understand that there maybe an internal limit to the length of error messages, but at least the ratio 192 / 80 should be set to something more sensible, like 64 / 208.

I don't know if there are any other things that prevent UDF implementors from signaling error messages longer than 80 bytes, but IMO the error message should not be truncated (unless of course the underlying limitation of the general error message length is exceeded)

How to repeat:
see share/errmsg.txt. You can use this code to play with UDF error messages:

Source
=======
#include <string.h>

#include <my_global.h>
#include <mysql.h>

#if defined(_WIN32)
#define DLLEXP __declspec(dllexport)
#else
#define DLLEXP
#endif

#ifdef __cplusplus
extern "C" {
#endif

DLLEXP my_bool raise_error_init(
  UDF_INIT *initid, UDF_ARGS *args,
  char *message
){
  char *msg;
  unsigned int msg_length;
  if (args->arg_count==1                          /* Require 1 argument    */
  &&  args->arg_type[0]==STRING_RESULT){          /* Must be string type   */
    msg = args->args[0];                          /* Use arg error msg     */
    msg_length = args->lengths[0];                /* error msg len of arg  */
  } else {
    msg = "raise_error expects 1 string arg";     /* Invalid argument(s)!  */
    msg_length = strlen(msg);
  }
  /* The +1 and -1 magic is here to account for the string terminator      */
  if((msg_length+1) > MYSQL_ERRMSG_SIZE) {        /* buffer large enough?  */
    msg_length = MYSQL_ERRMSG_SIZE -1;            /* no, mind string term  */
  }
  memcpy(message, msg, msg_length);               /* Copy to error message */
  message[msg_length] = '\0';                     /* Terminate err message */
  return 1;                                       /* Signal the error      */
}

DLLEXP longlong raise_error(){
  return 0;
}

#ifdef __cplusplus
}
#endif

Compilation and deployment:
==========================
Compile and move binary library to plugin_dir.

windows
-------
open the Visual Studio command prompt. 
Change to the dir where udf_lightspeed_sequence.c is located
type:

cl /Wall /LD /I"C:\Program Files\MySQL\MySQL 5.1\include" raise_error.c

CREATE FUNCTION raise_error
RETURNS INTEGER
SONAME 'raise_error.dll';

linux
-----
go to the directory containing the raise_error.c source file.
type

gcc -Wall -shared `mysql_config --cflags` -o raise_error.so raise_error.c

CREATE FUNCTION raise_error
RETURNS INTEGER
SONAME 'raise_error.so';

mac/osx
-------
go to the directory containing the raise_error.c source file.
type

gcc -Wall -shared `mysql_config --cflags` -lstdc++ -o raise_error.dylib raise_error.c

CREATE FUNCTION raise_error
RETURNS INTEGER
SONAME 'raise_error.dylib';

TEST:
======
SELECT raise_error('01234567890123456789012345678901234567890123456789012345678901234567890123456789You won''t see this....');

Suggested fix:
#1 Clean up usage of

ER_CANT_INITIALIZE_UDF ("Can't initialize function '%-.192s'; %-.80s")

I think usage is misplaced in the following places:

sql/item_func.cc:2963:    my_error(ER_CANT_INITIALIZE_UDF, MYF(0),

(not reachable, see bug 38451)

sql/sql_plugin.cc:1660:    my_error(ER_CANT_INITIALIZE_UDF, MYF(0), name->str,

(Code is about loading plugins, has got nothing to do with UDFs, so it should be another error message)

sql/sql_udf.cc:406:      my_error(ER_CANT_INITIALIZE_UDF, MYF(0),

(Code is about not loading UDFs at all in case of --skip-grant-tables, whereas the message indicates a problem with a particular UDF)

#2  PLease fix the error message format to allow UDF implementors to pass longer messages. Suggest:

"UDF '%-.64s' signaled error; %-.208s"
[15 Aug 2008 12:10] Roland Bouman
Hi miguel,

I tested on 5.1.25, and I see:

ERROR 1123 (HY000): Can't initialize function 'raise_error'; 01234567890123456789012345678901234567890123456789012345678901234567890123456
789

(so, there is extra prefix as compared to your result, and the 'real' message is truncated to 80 bytes)
[19 Aug 2008 12:40] Susanne Ebrecht
Verfied as described on Ubuntu 64bit by using MySQL 5.1 bzr tree:

mysql> SELECT
    -> raise_error('01234567890123456789012345678901234567890123456789012345678901234567890123456
    '> 789You won''t see this....');

ERROR 1123 (HY000): Can't initialize function 'raise_error'; 01234567890123456789012345678901234567890123456789012345678901234567890123456
78