You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hawq.apache.org by hu...@apache.org on 2016/07/28 03:18:44 UTC
incubator-hawq git commit: HAWQ-922. Add basic verification for
various pl and udf in HAWQ
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 <rh...@pivotal.io>
Authored: Mon Jul 25 15:20:00 2016 +0800
Committer: Ruilong Huo <rh...@pivotal.io>
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