1--source include/have_udf.inc 2# 3# To run this tests the "sql/udf_example.c" need to be compiled into 4# udf_example.so and LD_LIBRARY_PATH should be setup to point out where 5# the library are. 6# 7 8 9--disable_warnings 10drop table if exists t1; 11--enable_warnings 12 13# 14# Create the example functions from udf_example 15# 16 17--replace_result $UDF_EXAMPLE_SO UDF_EXAMPLE_LIB 18eval CREATE FUNCTION metaphon RETURNS STRING SONAME "$UDF_EXAMPLE_SO"; 19--replace_result $UDF_EXAMPLE_SO UDF_EXAMPLE_LIB 20eval CREATE FUNCTION myfunc_double RETURNS REAL SONAME "$UDF_EXAMPLE_SO"; 21 22--replace_result $UDF_EXAMPLE_SO UDF_EXAMPLE_LIB 23--error ER_CANT_FIND_DL_ENTRY 24eval CREATE FUNCTION myfunc_nonexist RETURNS INTEGER SONAME "$UDF_EXAMPLE_SO"; 25--replace_result $UDF_EXAMPLE_SO UDF_EXAMPLE_LIB 26eval CREATE FUNCTION myfunc_int RETURNS INTEGER SONAME "$UDF_EXAMPLE_SO"; 27--replace_result $UDF_EXAMPLE_SO UDF_EXAMPLE_LIB 28eval CREATE FUNCTION udf_sequence RETURNS INTEGER SONAME "$UDF_EXAMPLE_SO"; 29--replace_result $UDF_EXAMPLE_SO UDF_EXAMPLE_LIB 30eval CREATE FUNCTION lookup RETURNS STRING SONAME "$UDF_EXAMPLE_SO"; 31--replace_result $UDF_EXAMPLE_SO UDF_EXAMPLE_LIB 32eval CREATE FUNCTION reverse_lookup 33 RETURNS STRING SONAME "$UDF_EXAMPLE_SO"; 34--replace_result $UDF_EXAMPLE_SO UDF_EXAMPLE_LIB 35eval CREATE AGGREGATE FUNCTION avgcost 36 RETURNS REAL SONAME "$UDF_EXAMPLE_SO"; 37 38--error ER_CANT_INITIALIZE_UDF 39select myfunc_double(); 40select myfunc_double(1); 41select myfunc_double(78654); 42--error 1305 43select myfunc_nonexist(); 44select myfunc_int(); 45--error ER_CANT_INITIALIZE_UDF 46select lookup(); 47select lookup("127.0.0.1"); 48--error ER_CANT_INITIALIZE_UDF 49select lookup(127,0,0,1); 50select lookup("localhost") rlike '^127\.\\d+\.\\d+.\\d+$'; 51--error ER_CANT_INITIALIZE_UDF 52select reverse_lookup(); 53 54# These two function calls should return "localhost", but it's 55# depending on configuration, so just call them and don't log the result 56--disable_result_log 57select reverse_lookup("127.0.0.1"); 58select reverse_lookup(127,0,0,1); 59 60# This function call may return different results depending on platform, 61# so ignore results (see Bug#52060). 62select reverse_lookup("localhost"); 63--enable_result_log 64 65--error ER_CANT_INITIALIZE_UDF 66select avgcost(); 67--error ER_CANT_INITIALIZE_UDF 68select avgcost(100,23.76); 69create table t1(sum int, price float(24)); 70insert into t1 values(100, 50.00), (100, 100.00); 71select avgcost(sum, price) from t1; 72delete from t1; 73insert into t1 values(100, 54.33), (200, 199.99); 74select avgcost(sum, price) from t1; 75drop table t1; 76 77#------------------------------------------------------------------------ 78# BUG#17261 Passing a variable from a stored procedure to UDF crashes mysqld 79#------------------------------------------------------------------------ 80 81select metaphon('hello'); 82 83delimiter //; 84CREATE PROCEDURE `XXX1`(in testval varchar(10)) 85begin 86select metaphon(testval); 87end// 88delimiter ;// 89 90call XXX1('hello'); 91drop procedure xxx1; 92 93delimiter //; 94CREATE PROCEDURE `XXX2`() 95begin 96declare testval varchar(10); 97set testval = 'hello'; 98select metaphon(testval); 99end// 100delimiter ;// 101 102call XXX2(); 103drop procedure xxx2; 104 105# 106# Bug#19904: UDF: not initialized *is_null per row 107# 108 109CREATE TABLE bug19904(n INT, v varchar(10)); 110INSERT INTO bug19904 VALUES (1,'one'),(2,'two'),(NULL,NULL),(3,'three'),(4,'four'); 111SELECT myfunc_double(n) AS f FROM bug19904; 112SELECT metaphon(v) AS f FROM bug19904; 113DROP TABLE bug19904; 114 115# 116# Bug#21269: DEFINER-clause is allowed for UDF-functions 117# 118 119--error ER_PARSE_ERROR 120CREATE DEFINER=CURRENT_USER() FUNCTION should_not_parse 121RETURNS STRING SONAME "should_not_parse.so"; 122 123--error ER_PARSE_ERROR 124CREATE DEFINER=someone@somewhere FUNCTION should_not_parse 125RETURNS STRING SONAME "should_not_parse.so"; 126# 127# Bug#19862: Sort with filesort by function evaluates function twice 128# 129create table t1(f1 int); 130insert into t1 values(1),(2); 131explain select myfunc_int(f1) from t1 order by 1; 132drop table t1; 133 134# 135# Bug #21809: Error 1356 while selecting from view with grouping though 136# underlying select OK. 137# 138CREATE TABLE t1(a INT, b INT); INSERT INTO t1 values (1,1),(2,2); 139 140DELIMITER ||; 141CREATE FUNCTION fn(a int) RETURNS int DETERMINISTIC 142BEGIN 143 RETURN a; 144END 145|| 146DELIMITER ;|| 147 148CREATE VIEW v1 AS SELECT a, fn(MIN(b)) as c FROM t1 GROUP BY a; 149 150SELECT myfunc_int(a AS attr_name) FROM t1; 151EXPLAIN EXTENDED SELECT myfunc_int(a AS attr_name) FROM t1; 152EXPLAIN EXTENDED SELECT myfunc_int(a) FROM t1; 153SELECT a,c FROM v1; 154 155--error ER_WRONG_PARAMETERS_TO_STORED_FCT 156SELECT a, fn(MIN(b) xx) as c FROM t1 GROUP BY a; 157--error ER_WRONG_PARAMETERS_TO_STORED_FCT 158SELECT myfunc_int(fn(MIN(b) xx)) as c FROM t1 GROUP BY a; 159--error ER_PARSE_ERROR 160SELECT myfunc_int(test.fn(MIN(b) xx)) as c FROM t1 GROUP BY a; 161 162SELECT myfunc_int(fn(MIN(b)) xx) as c FROM t1 GROUP BY a; 163SELECT myfunc_int(test.fn(MIN(b)) xx) as c FROM t1 GROUP BY a; 164 165EXPLAIN EXTENDED SELECT myfunc_int(MIN(b) xx) as c FROM t1 GROUP BY a; 166EXPLAIN EXTENDED SELECT test.fn(MIN(b)) as c FROM t1 GROUP BY a; 167EXPLAIN EXTENDED SELECT myfunc_int(fn(MIN(b))) as c FROM t1 GROUP BY a; 168EXPLAIN EXTENDED SELECT myfunc_int(test.fn(MIN(b))) as c FROM t1 GROUP BY a; 169SELECT myfunc_int(MIN(b) xx) as c FROM t1 GROUP BY a; 170SELECT test.fn(MIN(b)) as c FROM t1 GROUP BY a; 171SELECT myfunc_int(fn(MIN(b))) as c FROM t1 GROUP BY a; 172SELECT myfunc_int(test.fn(MIN(b))) as c FROM t1 GROUP BY a; 173DROP VIEW v1; 174DROP TABLE t1; 175DROP FUNCTION fn; 176 177--echo End of 5.0 tests. 178 179# 180# Bug#24736: UDF functions parsed as Stored Functions 181# 182 183select myfunc_double(3); 184select myfunc_double(3 AS three); 185select myfunc_double(abs(3)); 186select myfunc_double(abs(3) AS named_param); 187select abs(myfunc_double(3)); 188select abs(myfunc_double(3 AS three)); 189 190-- error ER_WRONG_PARAMETERS_TO_NATIVE_FCT 191select myfunc_double(abs(3 AS wrong)); 192-- error ER_WRONG_PARAMETERS_TO_NATIVE_FCT 193select abs(myfunc_double(3) AS wrong); 194 195# 196# BUG#18239: Possible to overload internal functions with stored functions 197# 198 199--disable_warnings 200drop function if exists pi; 201--enable_warnings 202 203--error ER_NATIVE_FCT_NAME_COLLISION 204CREATE FUNCTION pi RETURNS STRING SONAME "should_not_parse.so"; 205 206# Verify that Stored Functions and UDF are mutually exclusive 207DROP FUNCTION IF EXISTS metaphon; 208 209CREATE FUNCTION metaphon(a int) RETURNS int 210return 0; 211 212# this currently passes, and eclipse the stored function 213--replace_result $UDF_EXAMPLE_SO UDF_EXAMPLE_LIB 214eval CREATE FUNCTION metaphon RETURNS STRING SONAME "$UDF_EXAMPLE_SO"; 215 216DROP FUNCTION metaphon; 217DROP FUNCTION metaphon; 218 219--replace_result $UDF_EXAMPLE_SO UDF_EXAMPLE_LIB 220eval CREATE FUNCTION metaphon RETURNS STRING SONAME "$UDF_EXAMPLE_SO"; 221 222--error ER_UDF_EXISTS 223CREATE FUNCTION metaphon(a int) RETURNS int 224return 0; 225 226--error ER_UDF_EXISTS 227CREATE FUNCTION test.metaphon(a int) RETURNS int 228return 0; 229 230# End of Bug#18239 231 232# 233# Drop the example functions from udf_example 234# 235 236DROP FUNCTION metaphon; 237DROP FUNCTION myfunc_double; 238--error ER_SP_DOES_NOT_EXIST 239DROP FUNCTION myfunc_nonexist; 240DROP FUNCTION myfunc_int; 241DROP FUNCTION udf_sequence; 242DROP FUNCTION lookup; 243DROP FUNCTION reverse_lookup; 244DROP FUNCTION avgcost; 245 246# 247# Bug #15439: UDF name case handling forces DELETE FROM mysql.func to remove 248# the UDF 249# 250select * from mysql.func; 251--replace_result $UDF_EXAMPLE_SO UDF_EXAMPLE_LIB 252eval CREATE FUNCTION is_const RETURNS STRING SONAME "$UDF_EXAMPLE_SO"; 253 254select IS_const(3); 255 256drop function IS_const; 257 258select * from mysql.func; 259 260--error 1305 261select is_const(3); 262 263# 264# Bug#18761: constant expression as UDF parameters not passed in as constant 265# 266--replace_result $UDF_EXAMPLE_SO UDF_EXAMPLE_LIB 267eval CREATE FUNCTION is_const RETURNS STRING SONAME "$UDF_EXAMPLE_SO"; 268 269select 270 is_const(3) as const, 271 is_const(3.14) as const, 272 is_const('fnord') as const, 273 is_const(2+3) as const, 274 is_const(rand()) as 'nc rand()', 275 is_const(sin(3.14)) as const, 276 is_const(upper('test')) as const; 277 278create table bug18761 (n int); 279insert into bug18761 values (null),(2); 280select 281 is_const(3) as const, 282 is_const(3.14) as const, 283 is_const('fnord') as const, 284 is_const(2+3) as const, 285 is_const(2+n) as 'nc 2+n ', 286 is_const(sin(n)) as 'nc sin(n)', 287 is_const(sin(3.14)) as const, 288 is_const(upper('test')) as const, 289 is_const(rand()) as 'nc rand()', 290 is_const(n) as 'nc n ', 291 is_const(is_const(n)) as 'nc ic?(n)', 292 is_const(is_const('c')) as const 293from 294 bug18761; 295drop table bug18761; 296 297--error 1241 298select is_const((1,2,3)); 299 300drop function if exists is_const; 301 302# 303# Bug #25382: Passing NULL to an UDF called from stored procedures 304# crashes server 305# 306--replace_result $UDF_EXAMPLE_SO UDF_EXAMPLE_LIB 307eval CREATE FUNCTION metaphon RETURNS STRING SONAME "$UDF_EXAMPLE_SO"; 308 309--replace_result $UDF_EXAMPLE_SO UDF_EXAMPLE_LIB 310eval CREATE FUNCTION myfunc_double RETURNS REAL SONAME "$UDF_EXAMPLE_SO"; 311 312--replace_result $UDF_EXAMPLE_SO UDF_EXAMPLE_LIB 313eval CREATE FUNCTION myfunc_int RETURNS INTEGER SONAME "$UDF_EXAMPLE_SO"; 314 315delimiter //; 316create function f1(p1 varchar(255)) 317returns varchar(255) 318begin 319 return metaphon(p1); 320end// 321 322create function f2(p1 varchar(255)) 323returns double 324begin 325 return myfunc_double(p1); 326end// 327 328create function f3(p1 varchar(255)) 329returns double 330begin 331 return myfunc_int(p1); 332end// 333 334delimiter ;// 335 336select f3(NULL); 337select f2(NULL); 338select f1(NULL); 339 340drop function f1; 341drop function f2; 342drop function f3; 343drop function metaphon; 344drop function myfunc_double; 345drop function myfunc_int; 346 347# 348# Bug#28318 CREATE FUNCTION (UDF) requires a schema 349# 350 351--disable_warnings 352DROP DATABASE IF EXISTS mysqltest; 353--enable_warnings 354CREATE DATABASE mysqltest; 355USE mysqltest; 356DROP DATABASE mysqltest; 357--replace_result $UDF_EXAMPLE_SO UDF_EXAMPLE_LIB 358eval CREATE FUNCTION metaphon RETURNS STRING SONAME "$UDF_EXAMPLE_SO"; 359DROP FUNCTION metaphon; 360USE test; 361 362# 363# Bug #29804 UDF parameters don't contain correct string length 364# 365 366CREATE TABLE const_len_bug ( 367 str_const varchar(4000), 368 result1 varchar(4000), 369 result2 varchar(4000) 370); 371 372DELIMITER |; 373CREATE TRIGGER check_const_len_trigger BEFORE INSERT ON const_len_bug FOR EACH ROW BEGIN 374 set NEW.str_const = 'bar'; 375 set NEW.result2 = check_const_len(NEW.str_const); 376END | 377 378CREATE PROCEDURE check_const_len_sp (IN str_const VARCHAR(4000)) 379BEGIN 380DECLARE result VARCHAR(4000); 381SET result = check_const_len(str_const); 382insert into const_len_bug values(str_const, result, ""); 383END | 384DELIMITER ;| 385 386--replace_result $UDF_EXAMPLE_SO UDF_EXAMPLE_LIB 387eval CREATE FUNCTION check_const_len RETURNS string SONAME "$UDF_EXAMPLE_SO"; 388 389CALL check_const_len_sp("foo"); 390 391SELECT * from const_len_bug; 392 393DROP FUNCTION check_const_len; 394DROP PROCEDURE check_const_len_sp; 395DROP TRIGGER check_const_len_trigger; 396DROP TABLE const_len_bug; 397 398 399# 400# Bug #30355: Incorrect ordering of UDF results 401# 402 403--replace_result $UDF_EXAMPLE_SO UDF_EXAMPLE_LIB 404eval CREATE FUNCTION udf_sequence RETURNS INTEGER SONAME "$UDF_EXAMPLE_SO"; 405CREATE TABLE t1 (a INT); 406CREATE TABLE t2 (a INT PRIMARY KEY); 407INSERT INTO t1 VALUES (4),(3),(2),(1); 408INSERT INTO t2 SELECT * FROM t1; 409 410SELECT udf_sequence() AS seq, a FROM t1 ORDER BY seq ASC; 411SELECT udf_sequence() AS seq, a FROM t1 ORDER BY seq DESC; 412 413SELECT * FROM t1 WHERE a = udf_sequence(); 414SELECT * FROM t2 WHERE a = udf_sequence(); 415 416DROP FUNCTION udf_sequence; 417DROP TABLE t1,t2; 418 419# 420# Bug#31767 (DROP FUNCTION name resolution) 421# 422 423--disable_warnings 424drop function if exists test.metaphon; 425drop function if exists metaphon; 426--enable_warnings 427 428--replace_result $UDF_EXAMPLE_SO UDF_EXAMPLE_LIB 429eval CREATE FUNCTION metaphon RETURNS STRING SONAME "$UDF_EXAMPLE_SO"; 430 431select metaphon("Hello"); 432 433# The UDF should not be dropped 434drop function if exists test.metaphon; 435 436select metaphon("Hello"); 437 438drop function metaphon; 439 440CREATE FUNCTION test.metaphon(a TEXT) RETURNS TEXT return "This is a SF"; 441 442create database db_31767; 443use db_31767; 444 445--replace_result $UDF_EXAMPLE_SO UDF_EXAMPLE_LIB 446eval CREATE FUNCTION metaphon RETURNS STRING SONAME "$UDF_EXAMPLE_SO"; 447 448use test; 449 450# Uses the UDF 451select metaphon("Hello"); 452 453# Uses the SF 454select test.metaphon("Hello"); 455 456# Should drop the UDF, resolving the name the same way select does. 457drop function metaphon; 458 459# Should call the SF 460select metaphon("Hello"); 461 462# Drop the SF 463drop function metaphon; 464 465# Change the current database to none. 466use db_31767; 467drop database db_31767; 468 469drop function if exists no_such_func; 470 471--error ER_SP_DOES_NOT_EXIST 472drop function no_such_func; 473 474drop function if exists test.no_such_func; 475 476--error ER_SP_DOES_NOT_EXIST 477drop function test.no_such_func; 478 479--error ER_NO_DB_ERROR 480drop procedure if exists no_such_proc; 481 482--error ER_NO_DB_ERROR 483drop procedure no_such_proc; 484 485use test; 486 487 488--echo # 489--echo # Bug#46259: 5.0.83 -> 5.1.36, query doesn't work 490--echo # 491CREATE TABLE t1 ( a INT ); 492 493INSERT INTO t1 VALUES (1), (2), (3); 494 495SELECT IF( a = 1, a, a ) AS `b` FROM t1 ORDER BY field( `b` + 1, 1 ); 496SELECT IF( a = 1, a, a ) AS `b` FROM t1 ORDER BY field( `b`, 1 ); 497 498DROP TABLE t1; 499 500--echo End of 5.0 tests. 501 502--echo # 503--echo # Bug#33546: Slowdown on re-evaluation of constant expressions. 504--echo # 505CREATE TABLE t1 (f1 INT); 506INSERT INTO t1 VALUES(1),(50); 507--replace_result $UDF_EXAMPLE_SO UDF_EXAMPLE_LIB 508eval CREATE FUNCTION myfunc_double RETURNS INTEGER SONAME "$UDF_EXAMPLE_SO"; 509EXPLAIN EXTENDED SELECT 1 FROM t1 WHERE f1=1 + myfunc_double(1); 510DROP FUNCTION myfunc_double; 511DROP TABLE t1; 512--echo # 513--echo End of 5.1 tests. 514 515--echo # 516--echo # MDEV-10134 Add full support for DEFAULT 517--echo # 518 519--replace_result $UDF_EXAMPLE_SO UDF_EXAMPLE_LIB 520eval CREATE FUNCTION metaphon RETURNS STRING SONAME "$UDF_EXAMPLE_SO"; 521SELECT METAPHON('Hello'); 522CREATE TABLE t1 (a VARCHAR(10), b VARCHAR(10) DEFAULT METAPHON(a)); 523SHOW CREATE TABLE t1; 524INSERT INTO t1 (a) VALUES ('Hello'); 525SELECT * FROM t1; 526DROP FUNCTION METAPHON; 527# QQ: this should return an error 528#INSERT INTO t1 (a) VALUES ('Hello'); 529#SELECT * FROM t1; 530DROP TABLE t1; 531 532--echo # 533--echo # MDEV-15424: Unreasonal SQL Error (1356) on select from view 534--echo # 535--replace_result $UDF_EXAMPLE_SO UDF_EXAMPLE_LIB 536eval CREATE FUNCTION myfunc_int RETURNS INTEGER SONAME "$UDF_EXAMPLE_SO"; 537create table t1(a int , b int); 538insert into t1 values(100, 54), (200, 199); 539create view v1 as select myfunc_int(max(a) over (order by b) , b) from t1; 540select * from v1; 541drop view v1; 542drop function myfunc_int; 543drop table t1; 544 545--echo # 546--echo # MDEV-23327: Can't uninstall UDF if the implementation library 547--echo # file doesn't exist 548--echo # 549 550# emulate brocken so/ddl udf 551insert into mysql.func values ("unexisting_udf", 0, "soname", "function"); 552 553# check that we have the function "installed" 554select * from mysql.func WHERE name='unexisting_udf'; 555 556# make attempt to drop the function 557DROP FUNCTION unexisting_udf; 558 559# check that we have the plugin uninstalled 560select * from mysql.plugin WHERE name='unexisting_udf'; 561 562--error ER_SP_DOES_NOT_EXIST 563DROP FUNCTION unexisting_udf; 564 565--echo # 566--echo # Bug #31674599: THE UDF_INIT() FUNCTION CAUSE SERVER CRASH 567--echo # 568call mtr.add_suppression('Invalid row in mysql.func table'); 569insert mysql.func () values (); 570source include/restart_mysqld.inc; 571delete from mysql.func where name = ''; 572 573--echo # 574--echo # End of 10.2 tests 575--echo # 576 577--echo # 578--echo # MDEV-15073: Generic UDAF parser code in server for window functions 579--echo # 580 581--replace_result $UDF_EXAMPLE_SO UDF_EXAMPLE_LIB 582eval CREATE AGGREGATE FUNCTION avgcost 583 RETURNS REAL SONAME "$UDF_EXAMPLE_SO"; 584--replace_result $UDF_EXAMPLE_SO UDF_EXAMPLE_LIB 585eval CREATE AGGREGATE FUNCTION avg2 586 RETURNS REAL SONAME "$UDF_EXAMPLE_SO"; 587--replace_result $UDF_EXAMPLE_SO UDF_EXAMPLE_LIB 588eval CREATE FUNCTION myfunc_double RETURNS REAL SONAME "$UDF_EXAMPLE_SO"; 589 590create table t1(pk int primary key, 591 a int, 592 sum int, 593 price float(24)); 594insert into t1 values 595 (1, 1, 100, 50.00), 596 (2, 1, 100, 100.00), 597 (3, 1, 100, 50.00), 598 (4, 1, 100, 50.00), 599 (5, 1, 100, 50.00), 600 (6, 1, 100, NULL), 601 (7, 1, NULL, NULL), 602 (8, 2, 2, 2), 603 (9, 2, 4, 4); 604 605--sorted_result 606select pk, a, sum, price, avgcost(sum, price) over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) 607from t1; 608--sorted_result 609select pk, a, sum, price, avgcost(sum, price) over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 0 FOLLOWING) 610from t1; 611 612--sorted_result 613select pk, a, sum, price, avg2(sum, price) over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) 614from t1; 615--sorted_result 616select pk, a, sum, price, avg2(sum, price) over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 0 FOLLOWING) 617from t1; 618--error ER_PARSE_ERROR 619select pk, a, sum, price, tttttttt(sprice,sum) over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 0 FOLLOWING) 620from t1; 621--error ER_PARSE_ERROR 622select pk, a, sum, price, myfunc_double(sum) over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 0 FOLLOWING) 623from t1; 624--error ER_PARSE_ERROR 625select pk, a, sum, price, round(sprice,sum) over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 0 FOLLOWING) 626from t1; 627--error ER_PARSE_ERROR 628select pk, a, sum, price, myfunc_double(sum) over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 0 FOLLOWING) 629from t1; 630 631set @save_sql_mode = @@sql_mode; 632set sql_mode="oracle"; 633--sorted_result 634select pk, a, sum, price, avg2(sum, price) over (partition by a order by pk ROWS BETWEEN 1 PRECEDING AND 0 FOLLOWING) 635from t1; 636set sql_mode= @save_sql_mode; 637 638drop table t1; 639DROP FUNCTION avgcost; 640DROP FUNCTION avg2; 641DROP FUNCTION myfunc_double; 642 643--echo # End of 10.4 tests 644