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
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexedi
MariaDB
Commits
13987057
Commit
13987057
authored
Mar 19, 2004
by
pem@mysql.comhem.se
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
WL#1366: Use the schema (db) associated with an SP.
Phase 3: Made qualified names work for functions as well.
parent
786f8232
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
286 additions
and
143 deletions
+286
-143
mysql-test/r/sp-security.result
mysql-test/r/sp-security.result
+25
-0
mysql-test/t/sp-security.test
mysql-test/t/sp-security.test
+18
-2
sql/item_func.cc
sql/item_func.cc
+14
-1
sql/item_func.h
sql/item_func.h
+6
-0
sql/mysql_priv.h
sql/mysql_priv.h
+1
-2
sql/sp.cc
sql/sp.cc
+96
-10
sql/sp_head.cc
sql/sp_head.cc
+9
-3
sql/sql_db.cc
sql/sql_db.cc
+40
-55
sql/sql_yacc.yy
sql/sql_yacc.yy
+77
-70
No files found.
mysql-test/r/sp-security.result
View file @
13987057
...
...
@@ -10,14 +10,27 @@ insert into db1_secret.t1 values (user(), i);
show procedure status like 'stamp';
Db Name Type Definer Modified Created Security_type Comment
db1_secret stamp PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER
create function db() returns varchar(64) return database();
show function status like 'db';
Db Name Type Definer Modified Created Security_type Comment
db1_secret db FUNCTION root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER
call stamp(1);
select * from t1;
u i
root@localhost 1
select db();
db()
db1_secret
call db1_secret.stamp(2);
select db1_secret.db();
db1_secret.db()
db1_secret
select * from db1_secret.t1;
ERROR 42000: Access denied for user: 'user1'@'localhost' to database 'db1_secret'
call db1_secret.stamp(3);
select db1_secret.db();
db1_secret.db()
db1_secret
select * from db1_secret.t1;
ERROR 42000: Access denied for user: ''@'localhost' to database 'db1_secret'
select * from t1;
...
...
@@ -29,6 +42,10 @@ alter procedure stamp sql security invoker;
show procedure status like 'stamp';
Db Name Type Definer Modified Created Security_type Comment
db1_secret stamp PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 INVOKER
alter function db sql security invoker;
show function status like 'db';
Db Name Type Definer Modified Created Security_type Comment
db1_secret db FUNCTION root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 INVOKER
call stamp(4);
select * from t1;
u i
...
...
@@ -36,10 +53,17 @@ root@localhost 1
user1@localhost 2
anon@localhost 3
root@localhost 4
select db();
db()
db1_secret
call db1_secret.stamp(5);
ERROR 42000: Access denied for user: 'user1'@'localhost' to database 'db1_secret'
select db1_secret.db();
ERROR 42000: Access denied for user: 'user1'@'localhost' to database 'db1_secret'
call db1_secret.stamp(6);
ERROR 42000: Access denied for user: ''@'localhost' to database 'db1_secret'
select db1_secret.db();
ERROR 42000: Access denied for user: ''@'localhost' to database 'db1_secret'
drop database if exists db2;
create database db2;
use db2;
...
...
@@ -74,6 +98,7 @@ s1
2
2
drop procedure db1_secret.stamp;
drop function db1_secret.db;
drop procedure db2.p;
drop procedure db2.q;
use test;
...
...
mysql-test/t/sp-security.test
View file @
13987057
...
...
@@ -21,15 +21,20 @@ use db1_secret;
create
table
t1
(
u
varchar
(
64
),
i
int
);
#
Our test procedure
#
A test procedure and function
create
procedure
stamp
(
i
int
)
insert
into
db1_secret
.
t1
values
(
user
(),
i
);
--
replace_column
5
'0000-00-00 00:00:00'
6
'0000-00-00 00:00:00'
show
procedure
status
like
'stamp'
;
create
function
db
()
returns
varchar
(
64
)
return
database
();
--
replace_column
5
'0000-00-00 00:00:00'
6
'0000-00-00 00:00:00'
show
function
status
like
'db'
;
# root can, of course
call
stamp
(
1
);
select
*
from
t1
;
select
db
();
connect
(
con2user1
,
localhost
,
user1
,,);
connect
(
con3anon
,
localhost
,
anon
,,);
...
...
@@ -41,6 +46,7 @@ connection con2user1;
# This should work...
call
db1_secret
.
stamp
(
2
);
select
db1_secret
.
db
();
# ...but not this
--
error
1044
...
...
@@ -53,6 +59,7 @@ connection con3anon;
# This should work...
call
db1_secret
.
stamp
(
3
);
select
db1_secret
.
db
();
# ...but not this
--
error
1044
...
...
@@ -71,9 +78,14 @@ alter procedure stamp sql security invoker;
--
replace_column
5
'0000-00-00 00:00:00'
6
'0000-00-00 00:00:00'
show
procedure
status
like
'stamp'
;
alter
function
db
sql
security
invoker
;
--
replace_column
5
'0000-00-00 00:00:00'
6
'0000-00-00 00:00:00'
show
function
status
like
'db'
;
# root still can
call
stamp
(
4
);
select
*
from
t1
;
select
db
();
#
# User1 cannot
...
...
@@ -83,6 +95,8 @@ connection con2user1;
# This should not work
--
error
1044
call
db1_secret
.
stamp
(
5
);
--
error
1044
select
db1_secret
.
db
();
#
# Anonymous cannot
...
...
@@ -92,7 +106,8 @@ connection con3anon;
# This should not work
--
error
1044
call
db1_secret
.
stamp
(
6
);
--
error
1044
select
db1_secret
.
db
();
#
# BUG#2777
...
...
@@ -149,6 +164,7 @@ select * from t2;
# Clean up
connection
con1root
;
drop
procedure
db1_secret
.
stamp
;
drop
function
db1_secret
.
db
;
drop
procedure
db2
.
p
;
drop
procedure
db2
.
q
;
use
test
;
...
...
sql/item_func.cc
View file @
13987057
...
...
@@ -3120,7 +3120,11 @@ Item_func_sp::execute(Item **itp)
if
(
!
m_sp
)
m_sp
=
sp_find_function
(
thd
,
m_name
);
if
(
!
m_sp
)
{
my_printf_error
(
ER_SP_DOES_NOT_EXIST
,
ER
(
ER_SP_DOES_NOT_EXIST
),
MYF
(
0
),
"FUNCTION"
,
m_name
->
m_qname
);
DBUG_RETURN
(
-
1
);
}
#ifndef NO_EMBEDDED_ACCESS_CHECKS
sp_change_security_context
(
thd
,
m_sp
,
&
save_ctx
);
...
...
@@ -3147,6 +3151,8 @@ Item_func_sp::field_type() const
DBUG_PRINT
(
"info"
,
(
"m_returns = %d"
,
m_sp
->
m_returns
));
DBUG_RETURN
(
m_sp
->
m_returns
);
}
my_printf_error
(
ER_SP_DOES_NOT_EXIST
,
ER
(
ER_SP_DOES_NOT_EXIST
),
MYF
(
0
),
"FUNCTION"
,
m_name
->
m_qname
);
DBUG_RETURN
(
MYSQL_TYPE_STRING
);
}
...
...
@@ -3162,6 +3168,8 @@ Item_func_sp::result_type() const
{
DBUG_RETURN
(
m_sp
->
result
());
}
my_printf_error
(
ER_SP_DOES_NOT_EXIST
,
ER
(
ER_SP_DOES_NOT_EXIST
),
MYF
(
0
),
"FUNCTION"
,
m_name
->
m_qname
);
DBUG_RETURN
(
STRING_RESULT
);
}
...
...
@@ -3172,7 +3180,12 @@ Item_func_sp::fix_length_and_dec()
if
(
!
m_sp
)
m_sp
=
sp_find_function
(
current_thd
,
m_name
);
if
(
m_sp
)
if
(
!
m_sp
)
{
my_printf_error
(
ER_SP_DOES_NOT_EXIST
,
ER
(
ER_SP_DOES_NOT_EXIST
),
MYF
(
0
),
"FUNCTION"
,
m_name
->
m_qname
);
}
else
{
switch
(
m_sp
->
result
())
{
case
STRING_RESULT
:
...
...
sql/item_func.h
View file @
13987057
...
...
@@ -1107,7 +1107,10 @@ class Item_func_sp :public Item_func
Item
*
it
;
if
(
execute
(
&
it
))
{
null_value
=
1
;
return
0.0
;
}
return
it
->
val
();
}
...
...
@@ -1116,7 +1119,10 @@ class Item_func_sp :public Item_func
Item
*
it
;
if
(
execute
(
&
it
))
{
null_value
=
1
;
return
NULL
;
}
return
it
->
val_str
(
str
);
}
...
...
sql/mysql_priv.h
View file @
13987057
...
...
@@ -445,8 +445,7 @@ int mysql_rm_table_part2_with_lock(THD *thd, TABLE_LIST *tables,
int
quick_rm_table
(
enum
db_type
base
,
const
char
*
db
,
const
char
*
table_name
);
bool
mysql_rename_tables
(
THD
*
thd
,
TABLE_LIST
*
table_list
);
bool
mysql_change_db
(
THD
*
thd
,
const
char
*
name
,
bool
empty_is_ok
=
0
,
bool
no_access_check
=
0
);
bool
mysql_change_db
(
THD
*
thd
,
const
char
*
name
);
void
mysql_parse
(
THD
*
thd
,
char
*
inBuf
,
uint
length
);
bool
is_update_query
(
enum
enum_sql_command
command
);
void
free_items
(
Item
*
item
);
...
...
sql/sp.cc
View file @
13987057
...
...
@@ -16,6 +16,7 @@
#include "mysql_priv.h"
#include "sql_acl.h"
#include "sp.h"
#include "sp_head.h"
#include "sp_cache.h"
...
...
@@ -960,19 +961,104 @@ sp_use_new_db(THD *thd, char *newdb, char *olddb, uint olddblen,
}
}
/*
Change database.
SYNOPSIS
sp_change_db()
thd Thread handler
name Database name
empty_is_ok True= it's ok with "" as name
no_access_check True= don't do access check
DESCRIPTION
This is the same as mysql_change_db(), but with some extra
arguments for Stored Procedure usage; doing implicit "use"
when executing an SP in a different database.
We also use different error routines, since this might be
invoked from a function when executing a query or statement.
Note: We would have prefered to reuse mysql_change_db(), but
the error handling in particular made that too awkward, so
we (reluctantly) have a "copy" here.
RETURN VALUES
0 ok
1 error
*/
int
sp_change_db
(
THD
*
thd
,
char
*
db
,
bool
no_access_check
)
sp_change_db
(
THD
*
thd
,
char
*
name
,
bool
no_access_check
)
{
int
ret
;
ulong
dbaccess
=
thd
->
db_access
;
/* mysql_change_db() changes this */
my_bool
nsok
=
thd
->
net
.
no_send_ok
;
/* mysql_change_db() does send_ok() */
thd
->
net
.
no_send_ok
=
TRUE
;
int
length
,
db_length
;
char
*
dbname
=
my_strdup
((
char
*
)
name
,
MYF
(
MY_WME
));
char
path
[
FN_REFLEN
];
ulong
db_access
;
HA_CREATE_INFO
create
;
DBUG_ENTER
(
"sp_change_db"
);
DBUG_PRINT
(
"enter"
,
(
"db: %s, no_access_check: %d"
,
db
,
no_access_check
));
DBUG_PRINT
(
"enter"
,
(
"db: %s, no_access_check: %d"
,
name
,
no_access_check
));
ret
=
mysql_change_db
(
thd
,
db
,
1
,
no_access_check
);
db_length
=
(
!
dbname
?
0
:
strip_sp
(
dbname
));
if
(
dbname
&&
db_length
)
{
if
((
db_length
>
NAME_LEN
)
||
check_db_name
(
dbname
))
{
my_printf_error
(
ER_WRONG_DB_NAME
,
ER
(
ER_WRONG_DB_NAME
),
MYF
(
0
),
dbname
);
x_free
(
dbname
);
DBUG_RETURN
(
1
);
}
}
thd
->
net
.
no_send_ok
=
nsok
;
thd
->
db_access
=
dbaccess
;
DBUG_RETURN
(
ret
);
if
(
dbname
&&
db_length
)
{
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if
(
!
no_access_check
)
{
if
(
test_all_bits
(
thd
->
master_access
,
DB_ACLS
))
db_access
=
DB_ACLS
;
else
db_access
=
(
acl_get
(
thd
->
host
,
thd
->
ip
,
thd
->
priv_user
,
dbname
,
0
)
|
thd
->
master_access
);
if
(
!
(
db_access
&
DB_ACLS
)
&&
(
!
grant_option
||
check_grant_db
(
thd
,
dbname
)))
{
my_printf_error
(
ER_DBACCESS_DENIED_ERROR
,
ER
(
ER_DBACCESS_DENIED_ERROR
),
MYF
(
0
),
thd
->
priv_user
,
thd
->
priv_host
,
dbname
);
mysql_log
.
write
(
thd
,
COM_INIT_DB
,
ER
(
ER_DBACCESS_DENIED_ERROR
),
thd
->
priv_user
,
thd
->
priv_host
,
dbname
);
my_free
(
dbname
,
MYF
(
0
));
DBUG_RETURN
(
1
);
}
}
#endif
(
void
)
sprintf
(
path
,
"%s/%s"
,
mysql_data_home
,
dbname
);
length
=
unpack_dirname
(
path
,
path
);
// Convert if not unix
if
(
length
&&
path
[
length
-
1
]
==
FN_LIBCHAR
)
path
[
length
-
1
]
=
0
;
// remove ending '\'
if
(
access
(
path
,
F_OK
))
{
my_printf_error
(
ER_BAD_DB_ERROR
,
ER
(
ER_BAD_DB_ERROR
),
MYF
(
0
),
dbname
);
my_free
(
dbname
,
MYF
(
0
));
DBUG_RETURN
(
1
);
}
}
x_free
(
thd
->
db
);
thd
->
db
=
dbname
;
// THD::~THD will free this
thd
->
db_length
=
db_length
;
if
(
dbname
&&
db_length
)
{
strmov
(
path
+
unpack_dirname
(
path
,
path
),
MY_DB_OPT_FILE
);
load_db_opt
(
thd
,
path
,
&
create
);
thd
->
db_charset
=
create
.
default_table_charset
?
create
.
default_table_charset
:
thd
->
variables
.
collation_server
;
thd
->
variables
.
collation_database
=
thd
->
db_charset
;
}
DBUG_RETURN
(
0
);
}
sql/sp_head.cc
View file @
13987057
...
...
@@ -389,12 +389,13 @@ sp_head::execute(THD *thd)
continue
;
}
}
}
while
(
ret
==
0
&&
!
thd
->
killed
&&
!
thd
->
query_error
);
}
while
(
ret
==
0
&&
!
thd
->
killed
&&
!
thd
->
query_error
&&
!
thd
->
net
.
report_error
);
done:
DBUG_PRINT
(
"info"
,
(
"ret=%d killed=%d query_error=%d"
,
ret
,
thd
->
killed
,
thd
->
query_error
));
if
(
thd
->
killed
||
thd
->
query_error
)
if
(
thd
->
killed
||
thd
->
query_error
||
thd
->
net
.
report_error
)
ret
=
-
1
;
/* If the DB has changed, the pointer has changed too, but the
original thd->db will then have been freed */
...
...
@@ -553,7 +554,12 @@ sp_head::execute_procedure(THD *thd, List<Item> *args)
ret
=
execute
(
thd
);
// Don't copy back OUT values if we got an error
if
(
ret
==
0
&&
csize
>
0
)
if
(
ret
)
{
if
(
thd
->
net
.
report_error
)
send_error
(
thd
,
0
,
NullS
);
}
else
if
(
csize
>
0
)
{
List_iterator_fast
<
Item
>
li
(
*
args
);
Item
*
it
;
...
...
sql/sql_db.cc
View file @
13987057
...
...
@@ -595,8 +595,7 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db,
1 error
*/
bool
mysql_change_db
(
THD
*
thd
,
const
char
*
name
,
bool
empty_is_ok
,
bool
no_access_check
)
bool
mysql_change_db
(
THD
*
thd
,
const
char
*
name
)
{
int
length
,
db_length
;
char
*
dbname
=
my_strdup
((
char
*
)
name
,
MYF
(
MY_WME
));
...
...
@@ -605,76 +604,62 @@ bool mysql_change_db(THD *thd, const char *name,
HA_CREATE_INFO
create
;
DBUG_ENTER
(
"mysql_change_db"
);
if
(
(
!
dbname
||
!
(
db_length
=
strip_sp
(
dbname
)))
&&
!
empty_is_ok
)
if
(
!
dbname
||
!
(
db_length
=
strip_sp
(
dbname
))
)
{
x_free
(
dbname
);
/* purecov: inspected */
send_error
(
thd
,
ER_NO_DB_ERROR
);
/* purecov: inspected */
DBUG_RETURN
(
1
);
/* purecov: inspected */
}
if
(
!
empty_is_ok
||
(
dbname
&&
db_length
))
if
(
(
db_length
>
NAME_LEN
)
||
check_db_name
(
dbname
))
{
if
((
db_length
>
NAME_LEN
)
||
check_db_name
(
dbname
))
{
net_printf
(
thd
,
ER_WRONG_DB_NAME
,
dbname
);
x_free
(
dbname
);
DBUG_RETURN
(
1
);
}
net_printf
(
thd
,
ER_WRONG_DB_NAME
,
dbname
);
x_free
(
dbname
);
DBUG_RETURN
(
1
);
}
DBUG_PRINT
(
"info"
,(
"Use database: %s"
,
dbname
));
if
(
!
empty_is_ok
||
(
dbname
&&
db_length
))
{
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if
(
!
no_access_check
)
{
if
(
test_all_bits
(
thd
->
master_access
,
DB_ACLS
))
db_access
=
DB_ACLS
;
else
db_access
=
(
acl_get
(
thd
->
host
,
thd
->
ip
,
thd
->
priv_user
,
dbname
,
0
)
|
thd
->
master_access
);
if
(
!
(
db_access
&
DB_ACLS
)
&&
(
!
grant_option
||
check_grant_db
(
thd
,
dbname
)))
{
net_printf
(
thd
,
ER_DBACCESS_DENIED_ERROR
,
thd
->
priv_user
,
thd
->
priv_host
,
dbname
);
mysql_log
.
write
(
thd
,
COM_INIT_DB
,
ER
(
ER_DBACCESS_DENIED_ERROR
),
thd
->
priv_user
,
thd
->
priv_host
,
dbname
);
my_free
(
dbname
,
MYF
(
0
));
DBUG_RETURN
(
1
);
}
}
if
(
test_all_bits
(
thd
->
master_access
,
DB_ACLS
))
db_access
=
DB_ACLS
;
else
db_access
=
(
acl_get
(
thd
->
host
,
thd
->
ip
,
thd
->
priv_user
,
dbname
,
0
)
|
thd
->
master_access
);
if
(
!
(
db_access
&
DB_ACLS
)
&&
(
!
grant_option
||
check_grant_db
(
thd
,
dbname
)))
{
net_printf
(
thd
,
ER_DBACCESS_DENIED_ERROR
,
thd
->
priv_user
,
thd
->
priv_host
,
dbname
);
mysql_log
.
write
(
thd
,
COM_INIT_DB
,
ER
(
ER_DBACCESS_DENIED_ERROR
),
thd
->
priv_user
,
thd
->
priv_host
,
dbname
);
my_free
(
dbname
,
MYF
(
0
));
DBUG_RETURN
(
1
);
}
#endif
(
void
)
sprintf
(
path
,
"%s/%s"
,
mysql_data_home
,
dbname
);
length
=
unpack_dirname
(
path
,
path
);
// Convert if not unix
if
(
length
&&
path
[
length
-
1
]
==
FN_LIBCHAR
)
path
[
length
-
1
]
=
0
;
// remove ending '\'
if
(
access
(
path
,
F_OK
))
{
net_printf
(
thd
,
ER_BAD_DB_ERROR
,
dbname
);
my_free
(
dbname
,
MYF
(
0
));
DBUG_RETURN
(
1
);
}
(
void
)
sprintf
(
path
,
"%s/%s"
,
mysql_data_home
,
dbname
);
length
=
unpack_dirname
(
path
,
path
);
// Convert if not unix
if
(
length
&&
path
[
length
-
1
]
==
FN_LIBCHAR
)
path
[
length
-
1
]
=
0
;
// remove ending '\'
if
(
access
(
path
,
F_OK
))
{
net_printf
(
thd
,
ER_BAD_DB_ERROR
,
dbname
);
my_free
(
dbname
,
MYF
(
0
));
DBUG_RETURN
(
1
);
}
send_ok
(
thd
);
x_free
(
thd
->
db
);
thd
->
db
=
dbname
;
// THD::~THD will free this
thd
->
db_length
=
db_length
;
if
(
!
empty_is_ok
||
(
dbname
&&
db_length
))
{
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if
(
!
no_access_check
)
thd
->
db_access
=
db_access
;
thd
->
db_access
=
db_access
;
#endif
strmov
(
path
+
unpack_dirname
(
path
,
path
),
MY_DB_OPT_FILE
);
load_db_opt
(
thd
,
path
,
&
create
);
thd
->
db_charset
=
create
.
default_table_charset
?
create
.
default_table_charset
:
thd
->
variables
.
collation_server
;
thd
->
variables
.
collation_database
=
thd
->
db_charset
;
}
strmov
(
path
+
unpack_dirname
(
path
,
path
),
MY_DB_OPT_FILE
);
load_db_opt
(
thd
,
path
,
&
create
);
thd
->
db_charset
=
create
.
default_table_charset
?
create
.
default_table_charset
:
thd
->
variables
.
collation_server
;
thd
->
variables
.
collation_database
=
thd
->
db_charset
;
DBUG_RETURN
(
0
);
}
sql/sql_yacc.yy
View file @
13987057
...
...
@@ -3923,83 +3923,90 @@ simple_expr:
{ $$= new Item_func_round($3,$5,1); }
| TRUE_SYM
{ $$= new Item_int((char*) "TRUE",1,1); }
|
IDENT_sys
'(' udf_expr_list ')'
|
ident '.' ident
'(' udf_expr_list ')'
{
sp_name *name= sp_name_current_db_new(YYTHD, $1);
if (sp_function_exists(YYTHD, name))
{
LEX *lex= Lex;
LEX *lex= Lex;
sp_name *name= new sp_name($1, $3);
sp_add_fun_to_lex(lex, name);
if ($3)
$$= new Item_func_sp(name, *$3);
else
$$= new Item_func_sp(name);
}
name->init_qname(YYTHD);
sp_add_fun_to_lex(Lex, name);
if ($5)
$$= new Item_func_sp(name, *$5);
else
{
$$= new Item_func_sp(name);
}
| IDENT_sys '(' udf_expr_list ')'
{
#ifdef HAVE_DLOPEN
udf_func *udf;
udf_func *udf;
if (using_udf_functions && (udf=find_udf($1.str, $1.length)))
{
switch (udf->returns) {
case STRING_RESULT:
if (udf->type == UDFTYPE_FUNCTION)
{
if ($3 != NULL)
$$ = new Item_func_udf_str(udf, *$3);
else
$$ = new Item_func_udf_str(udf);
}
else
{
if ($3 != NULL)
$$ = new Item_sum_udf_str(udf, *$3);
else
$$ = new Item_sum_udf_str(udf);
}
break;
case REAL_RESULT:
if (udf->type == UDFTYPE_FUNCTION)
{
if ($3 != NULL)
$$ = new Item_func_udf_float(udf, *$3);
else
$$ = new Item_func_udf_float(udf);
}
else
{
if ($3 != NULL)
$$ = new Item_sum_udf_float(udf, *$3);
else
$$ = new Item_sum_udf_float(udf);
}
break;
case INT_RESULT:
if (udf->type == UDFTYPE_FUNCTION)
{
if ($3 != NULL)
$$ = new Item_func_udf_int(udf, *$3);
else
$$ = new Item_func_udf_int(udf);
}
else
{
if ($3 != NULL)
$$ = new Item_sum_udf_int(udf, *$3);
else
$$ = new Item_sum_udf_int(udf);
}
break;
default:
YYABORT;
}
}
if (using_udf_functions && (udf=find_udf($1.str, $1.length)))
{
switch (udf->returns) {
case STRING_RESULT:
if (udf->type == UDFTYPE_FUNCTION)
{
if ($3 != NULL)
$$ = new Item_func_udf_str(udf, *$3);
else
$$ = new Item_func_udf_str(udf);
}
else
{
if ($3 != NULL)
$$ = new Item_sum_udf_str(udf, *$3);
else
$$ = new Item_sum_udf_str(udf);
}
break;
case REAL_RESULT:
if (udf->type == UDFTYPE_FUNCTION)
{
if ($3 != NULL)
$$ = new Item_func_udf_float(udf, *$3);
else
$$ = new Item_func_udf_float(udf);
}
else
{
if ($3 != NULL)
$$ = new Item_sum_udf_float(udf, *$3);
else
$$ = new Item_sum_udf_float(udf);
}
break;
case INT_RESULT:
if (udf->type == UDFTYPE_FUNCTION)
{
if ($3 != NULL)
$$ = new Item_func_udf_int(udf, *$3);
else
$$ = new Item_func_udf_int(udf);
}
else
{
if ($3 != NULL)
$$ = new Item_sum_udf_int(udf, *$3);
else
$$ = new Item_sum_udf_int(udf);
}
break;
default:
YYABORT;
}
}
else
#endif /* HAVE_DLOPEN */
{
sp_name *name= sp_name_current_db_new(YYTHD, $1);
sp_add_fun_to_lex(Lex, name);
if ($3)
$$= new Item_func_sp(name, *$3);
else
$$= new Item_func_sp(name);
}
}
}
| UNIQUE_USERS '(' text_literal ',' NUM ',' NUM ',' expr_list ')'
{
$$= new Item_func_unique_users($3,atoi($5.str),atoi($7.str), * $9);
...
...
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