Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
mariadb
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
mariadb
Commits
85547962
Commit
85547962
authored
Sep 13, 2003
by
bell@sanja.is.com.ua
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
new UDF arguments interface (WL#1017) (SCRUM)
parent
08e5a7e1
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
134 additions
and
14 deletions
+134
-14
include/mysql_com.h
include/mysql_com.h
+2
-0
sql/item.cc
sql/item.cc
+4
-3
sql/item.h
sql/item.h
+1
-0
sql/item_func.cc
sql/item_func.cc
+12
-5
sql/sql_parse.cc
sql/sql_parse.cc
+2
-0
sql/sql_yacc.yy
sql/sql_yacc.yy
+39
-5
sql/udf_example.cc
sql/udf_example.cc
+47
-1
tests/udf_test
tests/udf_test
+3
-0
tests/udf_test.res
tests/udf_test.res
+24
-0
No files found.
include/mysql_com.h
View file @
85547962
...
...
@@ -278,6 +278,8 @@ typedef struct st_udf_args
char
**
args
;
/* Pointer to argument */
unsigned
long
*
lengths
;
/* Length of string arguments */
char
*
maybe_null
;
/* Set to 1 for all maybe_null args */
char
**
attributes
;
/* Pointer to attribute name */
unsigned
long
*
attribute_lengths
;
/* Length of attribute arguments */
}
UDF_ARGS
;
/* This holds information about the result */
...
...
sql/item.cc
View file @
85547962
...
...
@@ -39,7 +39,7 @@ void item_init(void)
}
Item
::
Item
()
:
fixed
(
0
)
name_length
(
0
),
fixed
(
0
)
{
marker
=
0
;
maybe_null
=
null_value
=
with_sum_func
=
unsigned_flag
=
0
;
...
...
@@ -121,6 +121,7 @@ void Item::set_name(const char *str, uint length, CHARSET_INFO *cs)
{
/* Empty string, used by AS or internal function like last_insert_id() */
name
=
(
char
*
)
str
;
name_length
=
0
;
return
;
}
while
(
length
&&
!
my_isgraph
(
cs
,
*
str
))
...
...
@@ -131,12 +132,12 @@ void Item::set_name(const char *str, uint length, CHARSET_INFO *cs)
if
(
!
my_charset_same
(
cs
,
system_charset_info
))
{
uint32
res_length
;
name
=
sql_strmake_with_convert
(
str
,
length
,
cs
,
name
=
sql_strmake_with_convert
(
str
,
name_length
=
length
,
cs
,
MAX_ALIAS_NAME
,
system_charset_info
,
&
res_length
);
}
else
name
=
sql_strmake
(
str
,
min
(
length
,
MAX_ALIAS_NAME
));
name
=
sql_strmake
(
str
,
(
name_length
=
min
(
length
,
MAX_ALIAS_NAME
)
));
}
...
...
sql/item.h
View file @
85547962
...
...
@@ -106,6 +106,7 @@ public:
my_string
name
;
/* Name from select */
Item
*
next
;
uint32
max_length
;
uint
name_length
;
/* Length of name */
uint8
marker
,
decimals
;
my_bool
maybe_null
;
/* If item may be null */
my_bool
null_value
;
/* if item is null */
...
...
sql/item_func.cc
View file @
85547962
...
...
@@ -1498,11 +1498,16 @@ udf_handler::fix_fields(THD *thd, TABLE_LIST *tables, Item_result_field *func,
const_item_cache
&=
item
->
const_item
();
f_args
.
arg_type
[
i
]
=
item
->
result_type
();
}
//TODO: why all folowing memory is not allocated with 1 call of sql_alloc?
if
(
!
(
buffers
=
new
String
[
arg_count
])
||
!
(
f_args
.
args
=
(
char
**
)
sql_alloc
(
arg_count
*
sizeof
(
char
*
)))
||
!
(
f_args
.
lengths
=
(
ulong
*
)
sql_alloc
(
arg_count
*
sizeof
(
long
)))
||
!
(
f_args
.
maybe_null
=
(
char
*
)
sql_alloc
(
arg_count
*
sizeof
(
char
)))
||
!
(
num_buffer
=
(
char
*
)
sql_alloc
(
ALIGN_SIZE
(
sizeof
(
double
))
*
arg_count
)))
!
(
f_args
.
lengths
=
(
ulong
*
)
sql_alloc
(
arg_count
*
sizeof
(
long
)))
||
!
(
f_args
.
maybe_null
=
(
char
*
)
sql_alloc
(
arg_count
*
sizeof
(
char
)))
||
!
(
num_buffer
=
(
char
*
)
sql_alloc
(
arg_count
*
ALIGN_SIZE
(
sizeof
(
double
))))
||
!
(
f_args
.
attributes
=
(
char
**
)
sql_alloc
(
arg_count
*
sizeof
(
char
*
)))
||
!
(
f_args
.
attribute_lengths
=
(
ulong
*
)
sql_alloc
(
arg_count
*
sizeof
(
long
))))
{
free_udf
(
u_d
);
DBUG_RETURN
(
1
);
...
...
@@ -1521,8 +1526,10 @@ udf_handler::fix_fields(THD *thd, TABLE_LIST *tables, Item_result_field *func,
for
(
uint
i
=
0
;
i
<
arg_count
;
i
++
)
{
f_args
.
args
[
i
]
=
0
;
f_args
.
lengths
[
i
]
=
arguments
[
i
]
->
max_length
;
f_args
.
maybe_null
[
i
]
=
(
char
)
arguments
[
i
]
->
maybe_null
;
f_args
.
lengths
[
i
]
=
arguments
[
i
]
->
max_length
;
f_args
.
maybe_null
[
i
]
=
(
char
)
arguments
[
i
]
->
maybe_null
;
f_args
.
attributes
[
i
]
=
arguments
[
i
]
->
name
;
f_args
.
attribute_lengths
[
i
]
=
arguments
[
i
]
->
name_length
;
switch
(
arguments
[
i
]
->
type
())
{
case
Item
:
:
STRING_ITEM
:
// Constant string !
...
...
sql/sql_parse.cc
View file @
85547962
...
...
@@ -2986,6 +2986,8 @@ mysql_execute_command(THD *thd)
break
;
#ifdef HAVE_DLOPEN
sp_head
*
sph
=
sp_find_function
(
thd
,
&
lex
->
udf
.
name
);
// close & unlock table opened by sp_find_function
close_thread_tables
(
thd
);
if
(
sph
)
{
net_printf
(
thd
,
ER_UDF_EXISTS
,
lex
->
udf
.
name
.
str
);
...
...
sql/sql_yacc.yy
View file @
85547962
...
...
@@ -630,13 +630,14 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%type <item>
literal text_literal insert_ident order_ident
simple_ident select_item2 expr opt_expr opt_else sum_expr in_sum_expr
table_wild no_in_expr expr_expr simple_expr no_and_expr
table_wild no_in_expr expr_expr simple_expr no_and_expr
udf_expr
using_list expr_or_default set_expr_or_default interval_expr
param_marker singlerow_subselect singlerow_subselect_init
exists_subselect exists_subselect_init sp_opt_default
%type <item_list>
expr_list udf_expr_list when_list ident_list ident_list_arg
expr_list sp_expr_list udf_expr_list udf_expr_list2 when_list
ident_list ident_list_arg
%type <key_type>
key_type opt_unique_or_fulltext
...
...
@@ -702,7 +703,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
select_item_list select_item values_list no_braces
opt_limit_clause delete_limit_clause fields opt_values values
procedure_list procedure_list2 procedure_item
when_list2 expr_list2 handler
when_list2 expr_list2
udf_expr_list3
handler
opt_precision opt_ignore opt_column opt_restrict
grant revoke set lock unlock string_list field_options field_option
field_opt_list opt_binary table_lock_list table_lock
...
...
@@ -3246,7 +3247,7 @@ simple_expr:
{ $$= new Item_func_round($3,$5,1); }
| TRUE_SYM
{ $$= new Item_int((char*) "TRUE",1,1); }
| SP_FUNC '('
udf
_expr_list ')'
| SP_FUNC '('
sp
_expr_list ')'
{
sp_add_fun_to_lex(Lex, $1);
if ($3)
...
...
@@ -3336,10 +3337,43 @@ simple_expr:
| EXTRACT_SYM '(' interval FROM expr ')'
{ $$=new Item_extract( $3, $5); };
udf
_expr_list:
sp
_expr_list:
/* empty */ { $$= NULL; }
| expr_list { $$= $1;};
udf_expr_list:
/* empty */ { $$= NULL; }
| udf_expr_list2 { $$= $1;}
;
udf_expr_list2:
{ Select->expr_list.push_front(new List<Item>); }
udf_expr_list3
{ $$= Select->expr_list.pop(); }
;
udf_expr_list3:
udf_expr
{
Select->expr_list.head()->push_back($1);
}
| udf_expr_list3 ',' udf_expr
{
Select->expr_list.head()->push_back($3);
}
;
udf_expr:
remember_name expr remember_end select_alias
{
if ($4.str)
$2->set_name($4.str,$4.length,system_charset_info);
else
$2->set_name($1,(uint) ($3 - $1), YYTHD->charset());
$$= $2;
}
;
sum_expr:
AVG_SYM '(' in_sum_expr ')'
{ $$=new Item_sum_avg($3); }
...
...
sql/udf_example.cc
View file @
85547962
...
...
@@ -56,7 +56,9 @@
**
** Function 'myfunc_int' returns summary length of all its arguments.
**
** Function 'sequence' returns an sequence starting from a certain number
** Function 'sequence' returns an sequence starting from a certain number.
**
** Function 'myfunc_argument_name' returns name of argument.
**
** On the end is a couple of functions that converts hostnames to ip and
** vice versa.
...
...
@@ -82,6 +84,7 @@
** CREATE FUNCTION lookup RETURNS STRING SONAME "udf_example.so";
** CREATE FUNCTION reverse_lookup RETURNS STRING SONAME "udf_example.so";
** CREATE AGGREGATE FUNCTION avgcost RETURNS REAL SONAME "udf_example.so";
** CREATE FUNCTION myfunc_argument_name RETURNS STRING SONAME "udf_example.so";
**
** After this the functions will work exactly like native MySQL functions.
** Functions should be created only once.
...
...
@@ -94,6 +97,7 @@
** DROP FUNCTION lookup;
** DROP FUNCTION reverse_lookup;
** DROP FUNCTION avgcost;
** DROP FUNCTION myfunc_argument_name;
**
** The CREATE FUNCTION and DROP FUNCTION update the func@mysql table. All
** Active function will be reloaded on every restart of server
...
...
@@ -975,4 +979,46 @@ avgcost( UDF_INIT* initid, UDF_ARGS* args, char* is_null, char* error )
return
data
->
totalprice
/
double
(
data
->
totalquantity
);
}
extern
"C"
{
my_bool
myfunc_argument_name_init
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
message
);
void
myfunc_argument_name_deinit
(
UDF_INIT
*
initid
);
char
*
myfunc_argument_name
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
result
,
unsigned
long
*
length
,
char
*
null_value
,
char
*
error
);
}
my_bool
myfunc_argument_name_init
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
message
)
{
if
(
args
->
arg_count
!=
1
)
{
strmov
(
message
,
"myfunc_argument_name_init accepts only one argument"
);
return
1
;
}
initid
->
max_length
=
args
->
attribute_lengths
[
0
];
initid
->
maybe_null
=
1
;
initid
->
const_item
=
1
;
return
0
;
}
void
myfunc_argument_name_deinit
(
UDF_INIT
*
initid
)
{}
char
*
myfunc_argument_name
(
UDF_INIT
*
initid
,
UDF_ARGS
*
args
,
char
*
result
,
unsigned
long
*
length
,
char
*
null_value
,
char
*
error
)
{
if
(
!
args
->
attributes
[
0
])
{
null_value
=
0
;
return
0
;
}
(
*
length
)
--
;
// space for ending \0 (for debugging purposes)
if
(
*
length
>
args
->
attribute_lengths
[
0
])
*
length
=
args
->
attribute_lengths
[
0
];
memcpy
(
result
,
args
->
attributes
[
0
],
*
length
);
result
[
*
length
]
=
0
;
return
result
;
}
#endif
/* HAVE_DLOPEN */
tests/udf_test
View file @
85547962
...
...
@@ -9,6 +9,7 @@ CREATE FUNCTION myfunc_int RETURNS INTEGER SONAME "udf_example.so";
CREATE FUNCTION lookup RETURNS STRING SONAME "udf_example.so";
CREATE FUNCTION reverse_lookup RETURNS STRING SONAME "udf_example.so";
CREATE AGGREGATE FUNCTION avgcost RETURNS REAL SONAME "udf_example.so";
CREATE FUNCTION myfunc_argument_name RETURNS STRING SONAME "udf_example.so";
select metaphon("hello");
select myfunc_double("hello","world");
...
...
@@ -20,6 +21,7 @@ create temporary table t1 (a int,b double);
insert into t1 values (1,5),(1,4),(2,8),(3,9),(4,11);
select avgcost(a,b) from t1;
select avgcost(a,b) from t1 group by a;
select a, myfunc_argument_name(a) from t1;
drop table t1;
DROP FUNCTION metaphon;
...
...
@@ -28,3 +30,4 @@ DROP FUNCTION myfunc_int;
DROP FUNCTION lookup;
DROP FUNCTION reverse_lookup;
DROP FUNCTION avgcost;
DROP FUNCTION myfunc_argument_name;
tests/udf_test.res
View file @
85547962
...
...
@@ -34,6 +34,12 @@ CREATE AGGREGATE FUNCTION avgcost RETURNS REAL SONAME "udf_example.so"
Query OK, 0 rows affected
--------------
CREATE FUNCTION myfunc_argument_name RETURNS STRING SONAME "udf_example.so"
--------------
Query OK, 0 rows affected
--------------
select metaphon("hello")
--------------
...
...
@@ -106,6 +112,18 @@ avgcost(a,b)
11.0000
4 rows in set
--------------
select a, myfunc_argument_name(a) from t1;
--------------
a myfunc_argument_name(a)
1 a
1 a
2 a
3 a
4 a
5 rows in set
--------------
drop table t1
--------------
...
...
@@ -148,4 +166,10 @@ DROP FUNCTION avgcost
Query OK, 0 rows affected
--------------
DROP FUNCTION myfunc_argument_name;
--------------
Query OK, 0 rows affected
Bye
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment