Updated documentation of how to add new native functions.
Small cleanups
This commit is contained in:
parent
c488a2cdc9
commit
684082ce79
@ -1,6 +1 @@
|
|||||||
mwagner@evoq.mwagner.org
|
monty@tik.mysql.fi
|
||||||
tim@threads.polyesthetic.msg
|
|
||||||
tim@work.mysql.com
|
|
||||||
heikki@donna.mysql.fi
|
|
||||||
paul@central.snake.net
|
|
||||||
monty@donna.mysql.fi
|
|
||||||
|
@ -10361,7 +10361,7 @@ feature).
|
|||||||
Ignore the @code{delay_key_write} option for all tables.
|
Ignore the @code{delay_key_write} option for all tables.
|
||||||
@xref{Server parameters}.
|
@xref{Server parameters}.
|
||||||
|
|
||||||
@item -Sg, --skip-grant-tables
|
@item --skip-grant-tables
|
||||||
This option causes the server not to use the privilege system at all. This
|
This option causes the server not to use the privilege system at all. This
|
||||||
gives everyone @emph{full access} to all databases! (You can tell a running
|
gives everyone @emph{full access} to all databases! (You can tell a running
|
||||||
server to start using the grant tables again by executing @code{mysqladmin
|
server to start using the grant tables again by executing @code{mysqladmin
|
||||||
@ -35307,12 +35307,20 @@ To add a new native @strong{MySQL} function, follow these steps:
|
|||||||
Add one line to @file{lex.h} that defines the function name in the
|
Add one line to @file{lex.h} that defines the function name in the
|
||||||
@code{sql_functions[]} array.
|
@code{sql_functions[]} array.
|
||||||
@item
|
@item
|
||||||
Add two lines to @file{sql_yacc.yy}. One indicates the preprocessor
|
If the function prototype is simple (just takes zero, one, two or three
|
||||||
symbol that @code{yacc} should define (this should be added at the
|
arguments), you should in lex.h specify SYM(FUNC_ARG#) (where # is the
|
||||||
beginning of the file). Then define the function parameters and add an
|
number of arguments) as the second argument in the
|
||||||
``item'' with these parameters to the @code{simple_expr} parsing rule.
|
@code{sql_functions[]} array and add a function that creates a function
|
||||||
For an example, check all occurrences of @code{SOUNDEX} in
|
object in @file{item_create.cc}. Take a look at @code{"ABS"} and
|
||||||
@file{sql_yacc.yy} to see how this is done.
|
@code{create_funcs_abs()} for an example of this.
|
||||||
|
|
||||||
|
If the function prototype is complicated (for example takes a variable number
|
||||||
|
of arguments), you should add two lines to @file{sql_yacc.yy}. One
|
||||||
|
indicates the preprocessor symbol that @code{yacc} should define (this
|
||||||
|
should be added at the beginning of the file). Then define the function
|
||||||
|
parameters and add an ``item'' with these parameters to the
|
||||||
|
@code{simple_expr} parsing rule. For an example, check all occurrences
|
||||||
|
of @code{ATAN} in @file{sql_yacc.yy} to see how this is done.
|
||||||
@item
|
@item
|
||||||
In @file{item_func.h}, declare a class inheriting from @code{Item_num_func} or
|
In @file{item_func.h}, declare a class inheriting from @code{Item_num_func} or
|
||||||
@code{Item_str_func}, depending on whether your function returns a number or a
|
@code{Item_str_func}, depending on whether your function returns a number or a
|
||||||
@ -35325,28 +35333,45 @@ double Item_func_newname::val()
|
|||||||
longlong Item_func_newname::val_int()
|
longlong Item_func_newname::val_int()
|
||||||
String *Item_func_newname::Str(String *str)
|
String *Item_func_newname::Str(String *str)
|
||||||
@end example
|
@end example
|
||||||
|
|
||||||
|
If you inherit your object from any of the standard items (like
|
||||||
|
@code{Item_num_func} you probably only have to define one of the above
|
||||||
|
functions and let the parent object take care of the other functions.
|
||||||
|
For example, the @code{Item_str_func} class defines a @code{val()} function
|
||||||
|
that executes @code{atof()} on the value returned by @code{::str()}.
|
||||||
|
|
||||||
@item
|
@item
|
||||||
You should probably also define the following function:
|
You should probably also define the following object function:
|
||||||
@example
|
@example
|
||||||
void Item_func_newname::fix_length_and_dec()
|
void Item_func_newname::fix_length_and_dec()
|
||||||
@end example
|
@end example
|
||||||
This function should at least calculate @code{max_length} based on the
|
This function should at least calculate @code{max_length} based on the
|
||||||
given arguments. @code{max_length} is the maximum number of characters
|
given arguments. @code{max_length} is the maximum number of characters
|
||||||
the function may return. This function should also set @code{maybe_null = 0}
|
the function may return. This function should also set @code{maybe_null
|
||||||
if the main function can't return a @code{NULL} value. The function can check
|
= 0} if the main function can't return a @code{NULL} value. The
|
||||||
if any of the function arguments can return @code{NULL} by checking the
|
function can check if any of the function arguments can return
|
||||||
arguments @code{maybe_null} variable.
|
@code{NULL} by checking the arguments @code{maybe_null} variable. You
|
||||||
|
can take a look at @code{Item_func_mod::fix_length_and_dec} for a
|
||||||
|
typical example of how to do this.
|
||||||
@end enumerate
|
@end enumerate
|
||||||
|
|
||||||
All functions must be thread safe.
|
All functions must be thread safe (In other words, don't use any global or
|
||||||
|
static variables in the functions without protecting them with mutexes).
|
||||||
|
|
||||||
|
If you want to return @code{NULL}, from @code{::val()}, @code{::val_int()}
|
||||||
|
or @code{::str()} you should set @code{null_value} to 1 and return 0.
|
||||||
|
|
||||||
|
For @code{::str()} object functions, there are some additional
|
||||||
|
considerations to be aware of:
|
||||||
|
|
||||||
For string functions, there are some additional considerations to be aware of:
|
|
||||||
@itemize @bullet
|
@itemize @bullet
|
||||||
@item
|
@item
|
||||||
The @code{String *str} argument provides a string
|
The @code{String *str} argument provides a string buffer that may be
|
||||||
buffer that may be used to hold the result.
|
used to hold the result. (For more information about the @code{String} type,
|
||||||
|
take a look at the @file{sql_string.h} file.)
|
||||||
@item
|
@item
|
||||||
The function should return the string that holds the result.
|
The @code{::str()} function should return the string that holds the result or
|
||||||
|
@code{(char*) 0} if the result is @code{NULL}.
|
||||||
@item
|
@item
|
||||||
All current string functions try to avoid allocating any memory unless
|
All current string functions try to avoid allocating any memory unless
|
||||||
absolutely necessary!
|
absolutely necessary!
|
||||||
|
@ -1,2 +1,2 @@
|
|||||||
encrypt('foo', 'ff')
|
length(encrypt('foo', 'ff')) <> 0
|
||||||
ffTU0fyIP09Z.
|
1
|
||||||
|
@ -1 +1,2 @@
|
|||||||
select encrypt('foo', 'ff');
|
|
||||||
|
select length(encrypt('foo', 'ff')) <> 0;
|
||||||
|
@ -449,7 +449,7 @@ int thr_lock(THR_LOCK_DATA *data,enum thr_lock_type lock_type)
|
|||||||
check_locks(lock,"read lock with old write lock",0);
|
check_locks(lock,"read lock with old write lock",0);
|
||||||
if (lock->get_status)
|
if (lock->get_status)
|
||||||
(*lock->get_status)(data->status_param);
|
(*lock->get_status)(data->status_param);
|
||||||
++locks_immediate;
|
statistic_increment(locks_immediate,&THR_LOCK_lock);
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
if (lock->write.data->type == TL_WRITE_ONLY)
|
if (lock->write.data->type == TL_WRITE_ONLY)
|
||||||
@ -473,7 +473,7 @@ int thr_lock(THR_LOCK_DATA *data,enum thr_lock_type lock_type)
|
|||||||
if ((int) lock_type == (int) TL_READ_NO_INSERT)
|
if ((int) lock_type == (int) TL_READ_NO_INSERT)
|
||||||
lock->read_no_write_count++;
|
lock->read_no_write_count++;
|
||||||
check_locks(lock,"read lock with no write locks",0);
|
check_locks(lock,"read lock with no write locks",0);
|
||||||
++locks_immediate;
|
statistic_increment(locks_immediate,&THR_LOCK_lock);
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
/* Can't get lock yet; Wait for it */
|
/* Can't get lock yet; Wait for it */
|
||||||
@ -505,7 +505,7 @@ int thr_lock(THR_LOCK_DATA *data,enum thr_lock_type lock_type)
|
|||||||
data->cond=get_cond();
|
data->cond=get_cond();
|
||||||
if (lock->get_status)
|
if (lock->get_status)
|
||||||
(*lock->get_status)(data->status_param);
|
(*lock->get_status)(data->status_param);
|
||||||
++locks_immediate;
|
statistic_increment(locks_immediate,&THR_LOCK_lock);
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -540,7 +540,7 @@ int thr_lock(THR_LOCK_DATA *data,enum thr_lock_type lock_type)
|
|||||||
check_locks(lock,"second write lock",0);
|
check_locks(lock,"second write lock",0);
|
||||||
if (data->lock->get_status)
|
if (data->lock->get_status)
|
||||||
(*data->lock->get_status)(data->status_param);
|
(*data->lock->get_status)(data->status_param);
|
||||||
++locks_immediate;
|
statistic_increment(locks_immediate,&THR_LOCK_lock);
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
DBUG_PRINT("lock",("write locked by thread: %ld",
|
DBUG_PRINT("lock",("write locked by thread: %ld",
|
||||||
@ -566,7 +566,7 @@ int thr_lock(THR_LOCK_DATA *data,enum thr_lock_type lock_type)
|
|||||||
if (data->lock->get_status)
|
if (data->lock->get_status)
|
||||||
(*data->lock->get_status)(data->status_param);
|
(*data->lock->get_status)(data->status_param);
|
||||||
check_locks(lock,"only write lock",0);
|
check_locks(lock,"only write lock",0);
|
||||||
++locks_immediate;
|
statistic_increment(locks_immediate,&THR_LOCK_lock);
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user