Repository: incubator-hawq Updated Branches: refs/heads/master 4de3d107c -> 7ecf59aa9
HAWQ-922. Add basic verification for various pl and udf in HAWQ Project: http://git-wip-us.apache.org/repos/asf/incubator-hawq/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-hawq/commit/7ecf59aa Tree: http://git-wip-us.apache.org/repos/asf/incubator-hawq/tree/7ecf59aa Diff: http://git-wip-us.apache.org/repos/asf/incubator-hawq/diff/7ecf59aa Branch: refs/heads/master Commit: 7ecf59aa95b287949c9ae4a97d81eca55ecde21f Parents: 4de3d10 Author: Ruilong Huo <[email protected]> Authored: Mon Jul 25 15:20:00 2016 +0800 Committer: Ruilong Huo <[email protected]> Committed: Thu Jul 28 11:18:12 2016 +0800 ---------------------------------------------------------------------- src/test/feature/UDF/TestUDF.cpp | 218 ++++++++++++++++++- src/test/feature/UDF/ans/function_c.ans.source | 15 ++ src/test/feature/UDF/ans/function_internal.ans | 16 ++ src/test/feature/UDF/ans/function_pgcrypto.ans | 12 + src/test/feature/UDF/ans/function_pljava.ans | 21 ++ src/test/feature/UDF/ans/function_pljavau.ans | 21 ++ src/test/feature/UDF/ans/function_plperl.ans | 35 +++ src/test/feature/UDF/ans/function_plperlu.ans | 35 +++ src/test/feature/UDF/ans/function_plpgsql.ans | 18 ++ src/test/feature/UDF/ans/function_plpythonu.ans | 18 ++ src/test/feature/UDF/ans/function_plr.ans | 20 ++ src/test/feature/UDF/ans/function_sql.ans | 24 ++ src/test/feature/UDF/lib/function.c | 12 +- src/test/feature/UDF/sql/PLJavaAdd.jar | Bin 0 -> 654 bytes src/test/feature/UDF/sql/PLJavaAdd.java | 7 + src/test/feature/UDF/sql/PLJavauAdd.jar | Bin 0 -> 657 bytes src/test/feature/UDF/sql/PLJavauAdd.java | 7 + src/test/feature/UDF/sql/function_c.sql.source | 6 + src/test/feature/UDF/sql/function_internal.sql | 7 + src/test/feature/UDF/sql/function_pgcrypto.sql | 2 + src/test/feature/UDF/sql/function_pljava.sql | 8 + src/test/feature/UDF/sql/function_pljavau.sql | 8 + src/test/feature/UDF/sql/function_plperl.sql | 22 ++ src/test/feature/UDF/sql/function_plperlu.sql | 22 ++ src/test/feature/UDF/sql/function_plpgsql.sql | 9 + src/test/feature/UDF/sql/function_plpythonu.sql | 9 + src/test/feature/UDF/sql/function_plr.sql | 11 + src/test/feature/UDF/sql/function_sql.sql | 13 ++ src/test/feature/lib/hawq_scp.cpp | 24 ++ src/test/feature/lib/hawq_scp.h | 23 ++ src/test/feature/lib/sql_util.cpp | 33 +++ src/test/feature/lib/sql_util.h | 10 + 32 files changed, 683 insertions(+), 3 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7ecf59aa/src/test/feature/UDF/TestUDF.cpp ---------------------------------------------------------------------- diff --git a/src/test/feature/UDF/TestUDF.cpp b/src/test/feature/UDF/TestUDF.cpp index ce7f158..7107b63 100755 --- a/src/test/feature/UDF/TestUDF.cpp +++ b/src/test/feature/UDF/TestUDF.cpp @@ -1,7 +1,9 @@ #include "gtest/gtest.h" +#include "lib/command.h" #include "lib/sql_util.h" #include "lib/file_replace.h" +#include "lib/hawq_scp.h" class TestUDF: public ::testing::Test @@ -51,8 +53,18 @@ TEST_F(TestUDF, TestUDFCreation) TEST_F(TestUDF, TestUDFSetReturning) { hawq::test::SQLUtility util; - util.execSQLFile("UDF/sql/function_set_returning.sql", - "UDF/ans/function_set_returning.ans"); + // enable plpythonu language if it is absent + if (util.getQueryResult("SELECT lanname FROM pg_language WHERE lanname = 'plpythonu'") != "plpythonu") + { + util.execute("CREATE LANGUAGE plpythonu", false); + } + + // run test if plpythonu language is enabled + if (util.getQueryResult("SELECT lanname FROM pg_language WHERE lanname = 'plpythonu'") == "plpythonu") + { + util.execSQLFile("UDF/sql/function_set_returning.sql", + "UDF/ans/function_set_returning.ans"); + } } TEST_F(TestUDF, TestUDFExtension) @@ -61,3 +73,205 @@ TEST_F(TestUDF, TestUDFExtension) util.execSQLFile("UDF/sql/function_extension.sql", "UDF/ans/function_extension.ans"); } + +TEST_F(TestUDF, TestUDFInternal) +{ + hawq::test::SQLUtility util; + util.execSQLFile("UDF/sql/function_internal.sql", + "UDF/ans/function_internal.ans"); +} + +TEST_F(TestUDF, TestUDFC) +{ + // preprocess source files to get sql/ans files + hawq::test::SQLUtility util; + std::string d_feature_test_root(util.getTestRootPath()); + std::string f_sql_tpl(d_feature_test_root + "/UDF/sql/function_c.sql.source"); + std::string f_ans_tpl(d_feature_test_root + "/UDF/ans/function_c.ans.source"); + std::string f_sql(d_feature_test_root + "/UDF/sql/function_c.sql"); + std::string f_ans(d_feature_test_root + "/UDF/ans/function_c.ans"); + + hawq::test::FileReplace frep; + std::unordered_map<std::string, std::string> strs_src_dst; + strs_src_dst["@SHARE_LIBRARY_PATH@"] = d_feature_test_root + "/UDF/lib/function.so"; + + frep.replace(f_sql_tpl, f_sql, strs_src_dst); + frep.replace(f_ans_tpl, f_ans, strs_src_dst); + + // run sql file to get ans file and then diff it with out file + util.execSQLFile("UDF/sql/function_c.sql", + "UDF/ans/function_c.ans"); +} + +TEST_F(TestUDF, TestUDFSql) +{ + hawq::test::SQLUtility util; + util.execSQLFile("UDF/sql/function_sql.sql", + "UDF/ans/function_sql.ans"); +} + +TEST_F(TestUDF, TestUDFPlpgsql) +{ + hawq::test::SQLUtility util; + // enable plpgsql language if it is absent + if (util.getQueryResult("SELECT lanname FROM pg_language WHERE lanname = 'plpgsql'") != "plpgsql") + { + util.execute("CREATE LANGUAGE plpgsql", false); + } + + // run test if plpgsql language is enabled + if (util.getQueryResult("SELECT lanname FROM pg_language WHERE lanname = 'plpgsql'") == "plpgsql") + { + util.execSQLFile("UDF/sql/function_plpgsql.sql", + "UDF/ans/function_plpgsql.ans"); + } +} + +TEST_F(TestUDF, TestUDFPgcrypto) +{ + hawq::test::SQLUtility util; + // enable pgcrypto package if it is absent + if (util.getQueryResult("SELECT proname FROM pg_proc WHERE proname = 'crypt'") != "crypt") + { + const char *gph = getenv("GPHOME"); + std::string gphome = gph ? gph : ""; + EXPECT_NE(gphome, ""); + + util.execSQLFile(gphome + "/share/postgresql/contrib/pgcrypto.sql"); + } + + // run test if pgcrypto package is enabled + if (util.getQueryResult("SELECT proname FROM pg_proc WHERE proname = 'crypt'") == "crypt") + { + util.execSQLFile("UDF/sql/function_pgcrypto.sql", + "UDF/ans/function_pgcrypto.ans"); + } +} + +TEST_F(TestUDF, TestUDFPlr) +{ + hawq::test::SQLUtility util; + // enable plr language if it is absent + if (util.getQueryResult("SELECT lanname FROM pg_language WHERE lanname = 'plr'") != "plr") + { + util.execute("CREATE LANGUAGE plr", false); + } + + // run test if plr language is enabled + if (util.getQueryResult("SELECT lanname FROM pg_language WHERE lanname = 'plr'") == "plr") + { + util.execSQLFile("UDF/sql/function_plr.sql", + "UDF/ans/function_plr.ans"); + } +} + +TEST_F(TestUDF, TestUDFPljava) +{ + hawq::test::SQLUtility util; + std::string d_feature_test_root(util.getTestRootPath()); + + const char *gph = getenv("GPHOME"); + std::string gphome = gph ? gph : ""; + EXPECT_NE(gphome, ""); + + // enable pljava language if it is absent + if (util.getQueryResult("SELECT lanname FROM pg_language WHERE lanname = 'java'") != "java") + { + hawq::test::Command cmd("psql -f " + gphome + "/share/postgresql/pljava/install.sql"); + cmd.run(); + } + + // run test if pljava language is enabled + if (util.getQueryResult("SELECT lanname FROM pg_language WHERE lanname = 'java'") == "java") + { + // copy jar files over hawq cluster + std::string query = "SELECT string_agg('-h ' || hostname, ' ' ORDER BY hostname) FROM gp_segment_configuration;"; + std::string hosts = util.getQueryResult(query); + hawq::test::HAWQScp hscp; + EXPECT_EQ(hscp.copy(hosts, d_feature_test_root + "/UDF/sql/PLJavaAdd.jar", gphome + "/lib/postgresql/java/"), true); + + util.execSQLFile("UDF/sql/function_pljava.sql", + "UDF/ans/function_pljava.ans"); + } +} + +TEST_F(TestUDF, TestUDFPljavau) +{ + hawq::test::SQLUtility util; + std::string d_feature_test_root(util.getTestRootPath()); + + const char *gph = getenv("GPHOME"); + std::string gphome = gph ? gph : ""; + EXPECT_NE(gphome, ""); + + // enable pljavau language if it is absent + if (util.getQueryResult("SELECT lanname FROM pg_language WHERE lanname = 'javau'") != "javau") + { + hawq::test::Command cmd("psql -f " + gphome + "/share/postgresql/pljava/install.sql"); + cmd.run(); + } + + // run test if pljavau language is enabled + if (util.getQueryResult("SELECT lanname FROM pg_language WHERE lanname = 'javau'") == "javau") + { + // copy jar files over hawq cluster + std::string query = "SELECT string_agg('-h ' || hostname, ' ' ORDER BY hostname) FROM gp_segment_configuration;"; + std::string hosts = util.getQueryResult(query); + hawq::test::HAWQScp hscp; + EXPECT_EQ(hscp.copy(hosts, d_feature_test_root + "/UDF/sql/PLJavauAdd.jar", gphome + "/lib/postgresql/java/"), true); + + util.execSQLFile("UDF/sql/function_pljavau.sql", + "UDF/ans/function_pljavau.ans"); + } +} + +TEST_F(TestUDF, TestUDFPlpythonu) +{ + hawq::test::SQLUtility util; + // enable plpythonu language if it is absent + if (util.getQueryResult("SELECT lanname FROM pg_language WHERE lanname = 'plpythonu'") != "plpythonu") + { + util.execute("CREATE LANGUAGE plpythonu", false); + } + + // run test if plpythonu language is enabled + if (util.getQueryResult("SELECT lanname FROM pg_language WHERE lanname = 'plpythonu'") == "plpythonu") + { + util.execSQLFile("UDF/sql/function_plpythonu.sql", + "UDF/ans/function_plpythonu.ans"); + } +} + +TEST_F(TestUDF, TestUDFPlperl) +{ + hawq::test::SQLUtility util; + // enable plperl language if it is absent + if (util.getQueryResult("SELECT lanname FROM pg_language WHERE lanname = 'plperl'") != "plperl") + { + util.execute("CREATE LANGUAGE plperl", false); + } + + // run test if plperl language is enabled + if (util.getQueryResult("SELECT lanname FROM pg_language WHERE lanname = 'plperl'") == "plperl") + { + util.execSQLFile("UDF/sql/function_plperl.sql", + "UDF/ans/function_plperl.ans"); + } +} + +TEST_F(TestUDF, TestUDFPlperlu) +{ + hawq::test::SQLUtility util; + // enable plperlu language if it is absent + if (util.getQueryResult("SELECT lanname FROM pg_language WHERE lanname = 'plperlu'") != "plperlu") + { + util.execute("CREATE LANGUAGE plperlu", false); + } + + // run test if plperlu language is enabled + if (util.getQueryResult("SELECT lanname FROM pg_language WHERE lanname = 'plperlu'") == "plperlu") + { + util.execSQLFile("UDF/sql/function_plperlu.sql", + "UDF/ans/function_plperlu.ans"); + } +} http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7ecf59aa/src/test/feature/UDF/ans/function_c.ans.source ---------------------------------------------------------------------- diff --git a/src/test/feature/UDF/ans/function_c.ans.source b/src/test/feature/UDF/ans/function_c.ans.source new file mode 100644 index 0000000..c99f33c --- /dev/null +++ b/src/test/feature/UDF/ans/function_c.ans.source @@ -0,0 +1,15 @@ +-- start_ignore +SET SEARCH_PATH=TestUDF_TestUDFC; +SET +-- end_ignore +CREATE OR REPLACE FUNCTION c_add(x INT, y INT) +RETURNS INT +AS '@SHARE_LIBRARY_PATH@', 'c_add' +LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION +SELECT c_add(20, 30); + c_add +------- + 50 +(1 row) + http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7ecf59aa/src/test/feature/UDF/ans/function_internal.ans ---------------------------------------------------------------------- diff --git a/src/test/feature/UDF/ans/function_internal.ans b/src/test/feature/UDF/ans/function_internal.ans new file mode 100644 index 0000000..4740703 --- /dev/null +++ b/src/test/feature/UDF/ans/function_internal.ans @@ -0,0 +1,16 @@ +-- start_ignore +SET SEARCH_PATH=TestUDF_TestUDFInternal; +SET +-- end_ignore +CREATE OR REPLACE FUNCTION internal_sqrt(DOUBLE PRECISION) +RETURNS DOUBLE PRECISION +AS 'dsqrt' +LANGUAGE internal +STRICT; +CREATE FUNCTION +SELECT internal_sqrt(25.0); + internal_sqrt +--------------- + 5 +(1 row) + http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7ecf59aa/src/test/feature/UDF/ans/function_pgcrypto.ans ---------------------------------------------------------------------- diff --git a/src/test/feature/UDF/ans/function_pgcrypto.ans b/src/test/feature/UDF/ans/function_pgcrypto.ans new file mode 100644 index 0000000..f5eba2d --- /dev/null +++ b/src/test/feature/UDF/ans/function_pgcrypto.ans @@ -0,0 +1,12 @@ +-- start_ignore +SET SEARCH_PATH=TestUDF_TestUDFPgcrypto; +SET +-- end_ignore +SET search_path = public; +SET +SELECT crypt('abc', '123'); + crypt +--------------- + 12BWKETBcM70Q +(1 row) + http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7ecf59aa/src/test/feature/UDF/ans/function_pljava.ans ---------------------------------------------------------------------- diff --git a/src/test/feature/UDF/ans/function_pljava.ans b/src/test/feature/UDF/ans/function_pljava.ans new file mode 100644 index 0000000..e3f54d0 --- /dev/null +++ b/src/test/feature/UDF/ans/function_pljava.ans @@ -0,0 +1,21 @@ +-- start_ignore +SET SEARCH_PATH=TestUDF_TestUDFPljava; +SET +-- end_ignore +SELECT set_config('pljava_classpath', 'PLJavaAdd.jar', false); + set_config +--------------- + PLJavaAdd.jar +(1 row) + +CREATE OR REPLACE FUNCTION pljava_add(x INT, y INT) +RETURNS INT +AS 'PLJavaAdd.add' +LANGUAGE java; +CREATE FUNCTION +SELECT pljava_add(10, 20); + pljava_add +------------ + 30 +(1 row) + http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7ecf59aa/src/test/feature/UDF/ans/function_pljavau.ans ---------------------------------------------------------------------- diff --git a/src/test/feature/UDF/ans/function_pljavau.ans b/src/test/feature/UDF/ans/function_pljavau.ans new file mode 100644 index 0000000..7e1f556 --- /dev/null +++ b/src/test/feature/UDF/ans/function_pljavau.ans @@ -0,0 +1,21 @@ +-- start_ignore +SET SEARCH_PATH=TestUDF_TestUDFPljavau; +SET +-- end_ignore +SELECT set_config('pljava_classpath', 'PLJavauAdd.jar', false); + set_config +---------------- + PLJavauAdd.jar +(1 row) + +CREATE OR REPLACE FUNCTION pljavau_add(x INT, y INT) +RETURNS INT +AS 'PLJavauAdd.add' +LANGUAGE javau; +CREATE FUNCTION +SELECT pljavau_add(10, 20); + pljavau_add +------------- + 30 +(1 row) + http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7ecf59aa/src/test/feature/UDF/ans/function_plperl.ans ---------------------------------------------------------------------- diff --git a/src/test/feature/UDF/ans/function_plperl.ans b/src/test/feature/UDF/ans/function_plperl.ans new file mode 100644 index 0000000..d39a9d1 --- /dev/null +++ b/src/test/feature/UDF/ans/function_plperl.ans @@ -0,0 +1,35 @@ +-- start_ignore +SET SEARCH_PATH=TestUDF_TestUDFPlperl; +SET +-- end_ignore +CREATE OR REPLACE FUNCTION plperl_max (INTEGER, INTEGER) +RETURNS INTEGER +AS $$ + my ($x, $y) = @_; + if (not defined $x) { + return undef if not defined $y; + return $y; + } + return $x if not defined $y; + return $x if $x > $y; + return $y; +$$ LANGUAGE plperl; +CREATE FUNCTION +SELECT plperl_max(1, 10); + plperl_max +------------ + 10 +(1 row) + +CREATE OR REPLACE FUNCTION plperl_returns_array() +RETURNS TEXT[][] +AS $$ + return [['a"b','c,d'],['e\\f','g']]; +$$ LANGUAGE plperl; +CREATE FUNCTION +SELECT plperl_returns_array(); + plperl_returns_array +----------------------------- + {{"a\"b","c,d"},{"e\\f",g}} +(1 row) + http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7ecf59aa/src/test/feature/UDF/ans/function_plperlu.ans ---------------------------------------------------------------------- diff --git a/src/test/feature/UDF/ans/function_plperlu.ans b/src/test/feature/UDF/ans/function_plperlu.ans new file mode 100644 index 0000000..5319f95 --- /dev/null +++ b/src/test/feature/UDF/ans/function_plperlu.ans @@ -0,0 +1,35 @@ +-- start_ignore +SET SEARCH_PATH=TestUDF_TestUDFPlperlu; +SET +-- end_ignore +CREATE OR REPLACE FUNCTION plperlu_max (INTEGER, INTEGER) +RETURNS INTEGER +AS $$ + my ($x, $y) = @_; + if (not defined $x) { + return undef if not defined $y; + return $y; + } + return $x if not defined $y; + return $x if $x > $y; + return $y; +$$ LANGUAGE plperlu; +CREATE FUNCTION +SELECT plperlu_max(1, 10); + plperlu_max +------------- + 10 +(1 row) + +CREATE OR REPLACE FUNCTION plperlu_returns_array() +RETURNS TEXT[][] +AS $$ + return [['a"b','c,d'],['e\\f','g']]; +$$ LANGUAGE plperlu; +CREATE FUNCTION +SELECT plperlu_returns_array(); + plperlu_returns_array +----------------------------- + {{"a\"b","c,d"},{"e\\f",g}} +(1 row) + http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7ecf59aa/src/test/feature/UDF/ans/function_plpgsql.ans ---------------------------------------------------------------------- diff --git a/src/test/feature/UDF/ans/function_plpgsql.ans b/src/test/feature/UDF/ans/function_plpgsql.ans new file mode 100644 index 0000000..23396b6 --- /dev/null +++ b/src/test/feature/UDF/ans/function_plpgsql.ans @@ -0,0 +1,18 @@ +-- start_ignore +SET SEARCH_PATH=TestUDF_TestUDFPlpgsql; +SET +-- end_ignore +CREATE OR REPLACE FUNCTION plpgsql_increment(i INTEGER) +RETURNS INTEGER +AS $$ + BEGIN + RETURN i + 1; + END; +$$ LANGUAGE plpgsql; +CREATE FUNCTION +SELECT plpgsql_increment(6); + plpgsql_increment +------------------- + 7 +(1 row) + http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7ecf59aa/src/test/feature/UDF/ans/function_plpythonu.ans ---------------------------------------------------------------------- diff --git a/src/test/feature/UDF/ans/function_plpythonu.ans b/src/test/feature/UDF/ans/function_plpythonu.ans new file mode 100644 index 0000000..f1e9846 --- /dev/null +++ b/src/test/feature/UDF/ans/function_plpythonu.ans @@ -0,0 +1,18 @@ +-- start_ignore +SET SEARCH_PATH=TestUDF_TestUDFPlpythonu; +SET +-- end_ignore +CREATE OR REPLACE FUNCTION plpythonu_max (a INTEGER, b INTEGER) +RETURNS INTEGER +AS $$ + if a > b: + return a + return b +$$ LANGUAGE plpythonu; +CREATE FUNCTION +SELECT plpythonu_max(1, 10); + plpythonu_max +--------------- + 10 +(1 row) + http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7ecf59aa/src/test/feature/UDF/ans/function_plr.ans ---------------------------------------------------------------------- diff --git a/src/test/feature/UDF/ans/function_plr.ans b/src/test/feature/UDF/ans/function_plr.ans new file mode 100644 index 0000000..424bd39 --- /dev/null +++ b/src/test/feature/UDF/ans/function_plr.ans @@ -0,0 +1,20 @@ +-- start_ignore +SET SEARCH_PATH=TestUDF_TestUDFPlr; +SET +-- end_ignore +CREATE OR REPLACE FUNCTION r_max (INTEGER, INTEGER) +RETURNS INTEGER +AS $$ + if (arg1 > arg2) + return(arg1) + else + return(arg2) +$$ +LANGUAGE plr STRICT; +CREATE FUNCTION +SELECT r_max(1, 10); + r_max +------- + 10 +(1 row) + http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7ecf59aa/src/test/feature/UDF/ans/function_sql.ans ---------------------------------------------------------------------- diff --git a/src/test/feature/UDF/ans/function_sql.ans b/src/test/feature/UDF/ans/function_sql.ans new file mode 100644 index 0000000..c521db0 --- /dev/null +++ b/src/test/feature/UDF/ans/function_sql.ans @@ -0,0 +1,24 @@ +-- start_ignore +SET SEARCH_PATH=TestUDF_TestUDFSql; +SET +-- end_ignore +CREATE OR REPLACE FUNCTION sql_add(INTEGER, INTEGER) +RETURNS INTEGER +AS $$ + SELECT $1 + $2; +$$ LANGUAGE SQL; +CREATE FUNCTION +SELECT sql_add(1, 2); + sql_add +--------- + 3 +(1 row) + +CREATE OR REPLACE FUNCTION sql_add_invalid(x INTEGER, y INTEGER) +RETURNS INTEGER +AS $$ + SELECT x + y; +$$ LANGUAGE SQL; +psql:/tmp/TestUDF_TestUDFSql.sql:16: ERROR: column "x" does not exist +LINE 4: SELECT x + y; + ^ http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7ecf59aa/src/test/feature/UDF/lib/function.c ---------------------------------------------------------------------- diff --git a/src/test/feature/UDF/lib/function.c b/src/test/feature/UDF/lib/function.c index f346855..d9a842b 100755 --- a/src/test/feature/UDF/lib/function.c +++ b/src/test/feature/UDF/lib/function.c @@ -36,7 +36,7 @@ extern Datum autoinc(PG_FUNCTION_ARGS); extern Datum funny_dup17(PG_FUNCTION_ARGS); extern Datum ttdummy(PG_FUNCTION_ARGS); extern Datum set_ttdummy(PG_FUNCTION_ARGS); - +extern Datum c_add(PG_FUNCTION_ARGS); #ifdef PG_MODULE_MAGIC PG_MODULE_MAGIC; @@ -1243,3 +1243,13 @@ Datum set_ttdummy(PG_FUNCTION_ARGS) PG_RETURN_INT32(1); } + +PG_FUNCTION_INFO_V1(c_add); +Datum c_add(PG_FUNCTION_ARGS) +{ + int32 x = PG_GETARG_INT32(0); + int32 y = PG_GETARG_INT32(1); + + PG_RETURN_INT32(x+y); +} + http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7ecf59aa/src/test/feature/UDF/sql/PLJavaAdd.jar ---------------------------------------------------------------------- diff --git a/src/test/feature/UDF/sql/PLJavaAdd.jar b/src/test/feature/UDF/sql/PLJavaAdd.jar new file mode 100644 index 0000000..1041373 Binary files /dev/null and b/src/test/feature/UDF/sql/PLJavaAdd.jar differ http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7ecf59aa/src/test/feature/UDF/sql/PLJavaAdd.java ---------------------------------------------------------------------- diff --git a/src/test/feature/UDF/sql/PLJavaAdd.java b/src/test/feature/UDF/sql/PLJavaAdd.java new file mode 100644 index 0000000..2267821 --- /dev/null +++ b/src/test/feature/UDF/sql/PLJavaAdd.java @@ -0,0 +1,7 @@ +public class PLJavaAdd +{ + static int add(int x, int y) + { + return (x+y); + } +} http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7ecf59aa/src/test/feature/UDF/sql/PLJavauAdd.jar ---------------------------------------------------------------------- diff --git a/src/test/feature/UDF/sql/PLJavauAdd.jar b/src/test/feature/UDF/sql/PLJavauAdd.jar new file mode 100644 index 0000000..fafff6b Binary files /dev/null and b/src/test/feature/UDF/sql/PLJavauAdd.jar differ http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7ecf59aa/src/test/feature/UDF/sql/PLJavauAdd.java ---------------------------------------------------------------------- diff --git a/src/test/feature/UDF/sql/PLJavauAdd.java b/src/test/feature/UDF/sql/PLJavauAdd.java new file mode 100644 index 0000000..eceffe8 --- /dev/null +++ b/src/test/feature/UDF/sql/PLJavauAdd.java @@ -0,0 +1,7 @@ +public class PLJavauAdd +{ + static int add(int x, int y) + { + return (x+y); + } +} http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7ecf59aa/src/test/feature/UDF/sql/function_c.sql.source ---------------------------------------------------------------------- diff --git a/src/test/feature/UDF/sql/function_c.sql.source b/src/test/feature/UDF/sql/function_c.sql.source new file mode 100644 index 0000000..f9c6433 --- /dev/null +++ b/src/test/feature/UDF/sql/function_c.sql.source @@ -0,0 +1,6 @@ +CREATE OR REPLACE FUNCTION c_add(x INT, y INT) +RETURNS INT +AS '@SHARE_LIBRARY_PATH@', 'c_add' +LANGUAGE C IMMUTABLE STRICT; + +SELECT c_add(20, 30); http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7ecf59aa/src/test/feature/UDF/sql/function_internal.sql ---------------------------------------------------------------------- diff --git a/src/test/feature/UDF/sql/function_internal.sql b/src/test/feature/UDF/sql/function_internal.sql new file mode 100644 index 0000000..b0299be --- /dev/null +++ b/src/test/feature/UDF/sql/function_internal.sql @@ -0,0 +1,7 @@ +CREATE OR REPLACE FUNCTION internal_sqrt(DOUBLE PRECISION) +RETURNS DOUBLE PRECISION +AS 'dsqrt' +LANGUAGE internal +STRICT; + +SELECT internal_sqrt(25.0); http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7ecf59aa/src/test/feature/UDF/sql/function_pgcrypto.sql ---------------------------------------------------------------------- diff --git a/src/test/feature/UDF/sql/function_pgcrypto.sql b/src/test/feature/UDF/sql/function_pgcrypto.sql new file mode 100644 index 0000000..4cdf188 --- /dev/null +++ b/src/test/feature/UDF/sql/function_pgcrypto.sql @@ -0,0 +1,2 @@ +SET search_path = public; +SELECT crypt('abc', '123'); http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7ecf59aa/src/test/feature/UDF/sql/function_pljava.sql ---------------------------------------------------------------------- diff --git a/src/test/feature/UDF/sql/function_pljava.sql b/src/test/feature/UDF/sql/function_pljava.sql new file mode 100644 index 0000000..5730228 --- /dev/null +++ b/src/test/feature/UDF/sql/function_pljava.sql @@ -0,0 +1,8 @@ +SELECT set_config('pljava_classpath', 'PLJavaAdd.jar', false); + +CREATE OR REPLACE FUNCTION pljava_add(x INT, y INT) +RETURNS INT +AS 'PLJavaAdd.add' +LANGUAGE java; + +SELECT pljava_add(10, 20); http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7ecf59aa/src/test/feature/UDF/sql/function_pljavau.sql ---------------------------------------------------------------------- diff --git a/src/test/feature/UDF/sql/function_pljavau.sql b/src/test/feature/UDF/sql/function_pljavau.sql new file mode 100644 index 0000000..0e594c4 --- /dev/null +++ b/src/test/feature/UDF/sql/function_pljavau.sql @@ -0,0 +1,8 @@ +SELECT set_config('pljava_classpath', 'PLJavauAdd.jar', false); + +CREATE OR REPLACE FUNCTION pljavau_add(x INT, y INT) +RETURNS INT +AS 'PLJavauAdd.add' +LANGUAGE javau; + +SELECT pljavau_add(10, 20); http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7ecf59aa/src/test/feature/UDF/sql/function_plperl.sql ---------------------------------------------------------------------- diff --git a/src/test/feature/UDF/sql/function_plperl.sql b/src/test/feature/UDF/sql/function_plperl.sql new file mode 100644 index 0000000..35c8ba3 --- /dev/null +++ b/src/test/feature/UDF/sql/function_plperl.sql @@ -0,0 +1,22 @@ +CREATE OR REPLACE FUNCTION plperl_max (INTEGER, INTEGER) +RETURNS INTEGER +AS $$ + my ($x, $y) = @_; + if (not defined $x) { + return undef if not defined $y; + return $y; + } + return $x if not defined $y; + return $x if $x > $y; + return $y; +$$ LANGUAGE plperl; + +SELECT plperl_max(1, 10); + +CREATE OR REPLACE FUNCTION plperl_returns_array() +RETURNS TEXT[][] +AS $$ + return [['a"b','c,d'],['e\\f','g']]; +$$ LANGUAGE plperl; + +SELECT plperl_returns_array(); http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7ecf59aa/src/test/feature/UDF/sql/function_plperlu.sql ---------------------------------------------------------------------- diff --git a/src/test/feature/UDF/sql/function_plperlu.sql b/src/test/feature/UDF/sql/function_plperlu.sql new file mode 100644 index 0000000..a710843 --- /dev/null +++ b/src/test/feature/UDF/sql/function_plperlu.sql @@ -0,0 +1,22 @@ +CREATE OR REPLACE FUNCTION plperlu_max (INTEGER, INTEGER) +RETURNS INTEGER +AS $$ + my ($x, $y) = @_; + if (not defined $x) { + return undef if not defined $y; + return $y; + } + return $x if not defined $y; + return $x if $x > $y; + return $y; +$$ LANGUAGE plperlu; + +SELECT plperlu_max(1, 10); + +CREATE OR REPLACE FUNCTION plperlu_returns_array() +RETURNS TEXT[][] +AS $$ + return [['a"b','c,d'],['e\\f','g']]; +$$ LANGUAGE plperlu; + +SELECT plperlu_returns_array(); http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7ecf59aa/src/test/feature/UDF/sql/function_plpgsql.sql ---------------------------------------------------------------------- diff --git a/src/test/feature/UDF/sql/function_plpgsql.sql b/src/test/feature/UDF/sql/function_plpgsql.sql new file mode 100644 index 0000000..80f8d75 --- /dev/null +++ b/src/test/feature/UDF/sql/function_plpgsql.sql @@ -0,0 +1,9 @@ +CREATE OR REPLACE FUNCTION plpgsql_increment(i INTEGER) +RETURNS INTEGER +AS $$ + BEGIN + RETURN i + 1; + END; +$$ LANGUAGE plpgsql; + +SELECT plpgsql_increment(6); http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7ecf59aa/src/test/feature/UDF/sql/function_plpythonu.sql ---------------------------------------------------------------------- diff --git a/src/test/feature/UDF/sql/function_plpythonu.sql b/src/test/feature/UDF/sql/function_plpythonu.sql new file mode 100644 index 0000000..8c883ab --- /dev/null +++ b/src/test/feature/UDF/sql/function_plpythonu.sql @@ -0,0 +1,9 @@ +CREATE OR REPLACE FUNCTION plpythonu_max (a INTEGER, b INTEGER) +RETURNS INTEGER +AS $$ + if a > b: + return a + return b +$$ LANGUAGE plpythonu; + +SELECT plpythonu_max(1, 10); http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7ecf59aa/src/test/feature/UDF/sql/function_plr.sql ---------------------------------------------------------------------- diff --git a/src/test/feature/UDF/sql/function_plr.sql b/src/test/feature/UDF/sql/function_plr.sql new file mode 100644 index 0000000..cb6bbce --- /dev/null +++ b/src/test/feature/UDF/sql/function_plr.sql @@ -0,0 +1,11 @@ +CREATE OR REPLACE FUNCTION r_max (INTEGER, INTEGER) +RETURNS INTEGER +AS $$ + if (arg1 > arg2) + return(arg1) + else + return(arg2) +$$ +LANGUAGE plr STRICT; + +SELECT r_max(1, 10); http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7ecf59aa/src/test/feature/UDF/sql/function_sql.sql ---------------------------------------------------------------------- diff --git a/src/test/feature/UDF/sql/function_sql.sql b/src/test/feature/UDF/sql/function_sql.sql new file mode 100644 index 0000000..f2c885f --- /dev/null +++ b/src/test/feature/UDF/sql/function_sql.sql @@ -0,0 +1,13 @@ +CREATE OR REPLACE FUNCTION sql_add(INTEGER, INTEGER) +RETURNS INTEGER +AS $$ + SELECT $1 + $2; +$$ LANGUAGE SQL; + +SELECT sql_add(1, 2); + +CREATE OR REPLACE FUNCTION sql_add_invalid(x INTEGER, y INTEGER) +RETURNS INTEGER +AS $$ + SELECT x + y; +$$ LANGUAGE SQL; http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7ecf59aa/src/test/feature/lib/hawq_scp.cpp ---------------------------------------------------------------------- diff --git a/src/test/feature/lib/hawq_scp.cpp b/src/test/feature/lib/hawq_scp.cpp new file mode 100644 index 0000000..8af4c60 --- /dev/null +++ b/src/test/feature/lib/hawq_scp.cpp @@ -0,0 +1,24 @@ +#include "command.h" +#include "sql_util.h" +#include "hawq_scp.h" + +using std::string; + +namespace hawq { +namespace test { + +bool HAWQScp::copy(const string& host_list, const string& src_file, const string& dst_dir) +{ + Command cmd("hawq scp " + host_list + " " + src_file + " =:" + dst_dir); + if (cmd.run().getResultStatus() == 0) + { + return true; + } + else + { + return false; + } +} + +} // namespace test +} // namespace hawq http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7ecf59aa/src/test/feature/lib/hawq_scp.h ---------------------------------------------------------------------- diff --git a/src/test/feature/lib/hawq_scp.h b/src/test/feature/lib/hawq_scp.h new file mode 100644 index 0000000..5f3eed5 --- /dev/null +++ b/src/test/feature/lib/hawq_scp.h @@ -0,0 +1,23 @@ +#ifndef SRC_TEST_FEATURE_LIB_HAWQ_SCP_H_ +#define SRC_TEST_FEATURE_LIB_HAWQ_SCP_H_ + +#include <string> + +namespace hawq { +namespace test { + +class HAWQScp +{ +public: + HAWQScp() = default; + ~HAWQScp() = default; + HAWQScp(const HAWQScp&) = delete; + HAWQScp& operator=(const HAWQScp&) = delete; + + bool copy(const std::string& host_list, const std::string& src_file, const std::string& dst_dir); +}; + +} // namespace test +} // namespace hawq + +#endif // SRC_TEST_FEATURE_LIB_HAWQ_SCP_H_ http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7ecf59aa/src/test/feature/lib/sql_util.cpp ---------------------------------------------------------------------- diff --git a/src/test/feature/lib/sql_util.cpp b/src/test/feature/lib/sql_util.cpp index c11e519..36f33a7 100644 --- a/src/test/feature/lib/sql_util.cpp +++ b/src/test/feature/lib/sql_util.cpp @@ -158,6 +158,27 @@ void SQLUtility::execSQLFile(const string &sqlFile, } } +bool SQLUtility::execSQLFile(const string &sqlFile) { + // do precheck for sqlFile + if (hawq::test::startsWith(sqlFile, "/")) + return false; + + // double check to avoid empty fileBaseName + FilePath fp = splitFilePath(sqlFile); + if (fp.fileBaseName.empty()) + return false; + + // outFile is located in the same folder with ansFile + string outFileAbsPath = "/tmp/" + fp.fileBaseName + ".out"; + + // generate new sql file with set search_path added at the begining + const string newSqlFile = generateSQLFile(sqlFile); + + // run sql file and store its result in output file + conn->setOutputFile(outFileAbsPath); + return conn->runSQLFile(newSqlFile).getLastStatus() == 0 ? true : false; +} + const string SQLUtility::generateSQLFile(const string &sqlFile) { const string originSqlFile = testRootPath + "/" + sqlFile; const string newSqlFile = "/tmp/" + string(test_info->test_case_name()) + "_" + test_info->name() + ".sql"; @@ -230,6 +251,18 @@ std::string SQLUtility::getGUCValue(const std::string &guc) { return row[0]; } +std::string SQLUtility::getQueryResult(const std::string &query) { + const hawq::test::PSQLQueryResult &result = executeQuery(query); + EXPECT_LE(result.rowCount(), 1); + std::string value; + if (result.rowCount() == 1) + { + value = result.getRows()[0][0]; + } + + return value; +} + FilePath SQLUtility::splitFilePath(const string &filePath) const { FilePath fp; size_t found1 = filePath.find_last_of("/"); http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/7ecf59aa/src/test/feature/lib/sql_util.h ---------------------------------------------------------------------- diff --git a/src/test/feature/lib/sql_util.h b/src/test/feature/lib/sql_util.h index 6e8439a..8f8a6df 100644 --- a/src/test/feature/lib/sql_util.h +++ b/src/test/feature/lib/sql_util.h @@ -64,6 +64,11 @@ class SQLUtility { // @return void void execSQLFile(const std::string &sqlFile, const std::string &ansFile, const std::string &initFile = ""); + // Execute sql file and check its return status + // @param sqlFile The given sqlFile which is relative path to test root dir + // @return true if the sql file is executed successfully, false otherwise + bool execSQLFile(const std::string &sqlFile); + // Get PSQL connection: do not suggest to use // @return PSQL raw pointer const hawq::test::PSQL *getPSQL() const; @@ -77,6 +82,11 @@ class SQLUtility { // Get GUC value std::string getGUCValue(const std::string &guc); + // execute given query and return query result + // @param query the given query + // @return the query result + std::string getQueryResult(const std::string &query); + // execute expect error message // @param sql the given sql command // @param errmsg the expected sql error message
