You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hawq.apache.org by fo...@apache.org on 2015/11/12 21:25:20 UTC
[3/9] incubator-hawq git commit: HAWQ-149. Add orafce, gp_cancel_query,
pgbench and extprotocol to HAWQ
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/e74af545/contrib/orafce/plvstr.c
----------------------------------------------------------------------
diff --git a/contrib/orafce/plvstr.c b/contrib/orafce/plvstr.c
new file mode 100644
index 0000000..8e8b97e
--- /dev/null
+++ b/contrib/orafce/plvstr.c
@@ -0,0 +1,1347 @@
+/*
+ This code implements one part of functonality of
+ free available library PL/Vision. Please look www.quest.com
+
+ Original author: Steven Feuerstein, 1996 - 2002
+ PostgreSQL implementation author: Pavel Stehule, 2006
+
+ This module is under BSD Licence
+
+ History:
+ 1.0. first public version 13. March 2006
+*/
+
+
+#include "postgres.h"
+#include "utils/builtins.h"
+#include "utils/numeric.h"
+#include "string.h"
+#include "stdlib.h"
+#include "utils/pg_locale.h"
+#include "mb/pg_wchar.h"
+#include "nodes/execnodes.h"
+
+#include "catalog/pg_type.h"
+#include "libpq/pqformat.h"
+#include "orafunc.h"
+#include "builtins.h"
+
+PG_FUNCTION_INFO_V1(plvstr_rvrs);
+PG_FUNCTION_INFO_V1(plvstr_normalize);
+PG_FUNCTION_INFO_V1(plvstr_is_prefix);
+PG_FUNCTION_INFO_V1(plvstr_is_prefix_text);
+PG_FUNCTION_INFO_V1(plvstr_is_prefix_int);
+PG_FUNCTION_INFO_V1(plvstr_is_prefix_int64);
+PG_FUNCTION_INFO_V1(plvstr_lpart);
+PG_FUNCTION_INFO_V1(plvstr_rpart);
+PG_FUNCTION_INFO_V1(plvstr_lstrip);
+PG_FUNCTION_INFO_V1(plvstr_rstrip);
+PG_FUNCTION_INFO_V1(plvstr_left);
+PG_FUNCTION_INFO_V1(plvstr_right);
+PG_FUNCTION_INFO_V1(plvstr_substr2);
+PG_FUNCTION_INFO_V1(plvstr_substr3);
+PG_FUNCTION_INFO_V1(plvstr_instr2);
+PG_FUNCTION_INFO_V1(plvstr_instr3);
+PG_FUNCTION_INFO_V1(plvstr_instr4);
+PG_FUNCTION_INFO_V1(plvstr_betwn_i);
+PG_FUNCTION_INFO_V1(plvstr_betwn_c);
+PG_FUNCTION_INFO_V1(plvstr_swap);
+
+PG_FUNCTION_INFO_V1(plvchr_nth);
+PG_FUNCTION_INFO_V1(plvchr_first);
+PG_FUNCTION_INFO_V1(plvchr_last);
+PG_FUNCTION_INFO_V1(plvchr_is_kind_i);
+PG_FUNCTION_INFO_V1(plvchr_is_kind_a);
+PG_FUNCTION_INFO_V1(plvchr_char_name);
+
+PG_FUNCTION_INFO_V1(oracle_substr2);
+PG_FUNCTION_INFO_V1(oracle_substr3);
+
+static text *ora_substr(Datum str, int start, int len);
+
+#define ora_substr_text(str, start, len) \
+ ora_substr(PointerGetDatum((str)), (start), (len))
+
+static const char* char_names[] = {
+ "NULL","SOH","STX","ETX","EOT","ENQ","ACK","DEL",
+ "BS", "HT", "NL", "VT", "NP", "CR", "SO", "SI",
+ "DLE", "DC1","DC2","DC3","DC4","NAK","SYN","ETB",
+ "CAN", "EM","SUB","ESC","FS","GS","RS","US","SP"
+};
+
+#define NON_EMPTY_CHECK(str) \
+if (VARSIZE_ANY_EXHDR(str) == 0) \
+ ereport(ERROR, \
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE), \
+ errmsg("invalid parameter"), \
+ errdetail("Empty string is not allowed.")));
+
+#define PARAMETER_ERROR(detail) \
+ ereport(ERROR, \
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE), \
+ errmsg("invalid parameter"), \
+ errdetail(detail)));
+
+
+#ifndef _pg_mblen
+#define _pg_mblen pg_mblen
+#endif
+
+typedef enum
+{
+ POSITION,
+ FIRST,
+ LAST
+} position_mode;
+
+
+#if PG_VERSION_NUM < 80400
+text *
+cstring_to_text_with_len(const char *c, int n)
+{
+ text *result;
+ result = palloc(n + VARHDRSZ);
+ SET_VARSIZE(result, n + VARHDRSZ);
+ memcpy(VARDATA(result), c, n);
+
+ return result;
+}
+#endif
+
+/*
+ * Make substring, can handle negative start
+ *
+ */
+
+
+int
+ora_mb_strlen(text *str, char **sizes, int **positions)
+{
+ int r_len;
+ int cur_size = 0;
+ int sz;
+ char *p;
+ int cur = 0;
+
+ p = VARDATA_ANY(str);
+ r_len = VARSIZE_ANY_EXHDR(str);
+
+ if (NULL != sizes)
+ *sizes = palloc(r_len * sizeof(char));
+ if (NULL != positions)
+ *positions = palloc(r_len * sizeof(int));
+
+ while (cur < r_len)
+ {
+ sz = _pg_mblen(p);
+ if (sizes)
+ (*sizes)[cur_size] = sz;
+ if (positions)
+ (*positions)[cur_size] = cur;
+ cur += sz;
+ p += sz;
+ cur_size += 1;
+ }
+
+ return cur_size;
+}
+
+
+int
+ora_mb_strlen1(text *str)
+{
+ int r_len;
+ int c;
+ char *p;
+
+ r_len = VARSIZE_ANY_EXHDR(str);
+
+ if (pg_database_encoding_max_length() == 1)
+ return r_len;
+
+ p = VARDATA_ANY(str);
+ c = 0;
+ while (r_len > 0)
+ {
+ int sz;
+
+ sz = _pg_mblen(p);
+ p += sz;
+ r_len -= sz;
+ c += 1;
+ }
+
+ return c;
+}
+
+/*
+ * len < 0 means "length is not specified".
+ */
+static text *
+ora_substr(Datum str, int start, int len)
+{
+ if (start == 0)
+ start = 1; /* 0 is interpreted as 1 */
+ else if (start < 0)
+ {
+ text *t;
+ int32 n;
+
+ t = DatumGetTextPP(str);
+ n = pg_mbstrlen_with_len(VARDATA_ANY(t), VARSIZE_ANY_EXHDR(t));
+ start = n + start + 1;
+ if (start <= 0)
+ return cstring_to_text("");
+ str = PointerGetDatum(t); /* save detoasted text */
+ }
+
+ if (len < 0)
+ return DatumGetTextP(DirectFunctionCall2(text_substr_no_len,
+ str, Int32GetDatum(start)));
+ else
+ return DatumGetTextP(DirectFunctionCall3(text_substr,
+ str, Int32GetDatum(start), Int32GetDatum(len)));
+}
+
+/*
+ * Simply search algorithm. Could be greatly improved if we
+ * used KMP. Morris-Boyer would be more efficient but it might
+ * give us head aches in the presence of multibyte. For example, see
+ * `CHINESE STRING SEARCHING USING THE KMP ALGORITHM' by R. Luk.
+ */
+static int
+ora_instr_mb(text *txt, text *pattern, int start, int nth)
+{
+ int c_len_txt, c_len_pat;
+ int b_len_pat;
+ int *pos_txt;
+ const char *str_txt, *str_pat;
+ int beg, end, i, dx;
+
+ str_txt = VARDATA_ANY(txt);
+ c_len_txt = ora_mb_strlen(txt, NULL, &pos_txt);
+ str_pat = VARDATA_ANY(pattern);
+ b_len_pat = VARSIZE_ANY_EXHDR(pattern);
+ c_len_pat = pg_mbstrlen_with_len(str_pat, b_len_pat);
+
+ if (start > 0)
+ {
+ dx = 1;
+ beg = start - 1;
+ end = c_len_txt - c_len_pat + 1;
+ if (beg >= end)
+ return 0; /* out of range */
+ }
+ else
+ {
+ dx = -1;
+ beg = Min(c_len_txt + start, c_len_txt - c_len_pat);
+ end = -1;
+ if (beg <= end)
+ return 0; /* out of range */
+ }
+
+ for (i = beg; i != end; i += dx)
+ {
+ if (memcmp(str_txt + pos_txt[i], str_pat, b_len_pat) == 0)
+ {
+ if (--nth == 0)
+ return i + 1;
+ }
+ }
+
+ return 0;
+}
+
+
+int
+ora_instr(text *txt, text *pattern, int start, int nth)
+{
+ int len_txt, len_pat;
+ const char *str_txt, *str_pat;
+ int beg, end, i, dx;
+
+ if (nth <= 0)
+ PARAMETER_ERROR("Fourth parameter must be a positive integer.");
+
+ /* Forward for multibyte strings */
+ if (pg_database_encoding_max_length() > 1)
+ return ora_instr_mb(txt, pattern, start, nth);
+
+ str_txt = VARDATA_ANY(txt);
+ len_txt = VARSIZE_ANY_EXHDR(txt);
+ str_pat = VARDATA_ANY(pattern);
+ len_pat = VARSIZE_ANY_EXHDR(pattern);
+
+ if (start > 0)
+ {
+ dx = 1;
+ beg = start - 1;
+ end = len_txt - len_pat + 1;
+ if (beg >= end)
+ return 0; /* out of range */
+ }
+ else
+ {
+ dx = -1;
+ beg = Min(len_txt + start, len_txt - len_pat);
+ end = -1;
+ if (beg <= end)
+ return 0; /* out of range */
+ }
+
+ for (i = beg; i != end; i += dx)
+ {
+ if (memcmp(str_txt + i, str_pat, len_pat) == 0)
+ {
+ if (--nth == 0)
+ return i + 1;
+ }
+ }
+
+ return 0;
+}
+
+
+/****************************************************************
+ * PLVstr.normalize
+ *
+ * Syntax:
+ * FUNCTION plvstr.normalize (string_in IN VARCHAR)
+ * RETURN VARCHAR;
+ *
+ * Purpose:
+ * Normalize string - replace white chars by space, replace
+ * spaces by space
+ *
+ ****************************************************************/
+
+Datum
+plvstr_normalize(PG_FUNCTION_ARGS)
+{
+ text *str = PG_GETARG_TEXT_PP(0);
+ text *result;
+ char *aux, *aux_cur;
+ int i, l;
+ char c, *cur;
+ bool write_spc = false;
+ bool ignore_stsp = true;
+ bool mb_encode;
+ int sz;
+
+ mb_encode = pg_database_encoding_max_length() > 1;
+
+ l = VARSIZE_ANY_EXHDR(str);
+ aux_cur = aux = palloc(l);
+
+ write_spc = false;
+ cur = VARDATA_ANY(str);
+
+ for (i = 0; i < l; i++)
+ {
+ switch ((c = *cur))
+ {
+ case '\t':
+ case '\n':
+ case '\r':
+ case ' ':
+ write_spc = ignore_stsp ? false : true;
+ break;
+ default:
+ /* ignore all other unvisible chars */
+
+ if (mb_encode)
+ {
+ sz = _pg_mblen(cur);
+ if (sz > 1 || (sz == 1 && c > 32))
+ {
+ int j;
+
+ if (write_spc)
+ {
+ *aux_cur++ = ' ';
+ write_spc = false;
+
+ }
+ for (j = 0; j < sz; j++)
+ {
+ *aux_cur++ = *cur++;
+ }
+ ignore_stsp = false;
+ i += sz - 1;
+ }
+ continue;
+
+ }
+ else
+ if (c > 32)
+ {
+ if (write_spc)
+ {
+ *aux_cur++ = ' ';
+ write_spc = false;
+ }
+ *aux_cur++ = c;
+ ignore_stsp = false;
+ continue;
+ }
+
+ }
+ cur += 1;
+ }
+
+ l = aux_cur - aux;
+ result = palloc(l+VARHDRSZ);
+ SET_VARSIZE(result, l + VARHDRSZ);
+ memcpy(VARDATA(result), aux, l);
+
+ PG_RETURN_TEXT_P(result);
+}
+
+
+/****************************************************************
+ * PLVstr.instr
+ *
+ * Syntax:
+ * FUNCTION plvstr.instr (string_in VARCHAR, pattern VARCHAR)
+ * FUNCTION plvstr.instr (string_in VARCHAR, pattern VARCHAR,
+ * start_in INTEGER)
+ * FUNCTION plvstr.instr (string_in VARCHAR, pattern VARCHAR,
+ * start_in INTEGER, nth INTEGER)
+ * RETURN INT;
+ *
+ * Purpose:
+ * Search pattern in string.
+ *
+ ****************************************************************/
+
+Datum
+plvstr_instr2 (PG_FUNCTION_ARGS)
+{
+ text *arg1 = PG_GETARG_TEXT_PP(0);
+ text *arg2 = PG_GETARG_TEXT_PP(1);
+
+ PG_RETURN_INT32(ora_instr(arg1, arg2, 1, 1));
+}
+
+Datum
+plvstr_instr3 (PG_FUNCTION_ARGS)
+{
+ text *arg1 = PG_GETARG_TEXT_PP(0);
+ text *arg2 = PG_GETARG_TEXT_PP(1);
+ int arg3 = PG_GETARG_INT32(2);
+
+ PG_RETURN_INT32(ora_instr(arg1, arg2, arg3, 1));
+}
+
+Datum
+plvstr_instr4 (PG_FUNCTION_ARGS)
+{
+ text *arg1 = PG_GETARG_TEXT_PP(0);
+ text *arg2 = PG_GETARG_TEXT_PP(1);
+ int arg3 = PG_GETARG_INT32(2);
+ int arg4 = PG_GETARG_INT32(3);
+
+ PG_RETURN_INT32(ora_instr(arg1, arg2, arg3, arg4));
+}
+
+
+/****************************************************************
+ * PLVstr.is_prefix
+ *
+ * Syntax:
+ * FUNCTION plvstr.is_prefix (string_in IN VARCHAR,
+ * prefix_in VARCHAR,
+ * case_sensitive BOOL := true)
+ * RETURN bool;
+ * FUNCTION plvstr.is_prefix (num_in IN NUMERIC,
+ * prefix_in NUMERIC) RETURN bool;
+ * FUNCTION plvstr.is_prefix (int_in IN INT,
+ * prefix_in INT) RETURN bool;
+ *
+ * Purpose:
+ * Returns true, if prefix_in is prefix of string_in
+ *
+ ****************************************************************/
+
+
+Datum
+plvstr_is_prefix_text (PG_FUNCTION_ARGS)
+{
+ text *str = PG_GETARG_TEXT_PP(0);
+ text *prefix = PG_GETARG_TEXT_PP(1);
+ bool case_sens = PG_GETARG_BOOL(2);
+ bool mb_encode;
+
+ int str_len = VARSIZE_ANY_EXHDR(str);
+ int pref_len = VARSIZE_ANY_EXHDR(prefix);
+
+ int i;
+ char *ap, *bp;
+
+
+ mb_encode = pg_database_encoding_max_length() > 1;
+
+ if (mb_encode && !case_sens)
+ {
+ str = (text*)DatumGetPointer(DirectFunctionCall1(lower, PointerGetDatum(str)));
+ prefix = (text*)DatumGetPointer(DirectFunctionCall1(lower, PointerGetDatum(prefix)));
+ }
+
+ ap = VARDATA_ANY(str);
+ bp = VARDATA_ANY(prefix);
+
+ for (i = 0; i < pref_len; i++)
+ {
+ if (i >= str_len)
+ break;
+ if (case_sens || mb_encode)
+ {
+ if (*ap++ != *bp++)
+ break;
+ }
+ else if (!mb_encode)
+ {
+ if (pg_toupper((unsigned char) *ap++) != pg_toupper((unsigned char) *bp++))
+ break;
+ }
+ }
+
+ PG_RETURN_BOOL(i == pref_len);
+}
+
+Datum
+plvstr_is_prefix_int (PG_FUNCTION_ARGS)
+{
+ int n = PG_GETARG_INT32(0);
+ int prefix = PG_GETARG_INT32(1);
+ bool result = false;
+
+ do
+ {
+ if (n == prefix)
+ {
+ result = true;
+ break;
+ }
+ n = n / 10;
+
+ } while (n >= prefix);
+
+ PG_RETURN_BOOL(result);
+}
+
+Datum
+plvstr_is_prefix_int64 (PG_FUNCTION_ARGS)
+{
+ int64 n = PG_GETARG_INT64(0);
+ int64 prefix = PG_GETARG_INT64(1);
+ bool result = false;
+
+ do
+ {
+ if (n == prefix)
+ {
+ result = true;
+ break;
+ }
+ n = n / 10;
+
+ } while (n >= prefix);
+
+ PG_RETURN_BOOL(result);
+}
+
+
+/****************************************************************
+ * PLVstr.rvrs
+ *
+ * Syntax:
+ * FUNCTION plvstr.rvrs (string_in IN VARCHAR,
+ * start_in IN INTEGER := 1,
+ * end_in IN INTEGER := NULL)
+ * RETURN VARCHAR2;
+ *
+ * Purpose:
+ * Reverse string or part of string
+ *
+ ****************************************************************/
+
+Datum
+plvstr_rvrs(PG_FUNCTION_ARGS)
+{
+ text *str = PG_GETARG_TEXT_PP(0);
+ int start = PG_GETARG_INT32(1);
+ int end = PG_GETARG_INT32(2);
+ int len, aux;
+ int i;
+ int new_len;
+ text *result;
+ char *data;
+ char *sizes = NULL;
+ int *positions = NULL;
+ bool mb_encode;
+
+ if (PG_ARGISNULL(0))
+ PG_RETURN_NULL();
+
+ mb_encode = pg_database_encoding_max_length() > 1;
+
+ if (!mb_encode)
+ len = VARSIZE_ANY_EXHDR(str);
+ else
+ len = ora_mb_strlen(str, &sizes, &positions);
+
+
+
+ start = PG_ARGISNULL(1) ? 1 : start;
+ end = PG_ARGISNULL(2) ? (start < 0 ? -len : len) : end;
+
+ if ((start > end && start > 0) || (start < end && start < 0))
+ PARAMETER_ERROR("Third parameter must be greater than second.");
+
+ if (start < 0)
+ {
+ aux = len + end + 1;
+ end = len + start + 1;
+ start = end;
+ }
+
+ new_len = end - start + 1;
+
+ if (mb_encode)
+ {
+ int max_size;
+ int cur_size;
+ char *p;
+ int j;
+ int fz_size;
+
+ fz_size = VARSIZE_ANY_EXHDR(str);
+
+ if ((max_size = (new_len*pg_database_encoding_max_length())) > fz_size)
+ result = palloc(fz_size + VARHDRSZ);
+ else
+ result = palloc(max_size + VARHDRSZ);
+ data = (char*) VARDATA(result);
+
+ cur_size = 0;
+ p = VARDATA_ANY(str);
+ for (i = end - 1; i>= start - 1; i--)
+ {
+ for (j=0; j<sizes[i]; j++)
+ *data++ = *(p+positions[i]+j);
+ cur_size += sizes[i];
+ }
+ SET_VARSIZE(result, cur_size + VARHDRSZ);
+
+ }
+ else
+ {
+ char *p = VARDATA_ANY(str);
+ result = palloc(new_len + VARHDRSZ);
+ data = (char*) VARDATA(result);
+ SET_VARSIZE(result, new_len + VARHDRSZ);
+
+ for (i = end - 1; i >= start - 1; i--)
+ *data++ = p[i];
+ }
+
+ PG_RETURN_TEXT_P(result);
+}
+
+
+/****************************************************************
+ * PLVstr.lpart
+ *
+ * Syntax:
+ * FUNCTION PLVstr.lpart (string_in IN VARCHAR,
+ * divider_in IN VARCHAR,
+ * start_in IN INTEGER := 1,
+ * nth_in IN INTEGER := 1,
+ * all_if_notfound_in IN BOOLEAN := FALSE)
+ * RETURN VARCHAR2;
+ *
+ * Purpose:
+ * Call this function to return the left part of a string.
+ *
+ ****************************************************************/
+
+Datum
+plvstr_lpart (PG_FUNCTION_ARGS)
+{
+ text *str = PG_GETARG_TEXT_P(0);
+ text *div = PG_GETARG_TEXT_P(1);
+ int start = PG_GETARG_INT32(2);
+ int nth = PG_GETARG_INT32(3);
+ bool all_if_notfound = PG_GETARG_BOOL(4);
+ int loc;
+
+ loc = ora_instr(str, div, start, nth);
+ if (loc == 0)
+ {
+ if (all_if_notfound)
+ PG_RETURN_TEXT_P(TextPCopy(str));
+ else
+ PG_RETURN_NULL();
+ }
+ else
+ PG_RETURN_TEXT_P(ora_substr_text(str, 1, loc-1));
+}
+
+
+/****************************************************************
+ * PLVstr.rpart
+ *
+ * Syntax:
+ * FUNCTION PLVstr.rpart (string_in IN VARCHAR,
+ * divider_in IN VARCHAR,
+ * start_in IN INTEGER := 1,
+ * nth_in IN INTEGER := 1,
+ * all_if_notfound_in IN BOOLEAN := FALSE)
+ * RETURN VARCHAR2;
+ *
+ * Purpose:
+ * Call this function to return the right part of a string.
+ *
+ ****************************************************************/
+
+Datum
+plvstr_rpart (PG_FUNCTION_ARGS)
+{
+ text *str = PG_GETARG_TEXT_P(0);
+ text *div = PG_GETARG_TEXT_P(1);
+ int start = PG_GETARG_INT32(2);
+ int nth = PG_GETARG_INT32(3);
+ bool all_if_notfound = PG_GETARG_BOOL(4);
+ int loc;
+
+ loc = ora_instr(str, div, start, nth);
+ if (loc == 0)
+ {
+ if (all_if_notfound)
+ PG_RETURN_TEXT_P(TextPCopy(str));
+ else
+ PG_RETURN_NULL();
+ }
+ else
+ PG_RETURN_TEXT_P(ora_substr_text(str, loc+1, -1));
+}
+
+
+/****************************************************************
+ * PLVstr.lstrip
+ *
+ * Syntax:
+ * FUNCTION plvstr.lstrip (string_in IN VARCHAR,
+ * substring_in IN VARCHAR,
+ * num_in IN INTEGER := 1)
+ * RETURN VARCHAR;
+ *
+ * Purpose:
+ * Call this function to remove characters from the beginning
+ * (left) of a string.
+ *
+ ****************************************************************/
+
+Datum
+plvstr_lstrip (PG_FUNCTION_ARGS)
+{
+ text *str = PG_GETARG_TEXT_PP(0);
+ text *pat = PG_GETARG_TEXT_PP(1);
+ int num = PG_GETARG_INT32(2);
+ int count = 0;
+ int len_p, len_s, i;
+
+ char *str_p, *aux_str_p, *pat_p;
+ len_p = VARSIZE_ANY_EXHDR(pat);
+ len_s = VARSIZE_ANY_EXHDR(str);
+
+ str_p = VARDATA_ANY(str);
+ while (count < num)
+ {
+ pat_p = VARDATA_ANY(pat);
+ aux_str_p = str_p;
+
+ if (len_s < len_p)
+ break;
+
+ for (i = 0; i < len_p; i++)
+ if (*aux_str_p++ != *pat_p++)
+ break;
+
+ if (i >= len_p)
+ {
+ count++;
+ /* found */
+ str_p = aux_str_p;
+ len_s -= len_p;
+ continue;
+ }
+ break;
+ }
+
+ PG_RETURN_TEXT_P(cstring_to_text_with_len(str_p,len_s));
+}
+
+
+/****************************************************************
+ * PLVstr.rstrip
+ *
+ * Syntax:
+ * FUNCTION plvstr.rstrip (string_in IN VARCHAR,
+ * substring_in IN VARCHAR,
+ * num_in IN INTEGER := 1)
+ * RETURN VARCHAR;
+ *
+ * Purpose:
+ * Call this function to remove characters from the end
+ * (right) of a string.
+ *
+ ****************************************************************/
+
+Datum
+plvstr_rstrip (PG_FUNCTION_ARGS)
+{
+ text *str = PG_GETARG_TEXT_PP(0);
+ text *pat = PG_GETARG_TEXT_PP(1);
+ int num = PG_GETARG_INT32(2);
+ int count = 0;
+ int len_p, len_s, i;
+
+ char *str_p, *aux_str_p, *pat_p;
+ len_p = VARSIZE_ANY_EXHDR(pat);
+ len_s = VARSIZE_ANY_EXHDR(str);
+
+ str_p = VARDATA_ANY(str) + len_s - 1;
+
+ while (count < num)
+ {
+ pat_p = VARDATA_ANY(pat) + len_p - 1;
+ aux_str_p = str_p;
+
+ if (len_s < len_p)
+ break;
+
+ for (i = 0; i < len_p; i++)
+ if (*aux_str_p-- != *pat_p--)
+ break;
+
+ if (i >= len_p)
+ {
+ count++;
+ /* found */
+ str_p = aux_str_p;
+ len_s -= len_p;
+ continue;
+ }
+ break;
+ }
+
+ PG_RETURN_TEXT_P(cstring_to_text_with_len(VARDATA_ANY(str),len_s));
+}
+
+
+/****************************************************************
+ * PLVstr.left
+ *
+ * Syntax:
+ * FUNCTION plvstr.left (string_in IN VARCHAR,
+ * num_in INTEGER)
+ * RETURN VARCHAR;
+ *
+ * Purpose:
+ * Returns firs num_in charaters. You can use negative num_in
+ * left('abcde', -2) -> abc
+ *
+ ****************************************************************/
+
+
+Datum
+plvstr_left (PG_FUNCTION_ARGS)
+{
+ text *str = PG_GETARG_TEXT_P(0);
+ int n = PG_GETARG_INT32(1);
+ if (n < 0)
+ n = ora_mb_strlen1(str) + n;
+ n = n < 0 ? 0 : n;
+
+ PG_RETURN_TEXT_P(ora_substr_text(str, 1, n));
+}
+
+
+/****************************************************************
+ * PLVstr.right
+ *
+ * Syntax:
+ * FUNCTION plvstr.right (string_in IN VARCHAR,
+ * num_in INTEGER)
+ * RETURN VARCHAR;
+ *
+ * Purpose:
+ * Returns last (right) num_in characters.
+ *
+ ****************************************************************/
+
+Datum
+plvstr_right (PG_FUNCTION_ARGS)
+{
+ text *str = PG_GETARG_TEXT_P(0);
+ int n = PG_GETARG_INT32(1);
+ if (n < 0)
+ n = ora_mb_strlen1(str) + n;
+ n = (n < 0) ? 0 : n;
+
+ PG_RETURN_TEXT_P(ora_substr_text(str, -n, -1));
+}
+
+/****************************************************************
+ * PLVstr.substr2
+ *
+ * Syntax:
+ * FUNCTION plvstr.substr (string_in IN VARCHAR,
+ * start INTEGER)
+ * RETURN VARCHAR;
+ *
+ * Purpose:
+ * Returns substring started on start_in to end
+ *
+ ****************************************************************/
+
+Datum
+plvstr_substr2 (PG_FUNCTION_ARGS)
+{
+ return oracle_substr2(fcinfo);
+}
+
+
+/****************************************************************
+ * PLVstr.substr3
+ *
+ * Syntax:
+ * FUNCTION plvstr.substr (string_in IN VARCHAR,
+ * start INTEGER, len INTEGER)
+ * RETURN VARCHAR;
+ *
+ * Purpose:
+ * Returns len chars from start_in position
+ *
+ ****************************************************************/
+
+Datum
+plvstr_substr3 (PG_FUNCTION_ARGS)
+{
+ return oracle_substr3(fcinfo);
+}
+
+
+/****************************************************************
+ * PLVchr.nth
+ *
+ * Syntax:
+ * FUNCTION plvchr.nth (string_in IN VARCHAR,
+ * nth_in IN INTEGER)
+ * RETURN VARCHAR;
+ *
+ * Purpose:
+ * Call this function to return the Nth character in a string.
+ *
+ ****************************************************************/
+
+Datum
+plvchr_nth (PG_FUNCTION_ARGS)
+{
+ PG_RETURN_TEXT_P(ora_substr(PG_GETARG_DATUM(0), PG_GETARG_INT32(1), 1));
+}
+
+
+/****************************************************************
+ * PLVchr.first
+ *
+ * Syntax:
+ * FUNCTION plvchr.first (string_in IN VARCHAR,
+ * RETURN VARCHAR;
+ *
+ * Purpose:
+ * Call this function to return the first character in a string.
+ *
+ ****************************************************************/
+
+Datum
+plvchr_first (PG_FUNCTION_ARGS)
+{
+ PG_RETURN_TEXT_P(ora_substr(PG_GETARG_DATUM(0), 1, 1));
+}
+
+
+/****************************************************************
+ * PLVchr.last
+ *
+ * Syntax:
+ * FUNCTION plvchr.last (string_in IN VARCHAR,
+ * RETURN VARCHAR;
+ *
+ * Purpose:
+ * Call this function to return the last character in a string.
+ *
+ ****************************************************************/
+
+Datum
+plvchr_last (PG_FUNCTION_ARGS)
+{
+ PG_RETURN_TEXT_P(ora_substr(PG_GETARG_DATUM(0), -1, 1));
+}
+
+
+/****************************************************************
+ * PLVchr.is_blank, plvchr.is_digit, ...
+ *
+ * Syntax:
+ * FUNCTION plvchr.is_kind (string_in IN VARCHAR,
+ * kind INT)
+ * RETURN VARCHAR;
+ *
+ * Purpose:
+ * Call this function to see if a character is blank, ...
+ * 1 blank, 2 digit, 3 quote, 4 other, 5 letter
+ *
+ ****************************************************************/
+
+static bool
+is_kind(char c, int kind)
+{
+ switch (kind)
+ {
+ case 1:
+ return c ==' ';
+ case 2:
+ return !!(isdigit((unsigned char)c));
+ case 3:
+ return c == '\'';
+ case 4:
+ return
+ (32 <= c && c <= 47) ||
+ (58 <= c && c <= 64) ||
+ (91 <= c && c <= 96) || (123 <= c && c <= 126);
+ case 5:
+ return !!(isalpha((unsigned char)c));
+ default:
+ PARAMETER_ERROR("Second parameter isn't in enum {1,2,3,4,5}");
+ return false;
+ }
+}
+
+Datum
+plvchr_is_kind_i (PG_FUNCTION_ARGS)
+{
+ int32 c = PG_GETARG_INT32(0);
+ int32 k = PG_GETARG_INT32(1);
+
+ PG_RETURN_INT32(is_kind((char)c,k));
+}
+
+Datum
+plvchr_is_kind_a (PG_FUNCTION_ARGS)
+{
+ text *str = PG_GETARG_TEXT_PP(0);
+ int32 k = PG_GETARG_INT32(1);
+ char c;
+
+ NON_EMPTY_CHECK(str);
+ if (pg_database_encoding_max_length() > 1)
+ {
+ if (_pg_mblen(VARDATA_ANY(str)) > 1)
+ PG_RETURN_INT32( (k == 5) );
+ }
+
+ c = *VARDATA_ANY(str);
+ PG_RETURN_INT32(is_kind(c,k));
+}
+
+
+/****************************************************************
+ * PLVchr.char_name
+ *
+ * Syntax:
+ * FUNCTION plvchr.char_name (letter_in IN VARCHAR)
+ * RETURN VARCHAR;
+ *
+ * Purpose:
+ * Returns the name of the character to ascii code as a VARCHAR.
+ *
+ ****************************************************************/
+
+Datum
+plvchr_char_name(PG_FUNCTION_ARGS)
+{
+ text *str = PG_GETARG_TEXT_PP(0);
+ text *result;
+ unsigned char c;
+
+ NON_EMPTY_CHECK(str);
+ c = (unsigned char)*(VARDATA_ANY(str));
+
+ if (c >= lengthof(char_names))
+ result = ora_substr_text(str, 1, 1);
+ else
+ result = cstring_to_text(char_names[c]);
+
+ PG_RETURN_TEXT_P(result);
+}
+
+
+/****************************************************************
+ * substr
+ *
+ * Syntax:
+ * FUNCTION substr (string, start_position, [length])
+ * RETURN VARCHAR;
+ *
+ * Purpose:
+ * Returns len chars from start_in position, compatible with Oracle
+ *
+ ****************************************************************/
+
+Datum
+oracle_substr3(PG_FUNCTION_ARGS)
+{
+ int32 len = PG_GETARG_INT32(2);
+ if (len < 0)
+ PG_RETURN_NULL();
+ PG_RETURN_TEXT_P(ora_substr(PG_GETARG_DATUM(0), PG_GETARG_INT32(1), len));
+}
+
+Datum
+oracle_substr2(PG_FUNCTION_ARGS)
+{
+ PG_RETURN_TEXT_P(ora_substr(PG_GETARG_DATUM(0), PG_GETARG_INT32(1), -1));
+}
+
+
+static text*
+ora_concat2(text *str1, text *str2)
+{
+ int l1;
+ int l2;
+ text *result;
+
+ l1 = VARSIZE_ANY_EXHDR(str1);
+ l2 = VARSIZE_ANY_EXHDR(str2);
+
+ result = palloc(l1+l2+VARHDRSZ);
+ memcpy(VARDATA(result), VARDATA_ANY(str1), l1);
+ memcpy(VARDATA(result) + l1, VARDATA_ANY(str2), l2);
+ SET_VARSIZE(result, l1 + l2 + VARHDRSZ);
+
+ return result;
+}
+
+
+static text*
+ora_concat3(text *str1, text *str2, text *str3)
+{
+ int l1;
+ int l2;
+ int l3;
+ text *result;
+
+ l1 = VARSIZE_ANY_EXHDR(str1);
+ l2 = VARSIZE_ANY_EXHDR(str2);
+ l3 = VARSIZE_ANY_EXHDR(str3);
+
+ result = palloc(l1+l2+l3+VARHDRSZ);
+ memcpy(VARDATA(result), VARDATA_ANY(str1), l1);
+ memcpy(VARDATA(result) + l1, VARDATA_ANY(str2), l2);
+ memcpy(VARDATA(result) + l1+l2, VARDATA_ANY(str3), l3);
+ SET_VARSIZE(result, l1 + l2 + l3 + VARHDRSZ);
+
+ return result;
+}
+
+
+/****************************************************************
+ * PLVchr.swap
+ *
+ * Syntax:
+ * FUNCTION swap
+ * (string_in IN VARCHAR2,
+ * replace_in IN VARCHAR2,
+ * start_in IN INTEGER := 1,
+ * oldlen_in IN INTEGER := NULL)
+ * RETURN VARCHAR2
+ *
+ * Purpose:
+ * Replace a substring in a string with a specified string.
+ *
+ ****************************************************************/
+
+Datum
+plvstr_swap(PG_FUNCTION_ARGS)
+{
+ text *string_in;
+ text *replace_in;
+ int start_in = 1;
+ int oldlen_in;
+ int v_len;
+
+ if (PG_ARGISNULL(0))
+ PG_RETURN_NULL();
+ else
+ string_in = PG_GETARG_TEXT_P(0);
+
+ if (PG_ARGISNULL(1))
+ PG_RETURN_NULL();
+ else
+ replace_in = PG_GETARG_TEXT_P(1);
+
+ if (!PG_ARGISNULL(2))
+ start_in = PG_GETARG_INT32(2);
+
+ if (PG_ARGISNULL(3))
+ oldlen_in = ora_mb_strlen1(replace_in);
+ else
+ oldlen_in = PG_GETARG_INT32(3);
+
+ v_len = ora_mb_strlen1(string_in);
+
+ start_in = start_in > 0 ? start_in : v_len + start_in + 1;
+
+ if (start_in == 0 || start_in > v_len)
+ PG_RETURN_TEXT_P(TextPCopy(string_in));
+ else if (start_in == 1)
+ PG_RETURN_TEXT_P(ora_concat2(
+ replace_in, ora_substr_text(string_in, oldlen_in+1, -1)));
+ else
+ PG_RETURN_TEXT_P(ora_concat3(
+ ora_substr_text(string_in, 1, start_in - 1),
+ replace_in,
+ ora_substr_text(string_in, start_in + oldlen_in, -1)));
+}
+
+/****************************************************************
+ * PLVchr.betwn
+ *
+ * Find the Substring Between Start and End Locations
+ *
+ * Syntax:
+ * FUNCTION plvstr.betwn (string_in IN VARCHAR2,
+ * start_in IN INTEGER,
+ * end_in IN INTEGER,
+ * inclusive IN BOOLEAN := TRUE)
+ * RETURN VARCHAR2;
+ *
+ * FUNCTION plvstr.betwn (string_in IN VARCHAR2,
+ * start_in IN VARCHAR2,
+ * end_in IN VARCHAR2 := NULL,
+ * startnth_in IN INTEGER := 1,
+ * endnth_in IN INTEGER := 1,
+ * inclusive IN BOOLEAN := TRUE,
+ * gotoend IN BOOLEAN := FALSE)
+ * RETURN VARCHAR2;
+ *
+ * Purpose:
+ * Call this function to extract a sub-string from a string. This
+ * function is overloaded. You can either provide the start and end
+ * locations or you can provide start and end substrings.
+ *
+ ****************************************************************/
+
+
+Datum
+plvstr_betwn_i(PG_FUNCTION_ARGS)
+{
+ text *string_in = PG_GETARG_TEXT_P(0);
+ int start_in = PG_GETARG_INT32(1);
+ int end_in = PG_GETARG_INT32(2);
+ bool inclusive = PG_GETARG_BOOL(3);
+
+ if ((start_in < 0 && end_in > 0) ||
+ (start_in > 0 && end_in < 0) ||
+ (start_in > end_in))
+ PARAMETER_ERROR("Wrong positions.");
+
+ if (start_in < 0)
+ {
+ int v_len = ora_mb_strlen1(string_in);
+ start_in = v_len + start_in + 1;
+ end_in = v_len + start_in + 1;
+ }
+
+ if (!inclusive)
+ {
+ start_in += 1;
+ end_in -= 1;
+
+ if (start_in > end_in)
+ PG_RETURN_TEXT_P(cstring_to_text(""));
+ }
+
+ PG_RETURN_TEXT_P(ora_substr_text(string_in,
+ start_in,
+ end_in - start_in + 1));
+}
+
+
+Datum
+plvstr_betwn_c(PG_FUNCTION_ARGS)
+{
+ text *string_in;
+ text *start_in;
+ text *end_in;
+ int startnth_in;
+ int endnth_in;
+ bool inclusive;
+ bool gotoend;
+
+ int v_start;
+ int v_end;
+
+ if (PG_ARGISNULL(0) || PG_ARGISNULL(1) ||
+ PG_ARGISNULL(3) || PG_ARGISNULL(4) ||
+ PG_ARGISNULL(5) || PG_ARGISNULL(6))
+ PG_RETURN_NULL();
+
+
+ string_in = PG_GETARG_TEXT_P(0);
+ start_in = PG_GETARG_TEXT_P(1);
+ end_in = PG_ARGISNULL(2) ? start_in : PG_GETARG_TEXT_P(2);
+ startnth_in = PG_GETARG_INT32(3);
+ endnth_in = PG_GETARG_INT32(4);
+ inclusive = PG_GETARG_BOOL(5);
+ gotoend = PG_GETARG_BOOL(6);
+
+ if (startnth_in == 0)
+ {
+ v_start = 1;
+ v_end = ora_instr(string_in, end_in, 1, endnth_in);
+ }
+ else
+ {
+ v_start = ora_instr(string_in, start_in, 1, startnth_in);
+ v_end = ora_instr(string_in, end_in, v_start + 1, endnth_in);
+ }
+
+ if (v_start == 0)
+ PG_RETURN_NULL();
+
+ if (!inclusive)
+ {
+ if (startnth_in > 0)
+ v_start += ora_mb_strlen1(start_in);
+
+ v_end -= 1;
+ }
+ else
+ v_end += (ora_mb_strlen1(end_in) - 1);
+
+ if (((v_start > v_end) && (v_end > 0)) ||
+ (v_end <= 0 && !gotoend))
+ PG_RETURN_NULL();
+
+ if (v_end <= 0)
+ v_end = ora_mb_strlen1(string_in);
+
+ PG_RETURN_TEXT_P(ora_substr_text(string_in,
+ v_start,
+ v_end - v_start + 1));
+}
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/e74af545/contrib/orafce/plvsubst.c
----------------------------------------------------------------------
diff --git a/contrib/orafce/plvsubst.c b/contrib/orafce/plvsubst.c
new file mode 100644
index 0000000..3017a7b
--- /dev/null
+++ b/contrib/orafce/plvsubst.c
@@ -0,0 +1,252 @@
+/*
+ This code implements one part of functonality of
+ free available library PL/Vision. Please look www.quest.com
+
+ Original author: Steven Feuerstein, 1996 - 2002
+ PostgreSQL implementation author: Pavel Stehule, 2006
+
+ This module is under BSD Licence
+
+ History:
+ 1.0. first public version 22. September 2006
+
+*/
+
+#include "postgres.h"
+#include "utils/builtins.h"
+#include "utils/numeric.h"
+#include "string.h"
+#include "stdlib.h"
+#include "utils/pg_locale.h"
+#include "mb/pg_wchar.h"
+#include "lib/stringinfo.h"
+
+#include "catalog/pg_type.h"
+#include "libpq/pqformat.h"
+#include "utils/array.h"
+#include "utils/memutils.h"
+#include "utils/lsyscache.h"
+#include "access/tupmacs.h"
+#include "orafunc.h"
+#include "builtins.h"
+
+PG_FUNCTION_INFO_V1(plvsubst_string_array);
+PG_FUNCTION_INFO_V1(plvsubst_string_string);
+PG_FUNCTION_INFO_V1(plvsubst_setsubst);
+PG_FUNCTION_INFO_V1(plvsubst_setsubst_default);
+PG_FUNCTION_INFO_V1(plvsubst_subst);
+
+#define C_SUBST "%s"
+
+
+text *c_subst = NULL;
+
+static void
+init_c_subst()
+{
+ if (!c_subst)
+ {
+ MemoryContext oldctx;
+
+ oldctx = MemoryContextSwitchTo(TopMemoryContext);
+ c_subst = cstring_to_text(C_SUBST);
+ MemoryContextSwitchTo(oldctx);
+ }
+}
+
+static void
+set_c_subst(text *sc)
+{
+ MemoryContext oldctx;
+
+ if (c_subst)
+ pfree(c_subst);
+
+ oldctx = MemoryContextSwitchTo(TopMemoryContext);
+ c_subst = sc ? TextPCopy(sc) : cstring_to_text(C_SUBST);
+ MemoryContextSwitchTo(oldctx);
+}
+
+static text*
+plvsubst_string(text *template_in, ArrayType *vals_in, text *c_subst, FunctionCallInfo fcinfo)
+{
+ ArrayType *v = vals_in;
+ int nitems,
+ *dims,
+ ndims;
+ char *p;
+ int16 typlen;
+ bool typbyval;
+ char typalign;
+ char typdelim;
+ Oid typelem;
+ Oid typiofunc;
+ FmgrInfo proc;
+ int i = 0, items = 0;
+ StringInfo sinfo;
+ const char *template_str;
+ int template_len;
+ char *sizes;
+ int *positions;
+ int subst_mb_len;
+ int subst_len;
+ const bits8 *bitmap;
+ int bitmask;
+
+ if (v != NULL && (ndims = ARR_NDIM(v)) > 0)
+ {
+ if (ndims != 1)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("invalid parameter"),
+ errdetail("Array of arguments has wrong dimension: %d", ndims)));
+
+ p = ARR_DATA_PTR(v);
+ dims = ARR_DIMS(v);
+ nitems = ArrayGetNItems(ndims, dims);
+ bitmap = ARR_NULLBITMAP(v);
+ get_type_io_data(ARR_ELEMTYPE(v), IOFunc_output,
+ &typlen, &typbyval,
+ &typalign, &typdelim,
+ &typelem, &typiofunc);
+ fmgr_info_cxt(typiofunc, &proc, fcinfo->flinfo->fn_mcxt);
+ }
+ else
+ {
+ nitems = 0;
+ p = NULL;
+ bitmap = NULL;
+ }
+
+ template_str = VARDATA(template_in);
+ template_len = ora_mb_strlen(template_in, &sizes, &positions);
+ subst_mb_len = ora_mb_strlen1(c_subst);
+ subst_len = VARSIZE_ANY_EXHDR(c_subst);
+ sinfo = makeStringInfo();
+
+ bitmask = 1;
+ for (i = 0; i < template_len; i++)
+ {
+ if (strncmp(&template_str[positions[i]], VARDATA(c_subst), subst_len) == 0)
+ {
+ Datum itemvalue;
+ char *value;
+
+ if (items++ < nitems)
+ {
+ if (bitmap && (*bitmap & bitmask) == 0)
+ value = pstrdup("NULL");
+ else
+ {
+ itemvalue = fetch_att(p, typbyval, typlen);
+ value = DatumGetCString(FunctionCall3(&proc,
+ itemvalue,
+ ObjectIdGetDatum(typelem),
+ Int32GetDatum(-1)));
+
+ p = att_addlength_pointer(p, typlen, p);
+ p = (char *) att_align_nominal(p, typalign);
+ }
+ appendStringInfoString(sinfo, value);
+ pfree(value);
+
+ if (bitmap)
+ {
+ bitmask <<= 1;
+ if (bitmask == 0x100)
+ {
+ bitmap++;
+ bitmask = 1;
+ }
+ }
+ }
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("too few parameters specified for template string")));
+
+ i += subst_mb_len - 1;
+ }
+ else
+ appendBinaryStringInfo(sinfo, &template_str[positions[i]], sizes[i]);
+ }
+
+ return cstring_to_text(sinfo->data);
+}
+
+
+Datum
+plvsubst_string_array(PG_FUNCTION_ARGS)
+{
+ init_c_subst();
+
+ if (PG_ARGISNULL(0) || PG_ARGISNULL(1))
+ PG_RETURN_NULL();
+
+ PG_RETURN_TEXT_P(plvsubst_string(PG_GETARG_TEXT_P(0),
+ PG_GETARG_ARRAYTYPE_P(1),
+ PG_ARGISNULL(2) ? c_subst : PG_GETARG_TEXT_P(2),
+ fcinfo));
+}
+
+Datum
+plvsubst_string_string(PG_FUNCTION_ARGS)
+{
+ Datum r;
+ ArrayType *array;
+ FunctionCallInfoData locfcinfo;
+
+ init_c_subst();
+
+ if (PG_ARGISNULL(0) || PG_ARGISNULL(1))
+ PG_RETURN_NULL();
+
+ /*
+ * I can't use DirectFunctionCall2
+ */
+
+ InitFunctionCallInfoData(locfcinfo, fcinfo->flinfo, 2, NULL, NULL);
+ locfcinfo.arg[0] = PG_GETARG_DATUM(1);
+ locfcinfo.arg[1] = PG_GETARG_IF_EXISTS(2, DATUM, CStringGetTextDatum(","));
+ locfcinfo.argnull[0] = false;
+ locfcinfo.argnull[1] = false;
+ r = text_to_array(&locfcinfo);
+
+ if (locfcinfo.isnull || r == (Datum) 0)
+ array = NULL;
+ else
+ array = DatumGetArrayTypeP(r);
+
+ PG_RETURN_TEXT_P(plvsubst_string(PG_GETARG_TEXT_P(0),
+ array,
+ PG_GETARG_IF_EXISTS(3, TEXT_P, c_subst),
+ fcinfo));
+}
+
+Datum
+plvsubst_setsubst(PG_FUNCTION_ARGS)
+{
+ if (PG_ARGISNULL(0))
+ ereport(ERROR,
+ (errcode(ERRCODE_NULL_VALUE_NOT_ALLOWED),
+ errmsg("substition is NULL"),
+ errdetail("Substitution keyword may not be NULL.")));
+
+ set_c_subst(PG_GETARG_TEXT_P(0));
+ PG_RETURN_VOID();
+}
+
+Datum
+plvsubst_setsubst_default(PG_FUNCTION_ARGS)
+{
+ set_c_subst(NULL);
+ PG_RETURN_VOID();
+}
+
+
+Datum
+plvsubst_subst(PG_FUNCTION_ARGS)
+{
+ init_c_subst();
+ PG_RETURN_TEXT_P(TextPCopy(c_subst));
+}
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/e74af545/contrib/orafce/putline.c
----------------------------------------------------------------------
diff --git a/contrib/orafce/putline.c b/contrib/orafce/putline.c
new file mode 100644
index 0000000..288ca59
--- /dev/null
+++ b/contrib/orafce/putline.c
@@ -0,0 +1,347 @@
+#include "postgres.h"
+#include "funcapi.h"
+#include "access/heapam.h"
+#include "catalog/pg_type.h"
+#include "lib/stringinfo.h"
+
+#include "libpq/libpq.h"
+#include "libpq/pqformat.h"
+#include "utils/memutils.h"
+#include "utils/array.h"
+#include "utils/builtins.h"
+#include "utils/lsyscache.h"
+
+#include "orafunc.h"
+#include "builtins.h"
+
+extern PGDLLIMPORT ProtocolVersion FrontendProtocol;
+
+/*
+ * TODO: BUFSIZE_UNLIMITED to be truely unlimited (or INT_MAX),
+ * and allocate buffers on-demand.
+ */
+#define BUFSIZE_DEFAULT 20000
+#define BUFSIZE_MIN 2000
+#define BUFSIZE_MAX 1000000
+#define BUFSIZE_UNLIMITED BUFSIZE_MAX
+
+static bool is_server_output = false;
+static char *buffer = NULL;
+static int buffer_size = 0; /* allocated bytes in buffer */
+static int buffer_len = 0; /* used bytes in buffer */
+static int buffer_get = 0; /* retrieved bytes in buffer */
+
+static void add_str(const char *str, int len);
+static void add_text(text *str);
+static void add_newline(void);
+static void send_buffer(void);
+
+/*
+ * Aux. buffer functionality
+ */
+static void
+add_str(const char *str, int len)
+{
+ /* Discard all buffers if get_line was called. */
+ if (buffer_get > 0)
+ {
+ buffer_get = 0;
+ buffer_len = 0;
+ }
+
+ if (buffer_len + len > buffer_size)
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
+ errmsg("buffer overflow"),
+ errdetail("Buffer overflow, limit of %d bytes", buffer_size),
+ errhint("Increase buffer size in dbms_output.enable() next time")));
+
+ memcpy(buffer + buffer_len, str, len);
+ buffer_len += len;
+ buffer[buffer_len] = '\0';
+}
+
+static void
+add_text(text *str)
+{
+ add_str(VARDATA_ANY(str), VARSIZE_ANY_EXHDR(str));
+}
+
+static void
+add_newline(void)
+{
+ add_str("", 1); /* add \0 */
+ if (is_server_output)
+ send_buffer();
+}
+
+
+static void
+send_buffer()
+{
+ if (buffer_len > 0)
+ {
+ StringInfoData msgbuf;
+ char *cursor = buffer;
+
+ while (--buffer_len > 0)
+ {
+ if (*cursor == '\0')
+ *cursor = '\n';
+ cursor++;
+ }
+
+ if (*cursor != '\0')
+ ereport(ERROR,
+ (errcode(ERRCODE_INTERNAL_ERROR),
+ errmsg("internal error"),
+ errdetail("Wrong message format detected")));
+
+ pq_beginmessage(&msgbuf, 'N');
+
+ if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 3)
+ {
+ pq_sendbyte(&msgbuf, PG_DIAG_MESSAGE_PRIMARY);
+ pq_sendstring(&msgbuf, buffer);
+ pq_sendbyte(&msgbuf, '\0');
+ }
+ else
+ {
+ *cursor++ = '\n';
+ *cursor = '\0';
+ pq_sendstring(&msgbuf, buffer);
+ }
+
+ pq_endmessage(&msgbuf);
+ pq_flush();
+ }
+}
+
+
+/*
+ * Aux db functions
+ *
+ */
+
+static void
+dbms_output_enable_internal(int32 n_buf_size)
+{
+ /* We allocate +2 bytes for an end-of-line and a string terminator. */
+ if (buffer == NULL)
+ {
+ buffer = MemoryContextAlloc(TopMemoryContext, n_buf_size + 2);
+ buffer_size = n_buf_size;
+ buffer_len = 0;
+ buffer_get = 0;
+ }
+ else if (n_buf_size > buffer_len)
+ {
+ /* We cannot shrink buffer less than current length. */
+ buffer = repalloc(buffer, n_buf_size + 2);
+ buffer_size = n_buf_size;
+ }
+}
+
+PG_FUNCTION_INFO_V1(dbms_output_enable_default);
+
+Datum
+dbms_output_enable_default(PG_FUNCTION_ARGS)
+{
+ dbms_output_enable_internal(BUFSIZE_DEFAULT);
+ PG_RETURN_VOID();
+}
+
+
+PG_FUNCTION_INFO_V1(dbms_output_enable);
+
+Datum
+dbms_output_enable(PG_FUNCTION_ARGS)
+{
+ int32 n_buf_size;
+
+ if (PG_ARGISNULL(0))
+ n_buf_size = BUFSIZE_UNLIMITED;
+ else
+ {
+ n_buf_size = PG_GETARG_INT32(0);
+
+ if (n_buf_size > BUFSIZE_MAX)
+ {
+ n_buf_size = BUFSIZE_MAX;
+ elog(WARNING, "Limit decreased to %d bytes.", BUFSIZE_MAX);
+ }
+ else if (n_buf_size < BUFSIZE_MIN)
+ {
+ n_buf_size = BUFSIZE_MIN;
+ elog(WARNING, "Limit increased to %d bytes.", BUFSIZE_MIN);
+ }
+ }
+
+ dbms_output_enable_internal(n_buf_size);
+ PG_RETURN_VOID();
+}
+
+PG_FUNCTION_INFO_V1(dbms_output_disable);
+
+Datum
+dbms_output_disable(PG_FUNCTION_ARGS)
+{
+ if (buffer)
+ pfree(buffer);
+ buffer = NULL;
+ buffer_size = 0;
+ buffer_len = 0;
+ buffer_get = 0;
+ PG_RETURN_VOID();
+}
+
+PG_FUNCTION_INFO_V1(dbms_output_serveroutput);
+
+Datum
+dbms_output_serveroutput(PG_FUNCTION_ARGS)
+{
+ is_server_output = PG_GETARG_BOOL(0);
+ if (is_server_output && !buffer)
+ dbms_output_enable_internal(BUFSIZE_DEFAULT);
+ PG_RETURN_VOID();
+}
+
+
+/*
+ * main functions
+ */
+
+PG_FUNCTION_INFO_V1(dbms_output_put);
+
+Datum
+dbms_output_put(PG_FUNCTION_ARGS)
+{
+ if (buffer)
+ add_text(PG_GETARG_TEXT_PP(0));
+ PG_RETURN_VOID();
+}
+
+PG_FUNCTION_INFO_V1(dbms_output_put_line);
+
+Datum
+dbms_output_put_line(PG_FUNCTION_ARGS)
+{
+ if (buffer)
+ {
+ add_text(PG_GETARG_TEXT_PP(0));
+ add_newline();
+ }
+ PG_RETURN_VOID();
+}
+
+PG_FUNCTION_INFO_V1(dbms_output_new_line);
+
+Datum
+dbms_output_new_line(PG_FUNCTION_ARGS)
+{
+ if (buffer)
+ add_newline();
+ PG_RETURN_VOID();
+}
+
+static text *
+dbms_output_next(void)
+{
+ if (buffer_get < buffer_len)
+ {
+ text *line = cstring_to_text(buffer + buffer_get);
+ buffer_get += VARSIZE_ANY_EXHDR(line) + 1;
+ return line;
+ }
+ else
+ return NULL;
+}
+
+PG_FUNCTION_INFO_V1(dbms_output_get_line);
+
+Datum
+dbms_output_get_line(PG_FUNCTION_ARGS)
+{
+ TupleDesc tupdesc;
+ Datum result;
+ HeapTuple tuple;
+ Datum values[2];
+ bool nulls[2] = { false, false };
+ text *line;
+
+ /* Build a tuple descriptor for our result type */
+ if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
+ elog(ERROR, "return type must be a row type");
+
+ if ((line = dbms_output_next()) != NULL)
+ {
+ values[0] = PointerGetDatum(line);
+ values[1] = Int32GetDatum(0); /* 0: succeeded */
+ }
+ else
+ {
+ nulls[0] = true;
+ values[1] = Int32GetDatum(1); /* 1: failed */
+ }
+
+ tuple = heap_form_tuple(tupdesc, values, nulls);
+ result = HeapTupleGetDatum(tuple);
+
+ PG_RETURN_DATUM(result);
+}
+
+
+PG_FUNCTION_INFO_V1(dbms_output_get_lines);
+
+Datum
+dbms_output_get_lines(PG_FUNCTION_ARGS)
+{
+ TupleDesc tupdesc;
+ Datum result;
+ HeapTuple tuple;
+ Datum values[2];
+ bool nulls[2] = { false, false };
+ text *line;
+
+ int32 max_lines = PG_GETARG_INT32(0);
+ int32 n;
+ ArrayBuildState *astate = NULL;
+
+ /* Build a tuple descriptor for our result type */
+ if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
+ elog(ERROR, "return type must be a row type");
+
+ for (n = 0; n < max_lines && (line = dbms_output_next()) != NULL; n++)
+ {
+ astate = accumArrayResult(astate, PointerGetDatum(line), false,
+ TEXTOID, CurrentMemoryContext);
+ }
+
+ /* 0: lines as text array */
+ if (n > 0)
+ values[0] = makeArrayResult(astate, CurrentMemoryContext);
+ else
+ {
+ int16 typlen;
+ bool typbyval;
+ char typalign;
+ ArrayType *arr;
+
+ get_typlenbyvalalign(TEXTOID, &typlen, &typbyval, &typalign);
+ arr = construct_md_array(
+ NULL,
+#if PG_VERSION_NUM >= 80200
+ NULL,
+#endif
+ 0, NULL, NULL, TEXTOID, typlen, typbyval, typalign);
+ values[0] = PointerGetDatum(arr);
+ }
+
+ /* 1: # of lines as integer */
+ values[1] = Int32GetDatum(n);
+
+ tuple = heap_form_tuple(tupdesc, values, nulls);
+ result = HeapTupleGetDatum(tuple);
+
+ PG_RETURN_DATUM(result);
+}
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/e74af545/contrib/orafce/random.c
----------------------------------------------------------------------
diff --git a/contrib/orafce/random.c b/contrib/orafce/random.c
new file mode 100644
index 0000000..be39e1b
--- /dev/null
+++ b/contrib/orafce/random.c
@@ -0,0 +1,358 @@
+/*
+ * Note - I don't find any documentation about pseudo random
+ * number generator used in Oracle. So the results of these
+ * functions should be different then native Oracle functions!
+ * This library is based on ANSI C implementation.
+ */
+
+#include "postgres.h"
+#include "access/hash.h"
+#include "lib/stringinfo.h"
+#include "utils/builtins.h"
+
+#include "stdlib.h"
+#include "time.h"
+#include <math.h>
+#include <errno.h>
+
+#include "orafunc.h"
+#include "builtins.h"
+
+PG_FUNCTION_INFO_V1(dbms_random_initialize);
+PG_FUNCTION_INFO_V1(dbms_random_normal);
+PG_FUNCTION_INFO_V1(dbms_random_random);
+PG_FUNCTION_INFO_V1(dbms_random_seed_int);
+PG_FUNCTION_INFO_V1(dbms_random_seed_varchar);
+PG_FUNCTION_INFO_V1(dbms_random_string);
+PG_FUNCTION_INFO_V1(dbms_random_terminate);
+PG_FUNCTION_INFO_V1(dbms_random_value);
+PG_FUNCTION_INFO_V1(dbms_random_value_range);
+
+/* Coefficients in rational approximations. */
+static const double a[] =
+{
+ -3.969683028665376e+01,
+ 2.209460984245205e+02,
+ -2.759285104469687e+02,
+ 1.383577518672690e+02,
+ -3.066479806614716e+01,
+ 2.506628277459239e+00
+};
+
+static const double b[] =
+{
+ -5.447609879822406e+01,
+ 1.615858368580409e+02,
+ -1.556989798598866e+02,
+ 6.680131188771972e+01,
+ -1.328068155288572e+01
+};
+
+static const double c[] =
+{
+ -7.784894002430293e-03,
+ -3.223964580411365e-01,
+ -2.400758277161838e+00,
+ -2.549732539343734e+00,
+ 4.374664141464968e+00,
+ 2.938163982698783e+00
+};
+
+static const double d[] =
+{
+ 7.784695709041462e-03,
+ 3.224671290700398e-01,
+ 2.445134137142996e+00,
+ 3.754408661907416e+00
+};
+
+#define LOW 0.02425
+#define HIGH 0.97575
+
+static double ltqnorm(double p);
+
+
+/*
+ * dbms_random.initialize (seed IN BINARY_INTEGER)
+ *
+ * Initialize package with a seed value
+ */
+Datum
+dbms_random_initialize(PG_FUNCTION_ARGS)
+{
+ int seed = PG_GETARG_INT32(0);
+
+ srand(seed);
+
+ PG_RETURN_VOID();
+}
+
+/*
+ * dbms_random.normal() RETURN NUMBER;
+ *
+ * Returns random numbers in a standard normal distribution
+ */
+Datum
+dbms_random_normal(PG_FUNCTION_ARGS)
+{
+ float8 result;
+
+ /* need random value from (0..1) */
+ result = ltqnorm(((double) rand() + 1) / ((double) RAND_MAX + 2));
+
+ PG_RETURN_FLOAT8(result);
+}
+
+/*
+ * dbms_random.random() RETURN BINARY_INTEGER;
+ *
+ * Generate Random Numeric Values
+ */
+Datum
+dbms_random_random(PG_FUNCTION_ARGS)
+{
+ int result;
+ /*
+ * Oracle generator generates numebers from -2^31 and +2^31,
+ * ANSI C only from 0 .. RAND_MAX,
+ */
+ result = 2 * (rand() - RAND_MAX / 2);
+
+ PG_RETURN_INT32(result);
+}
+
+/*
+ * dbms_random.seed(val IN BINARY_INTEGER);
+ * dbms_random.seed(val IN VARCHAR2);
+ *
+ * Reset the seed value
+ */
+Datum
+dbms_random_seed_int(PG_FUNCTION_ARGS)
+{
+ int seed = PG_GETARG_INT32(0);
+
+ srand(seed);
+
+ PG_RETURN_VOID();
+}
+
+/*
+ * Atention!
+ *
+ * Hash function should be changed between mayor pg versions,
+ * don't use text based seed for regres tests!
+ */
+Datum
+dbms_random_seed_varchar(PG_FUNCTION_ARGS)
+{
+ text *key = PG_GETARG_TEXT_P(0);
+ Datum seed;
+
+ seed = hash_any((unsigned char *) VARDATA_ANY(key), VARSIZE_ANY_EXHDR(key));
+
+ srand((int) seed);
+
+ PG_RETURN_VOID();
+}
+
+/*
+ * dbms_random.string(opt IN CHAR, len IN NUMBER) RETURN VARCHAR2;
+ *
+ * Create Random Strings
+ * opt seed values:
+ * 'a','A' alpha characters only (mixed case)
+ * 'l','L' lower case alpha characters only
+ * 'p','P' any printable characters
+ * 'u','U' upper case alpha characters only
+ * 'x','X' any alpha-numeric characters (upper)
+ */
+static text *
+random_string(const char *charset, int chrset_size, int len)
+{
+ StringInfo str;
+ int i;
+
+ str = makeStringInfo();
+ for (i = 0; i < len; i++)
+ {
+ int pos = (double) rand() / ((double) RAND_MAX + 1) * chrset_size;
+
+ appendStringInfoChar(str, charset[pos]);
+ }
+
+ return cstring_to_text(str->data);
+}
+
+Datum
+dbms_random_string(PG_FUNCTION_ARGS)
+{
+ char *option;
+ int len;
+ const char *charset;
+ int chrset_size;
+
+ const char *alpha_mixed = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ const char *lower_only = "abcdefghijklmnopqrstuvwxyz";
+ const char *upper_only = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ const char *upper_alphanum = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ const char *printable = "`1234567890-=qwertyuiop[]asdfghjkl;'zxcvbnm,./!@#$%^&*()_+QWERTYUIOP{}|ASDFGHJKL:\"ZXCVVBNM<>? ";
+
+ option = text_to_cstring(PG_GETARG_TEXT_P(0));
+ len = PG_GETARG_INT32(1);
+
+ switch (option[0])
+ {
+ case 'a':
+ case 'A':
+ charset = alpha_mixed;
+ chrset_size = strlen(alpha_mixed);
+ break;
+ case 'l':
+ case 'L':
+ charset = lower_only;
+ chrset_size = strlen(lower_only);
+ break;
+ case 'u':
+ case 'U':
+ charset = upper_only;
+ chrset_size = strlen(upper_only);
+ break;
+ case 'x':
+ case 'X':
+ charset = upper_alphanum;
+ chrset_size = strlen(upper_alphanum);
+ break;
+ case 'p':
+ case 'P':
+ charset = printable;
+ chrset_size = strlen(printable);
+ break;
+
+ default:
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("unknown option '%s'", option),
+ errhint("available option \"aAlLuUxXpP\"")));
+ /* be compiler a quiete */
+ charset = NULL;
+ chrset_size = 0;
+ }
+
+ PG_RETURN_TEXT_P(random_string(charset, chrset_size, len));
+}
+
+/*
+ * dbms_random.terminate;
+ *
+ * Terminate use of the Package
+ */
+Datum
+dbms_random_terminate(PG_FUNCTION_ARGS)
+{
+ /* do nothing */
+ PG_RETURN_VOID();
+}
+
+/*
+ * dbms_random.value() RETURN NUMBER;
+ *
+ * Gets a random number, greater than or equal to 0 and less than 1.
+ */
+Datum
+dbms_random_value(PG_FUNCTION_ARGS)
+{
+ float8 result;
+
+ /* result [0.0 - 1.0) */
+ result = (double) rand() / ((double) RAND_MAX + 1);
+
+ PG_RETURN_FLOAT8(result);
+}
+
+/*
+ * dbms_random.value(low NUMBER, high NUMBER) RETURN NUMBER
+ *
+ * Alternatively, you can get a random Oracle number x,
+ * where x is greater than or equal to low and less than high
+ */
+Datum
+dbms_random_value_range(PG_FUNCTION_ARGS)
+{
+ float8 low = PG_GETARG_FLOAT8(0);
+ float8 high = PG_GETARG_FLOAT8(1);
+ float8 result;
+
+ if (low > high)
+ PG_RETURN_NULL();
+
+ result = ((double) rand() / ((double) RAND_MAX + 1)) * ( high - low) + low;
+
+ PG_RETURN_FLOAT8(result);
+}
+
+
+/*
+ * Lower tail quantile for standard normal distribution function.
+ *
+ * This function returns an approximation of the inverse cumulative
+ * standard normal distribution function. I.e., given P, it returns
+ * an approximation to the X satisfying P = Pr{Z <= X} where Z is a
+ * random variable from the standard normal distribution.
+ *
+ * The algorithm uses a minimax approximation by rational functions
+ * and the result has a relative error whose absolute value is less
+ * than 1.15e-9.
+ *
+ * Author: Peter J. Acklam
+ * Time-stamp: 2002-06-09 18:45:44 +0200
+ * E-mail: jacklam@math.uio.no
+ * WWW URL: http://www.math.uio.no/~jacklam
+ *
+ * C implementation adapted from Peter's Perl version
+ */
+static double
+ltqnorm(double p)
+{
+ double q, r;
+
+ errno = 0;
+
+ if (p < 0 || p > 1)
+ {
+ errno = EDOM;
+ return 0.0;
+ }
+ else if (p == 0)
+ {
+ errno = ERANGE;
+ return -HUGE_VAL /* minus "infinity" */;
+ }
+ else if (p == 1)
+ {
+ errno = ERANGE;
+ return HUGE_VAL /* "infinity" */;
+ }
+ else if (p < LOW)
+ {
+ /* Rational approximation for lower region */
+ q = sqrt(-2*log(p));
+ return (((((c[0]*q+c[1])*q+c[2])*q+c[3])*q+c[4])*q+c[5]) /
+ ((((d[0]*q+d[1])*q+d[2])*q+d[3])*q+1);
+ }
+ else if (p > HIGH)
+ {
+ /* Rational approximation for upper region */
+ q = sqrt(-2*log(1-p));
+ return -(((((c[0]*q+c[1])*q+c[2])*q+c[3])*q+c[4])*q+c[5]) /
+ ((((d[0]*q+d[1])*q+d[2])*q+d[3])*q+1);
+ }
+ else
+ {
+ /* Rational approximation for central region */
+ q = p - 0.5;
+ r = q*q;
+ return (((((a[0]*r+a[1])*r+a[2])*r+a[3])*r+a[4])*r+a[5])*q /
+ (((((b[0]*r+b[1])*r+b[2])*r+b[3])*r+b[4])*r+1);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/e74af545/contrib/orafce/shmmc.c
----------------------------------------------------------------------
diff --git a/contrib/orafce/shmmc.c b/contrib/orafce/shmmc.c
new file mode 100644
index 0000000..0a61d92
--- /dev/null
+++ b/contrib/orafce/shmmc.c
@@ -0,0 +1,341 @@
+/*
+ *
+ * Shared memory control - based on alocating chunks aligned on
+ * asize array (fibonachi), and dividing free bigger block.
+ *
+ */
+
+#include "postgres.h"
+#include "shmmc.h"
+#include "stdlib.h"
+#include "string.h"
+#include "orafunc.h"
+
+
+#define LIST_ITEMS 512
+
+int context;
+
+typedef struct {
+ size_t size;
+ void* first_byte_ptr;
+ bool dispossible;
+/* int16 context; */
+} list_item;
+
+typedef struct {
+ int list_c;
+ int max_size;
+ vardata data[1]; /* flexible array member */
+} mem_desc;
+
+#define MAX_SIZE 82688
+
+static size_t asize[] = {
+ 32,
+ 64, 96, 160, 256,
+ 416, 672, 1088, 1760,
+ 2848, 4608, 7456, 12064,
+ 19520, 31584, 51104, 82688};
+
+
+int *list_c = NULL;
+list_item *list = NULL;
+size_t max_size;
+
+int cycle = 0;
+
+
+/* align requested size */
+
+static int
+ptr_comp(const void* a, const void* b)
+{
+ list_item *_a = (list_item*) a;
+ list_item *_b = (list_item*) b;
+
+ return (long)_a->first_byte_ptr - (long)_b->first_byte_ptr;
+}
+
+char *
+ora_sstrcpy(char *str)
+{
+ int len;
+ char *result;
+
+ len = strlen(str);
+ if (NULL != (result = ora_salloc(len+1)))
+ memcpy(result, str, len + 1);
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_OUT_OF_MEMORY),
+ errmsg("out of memory"),
+ errdetail("Failed while allocation block %d bytes in shared memory.", len+1),
+ errhint("Increase SHMEMMSGSZ and recompile package.")));
+
+ return result;
+}
+
+char *
+ora_scstring(text *str)
+{
+ int len;
+ char *result;
+
+ len = VARSIZE_ANY_EXHDR(str);
+
+ if (NULL != (result = ora_salloc(len+1)))
+ {
+ memcpy(result, VARDATA_ANY(str), len);
+ result[len] = '\0';
+ }
+ else
+ ereport(ERROR,
+ (errcode(ERRCODE_OUT_OF_MEMORY),
+ errmsg("out of memory"),
+ errdetail("Failed while allocation block %d bytes in shared memory.", len+1),
+ errhint("Increase SHMEMMSGSZ and recompile package.")));
+
+ return result;
+}
+
+/*
+ * Compact the list of slots, by merging adjacent unused slots into larger
+ * slots.
+ */
+static void
+defragmentation()
+{
+ int src, target;
+
+ /* Sort the array to pointer order */
+ qsort(list, *list_c, sizeof(list_item), ptr_comp);
+
+ /* Merge adjacent dispossible slots, and move up other slots */
+ target = 0;
+ for (src = 0; src < *list_c; src++)
+ {
+ if (target > 0 &&
+ list[src].dispossible &&
+ list[target - 1].dispossible)
+ {
+ list[target - 1].size += list[src].size;
+ }
+ else
+ {
+ if (src != target)
+ memcpy(&list[target], &list[src], sizeof(list_item));
+ target++;
+ }
+ }
+ *list_c = target;
+}
+
+static size_t
+align_size(size_t size)
+{
+ int i;
+
+ /* default, we can allocate max MAX_SIZE memory block */
+
+ for (i = 0; i < 17; i++)
+ if (asize[i] >= size)
+ return asize[i];
+
+ ereport(ERROR,
+ (errcode(ERRCODE_OUT_OF_MEMORY),
+ errmsg("too much large memory block request"),
+ errdetail("Failed while allocation block %lu bytes in shared memory.", (unsigned long) size),
+ errhint("Increase MAX_SIZE constant, fill table a_size and recompile package.")));
+
+ return 0;
+}
+
+/*
+ inicialize shared memory. It works in two modes, create and no create.
+ No create is used for mounting shared memory buffer. Top of memory is
+ used for list_item array.
+*/
+
+void
+ora_sinit(void *ptr, size_t size, bool create)
+{
+ if (list == NULL)
+ {
+ mem_desc *m = (mem_desc*)ptr;
+ list = (list_item*)m->data;
+ list_c = &m->list_c;
+ max_size = m->max_size = size;
+
+ if (create)
+ {
+ list[0].size = size - sizeof(list_item)*LIST_ITEMS - sizeof(mem_desc);
+ list[0].first_byte_ptr = &m->data + sizeof(list_item)*LIST_ITEMS;
+ list[0].dispossible = true;
+ *list_c = 1;
+ }
+ }
+}
+
+
+void*
+ora_salloc(size_t size)
+{
+ size_t aligned_size;
+ int repeat_c;
+ void *ptr = NULL;
+
+ aligned_size = align_size(size);
+
+ for (repeat_c = 0; repeat_c < 2; repeat_c++)
+ {
+ size_t max_min = max_size;
+ int select = -1;
+ int i;
+
+ /* find first good free block */
+ for (i = 0; i < *list_c; i++)
+ {
+ if (list[i].dispossible)
+ {
+ /* If this block is just the right size, return it */
+ if (list[i].size == aligned_size)
+ {
+ list[i].dispossible = false;
+ ptr = list[i].first_byte_ptr;
+ /* list[i].context = context; */
+
+ return ptr;
+ }
+
+ if (list[i].size > aligned_size && list[i].size < max_min)
+ {
+ max_min = list[i].size;
+ select = i;
+ }
+ }
+ }
+
+ /* If no suitable free slot found, defragment and try again. */
+ if (select == -1 || *list_c == LIST_ITEMS)
+ {
+ defragmentation();
+ continue;
+ }
+
+ /*
+ * A slot larger than required was found. Divide it to avoid wasting
+ * space, and return the slot of the right size.
+ */
+ list[*list_c].size = list[select].size - aligned_size;
+ list[*list_c].first_byte_ptr = (char*)list[select].first_byte_ptr + aligned_size;
+ list[*list_c].dispossible = true;
+ list[select].size = aligned_size;
+ list[select].dispossible = false;
+ /* list[select].context = context; */
+ ptr = list[select].first_byte_ptr;
+ *list_c += 1;
+ break;
+ }
+
+ return ptr;
+}
+
+void
+ora_sfree(void* ptr)
+{
+ int i;
+
+/*
+ if (cycle++ % 100 == 0)
+ {
+ size_t suma = 0;
+ for (i = 0; i < *list_c; i++)
+ if (list[i].dispossible)
+ suma += list[i].size;
+ elog(NOTICE, "=============== FREE MEM REPORT === %10d ================", suma);
+ }
+*/
+
+ for (i = 0; i < *list_c; i++)
+ if (list[i].first_byte_ptr == ptr)
+ {
+ list[i].dispossible = true;
+ /* list[i].context = -1; */
+ memset(list[i].first_byte_ptr, '#', list[i].size);
+ return;
+ }
+
+ ereport(ERROR,
+ (errcode(ERRCODE_INTERNAL_ERROR),
+ errmsg("corrupted pointer"),
+ errdetail("Failed while reallocating memory block in shared memory."),
+ errhint("Report this bug to autors.")));
+}
+
+
+void*
+ora_srealloc(void *ptr, size_t size)
+{
+ void *result;
+ size_t aux_s = 0;
+ int i;
+
+ for (i = 0; i < *list_c; i++)
+ if (list[i].first_byte_ptr == ptr)
+ {
+ if (align_size(size) <= list[i].size)
+ return ptr;
+ aux_s = list[i].size;
+ }
+
+ if (aux_s == 0)
+ ereport(ERROR,
+ (errcode(ERRCODE_INTERNAL_ERROR),
+ errmsg("corrupted pointer"),
+ errdetail("Failed while reallocating memory block in shared memory."),
+ errhint("Report this bug to autors.")));
+
+
+ if (NULL != (result = ora_salloc(size)))
+ {
+ memcpy(result, ptr, aux_s);
+ ora_sfree(ptr);
+ }
+
+ return result;
+}
+
+/*
+ * alloc shared memory, raise exception if not
+ */
+
+void*
+salloc(size_t size)
+{
+ void* result;
+
+ if (NULL == (result = ora_salloc(size)))
+ ereport(ERROR,
+ (errcode(ERRCODE_OUT_OF_MEMORY),
+ errmsg("out of memory"),
+ errdetail("Failed while allocation block %lu bytes in shared memory.", (unsigned long) size),
+ errhint("Increase SHMEMMSGSZ and recompile package.")));
+
+ return result;
+}
+
+void*
+srealloc(void *ptr, size_t size)
+{
+ void* result;
+
+ if (NULL == (result = ora_srealloc(ptr, size)))
+ ereport(ERROR,
+ (errcode(ERRCODE_OUT_OF_MEMORY),
+ errmsg("out of memory"),
+ errdetail("Failed while reallocation block %lu bytes in shared memory.", (unsigned long) size),
+ errhint("Increase SHMEMMSGSZ and recompile package.")));
+
+ return result;
+}
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/e74af545/contrib/orafce/shmmc.h
----------------------------------------------------------------------
diff --git a/contrib/orafce/shmmc.h b/contrib/orafce/shmmc.h
new file mode 100644
index 0000000..2bf26b9
--- /dev/null
+++ b/contrib/orafce/shmmc.h
@@ -0,0 +1,12 @@
+#ifndef __SHMMC__
+#define __SHMMC__
+
+void ora_sinit(void *ptr, size_t size, bool create);
+void* ora_salloc(size_t size);
+void* ora_srealloc(void *ptr, size_t size);
+void ora_sfree(void* ptr);
+char* ora_sstrcpy(char *str);
+char* ora_scstring(text *str);
+void* salloc(size_t size);
+void* srealloc(void *ptr,size_t size);
+#endif
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/e74af545/contrib/orafce/sql/dbms_output.sql
----------------------------------------------------------------------
diff --git a/contrib/orafce/sql/dbms_output.sql b/contrib/orafce/sql/dbms_output.sql
new file mode 100644
index 0000000..c46088c
--- /dev/null
+++ b/contrib/orafce/sql/dbms_output.sql
@@ -0,0 +1,764 @@
+\set ECHO none
+SET client_min_messages = warning;
+SET DATESTYLE TO ISO;
+SET client_encoding = utf8;
+\pset null '<NULL>'
+\set ECHO all
+
+DROP FUNCTION dbms_output_test();
+DROP TABLE dbms_output_test;
+
+-- DBMS_OUTPUT.DISABLE [0]
+CREATE TABLE dbms_output_test (buff VARCHAR(20), status INTEGER);
+CREATE FUNCTION dbms_output_test() RETURNS VOID AS $$
+DECLARE
+ buff VARCHAR(20);
+ stts INTEGER;
+BEGIN
+ PERFORM DBMS_OUTPUT.PUT_LINE ('ORAFCE TEST 1');
+ SELECT INTO buff,stts line,status FROM DBMS_OUTPUT.GET_LINE();
+ INSERT INTO dbms_output_test VALUES (buff, stts);
+END;
+$$ LANGUAGE plpgsql;
+SELECT dbms_output_test();
+SELECT * FROM dbms_output_test;
+DROP TABLE dbms_output_test;
+DROP FUNCTION dbms_output_test();
+
+-- DBMS_OUTPUT.PUT_LINE [1]
+CREATE FUNCTION dbms_output_test() RETURNS VOID AS $$
+DECLARE
+ buff1 VARCHAR(20) := 'orafce';
+BEGIN
+ PERFORM DBMS_OUTPUT.DISABLE();
+ PERFORM DBMS_OUTPUT.ENABLE();
+ PERFORM DBMS_OUTPUT.SERVEROUTPUT ('t');
+ PERFORM DBMS_OUTPUT.PUT_LINE ('ORAFCE');
+ PERFORM DBMS_OUTPUT.PUT_LINE (buff1);
+ PERFORM DBMS_OUTPUT.PUT ('ABC');
+ PERFORM DBMS_OUTPUT.PUT_LINE ('');
+END;
+$$ LANGUAGE plpgsql;
+SELECT dbms_output_test();
+DROP FUNCTION dbms_output_test();
+
+-- DBMS_OUTPUT.PUT_LINE [2]
+CREATE FUNCTION dbms_output_test() RETURNS VOID AS $$
+BEGIN
+ PERFORM DBMS_OUTPUT.DISABLE();
+ PERFORM DBMS_OUTPUT.ENABLE();
+ PERFORM DBMS_OUTPUT.SERVEROUTPUT ('t');
+ PERFORM DBMS_OUTPUT.PUT_LINE ('ORA
+F
+CE');
+END;
+$$ LANGUAGE plpgsql;
+SELECT dbms_output_test();
+DROP FUNCTION dbms_output_test();
+
+-- DBMS_OUTPUT.PUT [1]
+CREATE FUNCTION dbms_output_test() RETURNS VOID AS $$
+DECLARE
+ buff1 VARCHAR(20) := 'ora';
+ buff2 VARCHAR(20) := 'f';
+ buff3 VARCHAR(20) := 'ce';
+BEGIN
+ PERFORM DBMS_OUTPUT.DISABLE();
+ PERFORM DBMS_OUTPUT.ENABLE();
+ PERFORM DBMS_OUTPUT.SERVEROUTPUT ('t');
+ PERFORM DBMS_OUTPUT.PUT ('ORA');
+ PERFORM DBMS_OUTPUT.PUT ('F');
+ PERFORM DBMS_OUTPUT.PUT ('CE');
+ PERFORM DBMS_OUTPUT.PUT_LINE ('');
+ PERFORM DBMS_OUTPUT.PUT ('ABC');
+ PERFORM DBMS_OUTPUT.PUT_LINE ('');
+END;
+$$ LANGUAGE plpgsql;
+SELECT dbms_output_test();
+DROP FUNCTION dbms_output_test();
+
+-- DBMS_OUTPUT.PUT [2]
+CREATE FUNCTION dbms_output_test() RETURNS VOID AS $$
+BEGIN
+ PERFORM DBMS_OUTPUT.DISABLE();
+ PERFORM DBMS_OUTPUT.ENABLE();
+ PERFORM DBMS_OUTPUT.SERVEROUTPUT ('t');
+ PERFORM DBMS_OUTPUT.PUT ('ORA
+F
+CE');
+ PERFORM DBMS_OUTPUT.PUT_LINE ('');
+END;
+$$ LANGUAGE plpgsql;
+SELECT dbms_output_test();
+DROP FUNCTION dbms_output_test();
+
+-- DBMS_OUTPUT.GET_LINE [1]
+CREATE TABLE dbms_output_test (buff VARCHAR(20), status INTEGER);
+CREATE FUNCTION dbms_output_test() RETURNS VOID AS $$
+DECLARE
+ buff VARCHAR(20);
+ stts INTEGER;
+BEGIN
+ PERFORM DBMS_OUTPUT.DISABLE();
+ PERFORM DBMS_OUTPUT.ENABLE();
+ PERFORM DBMS_OUTPUT.SERVEROUTPUT ('f');
+ PERFORM DBMS_OUTPUT.PUT_LINE ('ORAFCE TEST 1');
+ PERFORM DBMS_OUTPUT.PUT_LINE ('ORAFCE TEST 2');
+ SELECT INTO buff,stts line,status FROM DBMS_OUTPUT.GET_LINE();
+ INSERT INTO dbms_output_test VALUES (buff, stts);
+ SELECT INTO buff,stts line,status FROM DBMS_OUTPUT.GET_LINE();
+ INSERT INTO dbms_output_test VALUES (buff, stts);
+ PERFORM DBMS_OUTPUT.DISABLE();
+ PERFORM DBMS_OUTPUT.ENABLE();
+END;
+$$ LANGUAGE plpgsql;
+SELECT dbms_output_test();
+SELECT * FROM dbms_output_test;
+DROP TABLE dbms_output_test;
+DROP FUNCTION dbms_output_test();
+
+-- DBMS_OUTPUT.GET_LINE [2]
+CREATE TABLE dbms_output_test (buff VARCHAR(20), status INTEGER);
+CREATE FUNCTION dbms_output_test() RETURNS VOID AS $$
+DECLARE
+ buff VARCHAR(20);
+ stts INTEGER;
+BEGIN
+ PERFORM DBMS_OUTPUT.DISABLE();
+ PERFORM DBMS_OUTPUT.ENABLE();
+ PERFORM DBMS_OUTPUT.SERVEROUTPUT ('f');
+ PERFORM DBMS_OUTPUT.PUT_LINE ('ORAFCE TEST 1');
+ PERFORM DBMS_OUTPUT.PUT_LINE ('ORAFCE TEST 2');
+ SELECT INTO buff,stts line,status FROM DBMS_OUTPUT.GET_LINE();
+ INSERT INTO dbms_output_test VALUES (buff, stts);
+ PERFORM DBMS_OUTPUT.PUT_LINE ('ORAFCE TEST 3');
+ SELECT INTO buff,stts line,status FROM DBMS_OUTPUT.GET_LINE();
+ INSERT INTO dbms_output_test VALUES (buff, stts);
+ SELECT INTO buff,stts line,status FROM DBMS_OUTPUT.GET_LINE();
+ INSERT INTO dbms_output_test VALUES (buff, stts);
+ SELECT INTO buff,stts line,status FROM DBMS_OUTPUT.GET_LINE();
+ INSERT INTO dbms_output_test VALUES (buff, stts);
+ PERFORM DBMS_OUTPUT.DISABLE();
+ PERFORM DBMS_OUTPUT.ENABLE();
+END;
+$$ LANGUAGE plpgsql;
+SELECT dbms_output_test();
+SELECT * FROM dbms_output_test;
+DROP TABLE dbms_output_test;
+DROP FUNCTION dbms_output_test();
+
+-- DBMS_OUTPUT.GET_LINE [3]
+CREATE TABLE dbms_output_test (buff VARCHAR(20), status INTEGER);
+CREATE FUNCTION dbms_output_test() RETURNS VOID AS $$
+DECLARE
+ buff VARCHAR(20);
+ stts INTEGER;
+BEGIN
+ PERFORM DBMS_OUTPUT.DISABLE();
+ PERFORM DBMS_OUTPUT.ENABLE();
+ PERFORM DBMS_OUTPUT.SERVEROUTPUT ('f');
+ PERFORM DBMS_OUTPUT.PUT_LINE ('ORAFCE TEST 1');
+ PERFORM DBMS_OUTPUT.PUT_LINE ('ORAFCE TEST 2');
+ SELECT INTO buff,stts line,status FROM DBMS_OUTPUT.GET_LINE();
+ INSERT INTO dbms_output_test VALUES (buff, stts);
+ PERFORM DBMS_OUTPUT.PUT ('ORA');
+ SELECT INTO buff,stts line,status FROM DBMS_OUTPUT.GET_LINE();
+ INSERT INTO dbms_output_test VALUES (buff, stts);
+ SELECT INTO buff,stts line,status FROM DBMS_OUTPUT.GET_LINE();
+ INSERT INTO dbms_output_test VALUES (buff, stts);
+ PERFORM DBMS_OUTPUT.DISABLE();
+ PERFORM DBMS_OUTPUT.ENABLE();
+END;
+$$ LANGUAGE plpgsql;
+SELECT dbms_output_test();
+SELECT * FROM dbms_output_test;
+DROP TABLE dbms_output_test;
+DROP FUNCTION dbms_output_test();
+
+-- DBMS_OUTPUT.GET_LINE [4]
+CREATE TABLE dbms_output_test (buff VARCHAR(20), status INTEGER);
+CREATE FUNCTION dbms_output_test() RETURNS VOID AS $$
+DECLARE
+ buff VARCHAR(20);
+ stts INTEGER;
+BEGIN
+ PERFORM DBMS_OUTPUT.DISABLE();
+ PERFORM DBMS_OUTPUT.ENABLE();
+ PERFORM DBMS_OUTPUT.SERVEROUTPUT ('f');
+ PERFORM DBMS_OUTPUT.PUT_LINE ('ORAFCE TEST 1');
+ PERFORM DBMS_OUTPUT.PUT_LINE ('ORAFCE TEST 2');
+ SELECT INTO buff,stts line,status FROM DBMS_OUTPUT.GET_LINE();
+ INSERT INTO dbms_output_test VALUES (buff, stts);
+ PERFORM DBMS_OUTPUT.NEW_LINE();
+ SELECT INTO buff,stts line,status FROM DBMS_OUTPUT.GET_LINE();
+ INSERT INTO dbms_output_test VALUES (buff, stts);
+ SELECT INTO buff,stts line,status FROM DBMS_OUTPUT.GET_LINE();
+ INSERT INTO dbms_output_test VALUES (buff, stts);
+ PERFORM DBMS_OUTPUT.DISABLE();
+ PERFORM DBMS_OUTPUT.ENABLE();
+END;
+$$ LANGUAGE plpgsql;
+SELECT dbms_output_test();
+SELECT * FROM dbms_output_test;
+DROP TABLE dbms_output_test;
+DROP FUNCTION dbms_output_test();
+
+-- DBMS_OUTPUT.GET_LINE [5]
+CREATE TABLE dbms_output_test (buff VARCHAR(20), status INTEGER);
+CREATE FUNCTION dbms_output_test() RETURNS VOID AS $$
+DECLARE
+ buff VARCHAR(20);
+ stts INTEGER;
+BEGIN
+ PERFORM DBMS_OUTPUT.DISABLE();
+ PERFORM DBMS_OUTPUT.ENABLE();
+ PERFORM DBMS_OUTPUT.SERVEROUTPUT ('f');
+ PERFORM DBMS_OUTPUT.PUT_LINE ('ORAFCE TEST 1
+');
+ PERFORM DBMS_OUTPUT.PUT_LINE ('ORAFCE TEST 2');
+ SELECT INTO buff,stts line,status FROM DBMS_OUTPUT.GET_LINE();
+ INSERT INTO dbms_output_test VALUES (buff, stts);
+ SELECT INTO buff,stts line,status FROM DBMS_OUTPUT.GET_LINE();
+ INSERT INTO dbms_output_test VALUES (buff, stts);
+ PERFORM DBMS_OUTPUT.DISABLE();
+ PERFORM DBMS_OUTPUT.ENABLE();
+END;
+$$ LANGUAGE plpgsql;
+SELECT dbms_output_test();
+SELECT REPLACE(buff, '
+', '<LF>') FROM dbms_output_test;
+DROP TABLE dbms_output_test;
+DROP FUNCTION dbms_output_test();
+
+-- DBMS_OUTPUT.GET_LINE [6]
+CREATE TABLE dbms_output_test (buff VARCHAR(20), status INTEGER);
+CREATE FUNCTION dbms_output_test() RETURNS VOID AS $$
+DECLARE
+ buff VARCHAR(20);
+ stts INTEGER;
+BEGIN
+ PERFORM DBMS_OUTPUT.DISABLE();
+ PERFORM DBMS_OUTPUT.ENABLE();
+ PERFORM DBMS_OUTPUT.SERVEROUTPUT ('f');
+ PERFORM DBMS_OUTPUT.PUT_LINE ('ORA
+F
+CE');
+ SELECT INTO buff,stts line,status FROM DBMS_OUTPUT.GET_LINE();
+ INSERT INTO dbms_output_test VALUES (buff, stts);
+ PERFORM DBMS_OUTPUT.DISABLE();
+ PERFORM DBMS_OUTPUT.ENABLE();
+END;
+$$ LANGUAGE plpgsql;
+SELECT dbms_output_test();
+SELECT regexp_replace(buff, E'\n', '<LF>', 'g') FROM dbms_output_test limit 1;
+DROP TABLE dbms_output_test;
+DROP FUNCTION dbms_output_test();
+
+-- DBMS_OUTPUT.GET_LINES [1]
+CREATE TABLE dbms_output_test (buff VARCHAR(20), status INTEGER);
+CREATE FUNCTION dbms_output_test() RETURNS VOID AS $$
+DECLARE
+ buff VARCHAR(20);
+ buff1 VARCHAR(20);
+ buff2 VARCHAR(20);
+ buff3 VARCHAR(20);
+ stts INTEGER := 10;
+BEGIN
+ PERFORM DBMS_OUTPUT.DISABLE();
+ PERFORM DBMS_OUTPUT.ENABLE();
+ PERFORM DBMS_OUTPUT.SERVEROUTPUT ('f');
+ PERFORM DBMS_OUTPUT.PUT_LINE ('ORAFCE TEST 1');
+ PERFORM DBMS_OUTPUT.PUT_LINE ('ORAFCE TEST 2');
+ PERFORM DBMS_OUTPUT.PUT_LINE ('ORAFCE TEST 3');
+ SELECT INTO buff1,buff2,buff3,stts lines[1],lines[2],lines[3],numlines FROM DBMS_OUTPUT.GET_LINES(stts);
+ INSERT INTO dbms_output_test VALUES (buff1, stts);
+ INSERT INTO dbms_output_test VALUES (buff2, stts);
+ INSERT INTO dbms_output_test VALUES (buff3, stts);
+ SELECT INTO buff,stts lines[1],numlines FROM DBMS_OUTPUT.GET_LINES(stts);
+ INSERT INTO dbms_output_test VALUES (buff, stts);
+ PERFORM DBMS_OUTPUT.DISABLE();
+ PERFORM DBMS_OUTPUT.ENABLE();
+END;
+$$ LANGUAGE plpgsql;
+SELECT dbms_output_test();
+SELECT * FROM dbms_output_test;
+DROP TABLE dbms_output_test;
+DROP FUNCTION dbms_output_test();
+
+-- DBMS_OUTPUT.GET_LINES [2]
+CREATE TABLE dbms_output_test (buff VARCHAR(20), status INTEGER);
+CREATE FUNCTION dbms_output_test() RETURNS VOID AS $$
+DECLARE
+ buff VARCHAR(20);
+ buff1 VARCHAR(20);
+ buff2 VARCHAR(20);
+ stts INTEGER := 2;
+BEGIN
+ PERFORM DBMS_OUTPUT.DISABLE();
+ PERFORM DBMS_OUTPUT.ENABLE();
+ PERFORM DBMS_OUTPUT.SERVEROUTPUT ('f');
+ PERFORM DBMS_OUTPUT.PUT_LINE ('ORAFCE TEST 1');
+ PERFORM DBMS_OUTPUT.PUT_LINE ('ORAFCE TEST 2');
+ PERFORM DBMS_OUTPUT.PUT_LINE ('ORAFCE TEST 3');
+ SELECT INTO buff1,buff2,stts lines[1],lines[2],numlines FROM DBMS_OUTPUT.GET_LINES(stts);
+ INSERT INTO dbms_output_test VALUES (buff1, stts);
+ INSERT INTO dbms_output_test VALUES (buff2, stts);
+ SELECT INTO buff,stts lines[1],numlines FROM DBMS_OUTPUT.GET_LINES(stts);
+ INSERT INTO dbms_output_test VALUES (buff, stts);
+ PERFORM DBMS_OUTPUT.DISABLE();
+ PERFORM DBMS_OUTPUT.ENABLE();
+END;
+$$ LANGUAGE plpgsql;
+SELECT dbms_output_test();
+SELECT * FROM dbms_output_test;
+DROP TABLE dbms_output_test;
+DROP FUNCTION dbms_output_test();
+
+-- DBMS_OUTPUT.GET_LINES [3]
+CREATE TABLE dbms_output_test (buff VARCHAR(20), status INTEGER);
+CREATE FUNCTION dbms_output_test() RETURNS VOID AS $$
+DECLARE
+ buff VARCHAR(20);
+ stts INTEGER := 1;
+BEGIN
+ PERFORM DBMS_OUTPUT.DISABLE();
+ PERFORM DBMS_OUTPUT.ENABLE();
+ PERFORM DBMS_OUTPUT.SERVEROUTPUT ('f');
+ PERFORM DBMS_OUTPUT.PUT_LINE ('ORAFCE TEST 1');
+ PERFORM DBMS_OUTPUT.PUT_LINE ('ORAFCE TEST 2');
+ SELECT INTO buff,stts lines[1],numlines FROM DBMS_OUTPUT.GET_LINES(stts);
+ INSERT INTO dbms_output_test VALUES (buff, stts);
+ PERFORM DBMS_OUTPUT.PUT_LINE ('ORAFCE TEST 3');
+ SELECT INTO buff,stts lines[1],numlines FROM DBMS_OUTPUT.GET_LINES(stts);
+ INSERT INTO dbms_output_test VALUES (buff, stts);
+ SELECT INTO buff,stts lines[1],numlines FROM DBMS_OUTPUT.GET_LINES(stts);
+ INSERT INTO dbms_output_test VALUES (buff, stts);
+ PERFORM DBMS_OUTPUT.DISABLE();
+ PERFORM DBMS_OUTPUT.ENABLE();
+END;
+$$ LANGUAGE plpgsql;
+SELECT dbms_output_test();
+SELECT * FROM dbms_output_test;
+DROP TABLE dbms_output_test;
+DROP FUNCTION dbms_output_test();
+
+-- DBMS_OUTPUT.GET_LINES [4]
+CREATE TABLE dbms_output_test (buff VARCHAR(20), status INTEGER);
+CREATE FUNCTION dbms_output_test() RETURNS VOID AS $$
+DECLARE
+ buff VARCHAR(20);
+ stts INTEGER := 1;
+BEGIN
+ PERFORM DBMS_OUTPUT.DISABLE();
+ PERFORM DBMS_OUTPUT.ENABLE();
+ PERFORM DBMS_OUTPUT.SERVEROUTPUT ('f');
+ PERFORM DBMS_OUTPUT.PUT_LINE ('ORAFCE TEST 1');
+ PERFORM DBMS_OUTPUT.PUT_LINE ('ORAFCE TEST 2');
+ SELECT INTO buff,stts lines[1],numlines FROM DBMS_OUTPUT.GET_LINES(stts);
+ INSERT INTO dbms_output_test VALUES (buff, stts);
+ PERFORM DBMS_OUTPUT.PUT ('ORA');
+ SELECT INTO buff,stts lines[1],numlines FROM DBMS_OUTPUT.GET_LINES(stts);
+ INSERT INTO dbms_output_test VALUES (buff, stts);
+ SELECT INTO buff,stts lines[1],numlines FROM DBMS_OUTPUT.GET_LINES(stts);
+ INSERT INTO dbms_output_test VALUES (buff, stts);
+ PERFORM DBMS_OUTPUT.DISABLE();
+ PERFORM DBMS_OUTPUT.ENABLE();
+END;
+$$ LANGUAGE plpgsql;
+SELECT dbms_output_test();
+SELECT * FROM dbms_output_test;
+DROP TABLE dbms_output_test;
+DROP FUNCTION dbms_output_test();
+
+-- DBMS_OUTPUT.GET_LINES [5]
+CREATE TABLE dbms_output_test (buff VARCHAR(20), status INTEGER);
+CREATE FUNCTION dbms_output_test() RETURNS VOID AS $$
+DECLARE
+ buff VARCHAR(20);
+ stts INTEGER := 1;
+BEGIN
+ PERFORM DBMS_OUTPUT.DISABLE();
+ PERFORM DBMS_OUTPUT.ENABLE();
+ PERFORM DBMS_OUTPUT.SERVEROUTPUT ('f');
+ PERFORM DBMS_OUTPUT.PUT_LINE ('ORAFCE TEST 1');
+ PERFORM DBMS_OUTPUT.PUT_LINE ('ORAFCE TEST 2');
+ SELECT INTO buff,stts lines[1],numlines FROM DBMS_OUTPUT.GET_LINES(stts);
+ INSERT INTO dbms_output_test VALUES (buff, stts);
+ PERFORM DBMS_OUTPUT.NEW_LINE();
+ SELECT INTO buff,stts lines[1],numlines FROM DBMS_OUTPUT.GET_LINES(stts);
+ INSERT INTO dbms_output_test VALUES (buff, stts);
+ SELECT INTO buff,stts lines[1],numlines FROM DBMS_OUTPUT.GET_LINES(stts);
+ INSERT INTO dbms_output_test VALUES (buff, stts);
+ PERFORM DBMS_OUTPUT.DISABLE();
+ PERFORM DBMS_OUTPUT.ENABLE();
+END;
+$$ LANGUAGE plpgsql;
+SELECT dbms_output_test();
+SELECT * FROM dbms_output_test;
+DROP TABLE dbms_output_test;
+DROP FUNCTION dbms_output_test();
+
+-- DBMS_OUTPUT.GET_LINES [6]
+CREATE TABLE dbms_output_test (buff VARCHAR(20), status INTEGER);
+CREATE FUNCTION dbms_output_test() RETURNS VOID AS $$
+DECLARE
+ buff VARCHAR(20);
+ stts INTEGER := 1;
+BEGIN
+ PERFORM DBMS_OUTPUT.DISABLE();
+ PERFORM DBMS_OUTPUT.ENABLE();
+ PERFORM DBMS_OUTPUT.SERVEROUTPUT ('f');
+ PERFORM DBMS_OUTPUT.PUT_LINE ('ORA
+F
+CE');
+ SELECT INTO buff,stts lines[1],numlines FROM DBMS_OUTPUT.GET_LINES(stts);
+ INSERT INTO dbms_output_test VALUES (buff, stts);
+ PERFORM DBMS_OUTPUT.DISABLE();
+ PERFORM DBMS_OUTPUT.ENABLE();
+END;
+$$ LANGUAGE plpgsql;
+SELECT dbms_output_test();
+SELECT regexp_replace(buff, E'\n', '<LF>', 'g') FROM dbms_output_test limit 1;
+DROP TABLE dbms_output_test;
+DROP FUNCTION dbms_output_test();
+
+-- DBMS_OUTPUT.NEW_LINE [1]
+CREATE TABLE dbms_output_test (buff VARCHAR(20), status INTEGER);
+CREATE FUNCTION dbms_output_test() RETURNS VOID AS $$
+DECLARE
+ buff1 VARCHAR(20);
+ buff2 VARCHAR(20);
+ stts INTEGER := 10;
+BEGIN
+ PERFORM DBMS_OUTPUT.DISABLE();
+ PERFORM DBMS_OUTPUT.ENABLE();
+ PERFORM DBMS_OUTPUT.SERVEROUTPUT ('f');
+ PERFORM DBMS_OUTPUT.PUT ('ORA');
+ PERFORM DBMS_OUTPUT.NEW_LINE();
+ PERFORM DBMS_OUTPUT.PUT ('FCE');
+ PERFORM DBMS_OUTPUT.NEW_LINE();
+ SELECT INTO buff1,buff2,stts lines[1],lines[2],numlines FROM DBMS_OUTPUT.GET_LINES(stts);
+ INSERT INTO dbms_output_test VALUES (buff1, stts);
+ INSERT INTO dbms_output_test VALUES (buff2, stts);
+ PERFORM DBMS_OUTPUT.DISABLE();
+ PERFORM DBMS_OUTPUT.ENABLE();
+END;
+$$ LANGUAGE plpgsql;
+SELECT dbms_output_test();
+SELECT * FROM dbms_output_test;
+DROP TABLE dbms_output_test;
+DROP FUNCTION dbms_output_test();
+
+-- DBMS_OUTPUT.NEW_LINE [2]
+CREATE TABLE dbms_output_test (buff VARCHAR(3000), status INTEGER);
+CREATE FUNCTION dbms_output_test() RETURNS VOID AS $$
+DECLARE
+ buff1 VARCHAR(3000);
+ stts INTEGER := 10;
+BEGIN
+ PERFORM DBMS_OUTPUT.DISABLE();
+ PERFORM DBMS_OUTPUT.ENABLE();
+ PERFORM DBMS_OUTPUT.SERVEROUTPUT ('f');
+ PERFORM DBMS_OUTPUT.ENABLE(2000);
+ FOR j IN 1..1999 LOOP
+ PERFORM DBMS_OUTPUT.PUT ('A');
+ END LOOP;
+ PERFORM DBMS_OUTPUT.NEW_LINE();
+ SELECT INTO buff1,stts lines[1],numlines FROM DBMS_OUTPUT.GET_LINES(stts);
+ INSERT INTO dbms_output_test VALUES (buff1, stts);
+ PERFORM DBMS_OUTPUT.DISABLE();
+ PERFORM DBMS_OUTPUT.ENABLE();
+END;
+$$ LANGUAGE plpgsql;
+SELECT dbms_output_test();
+SELECT buff FROM dbms_output_test;
+DROP TABLE dbms_output_test;
+DROP FUNCTION dbms_output_test();
+
+-- DBMS_OUTPUT.DISABLE [1]
+CREATE TABLE dbms_output_test (buff VARCHAR(20), status INTEGER);
+CREATE FUNCTION dbms_output_test() RETURNS VOID AS $$
+DECLARE
+ buff VARCHAR(20);
+ stts INTEGER;
+BEGIN
+ PERFORM DBMS_OUTPUT.DISABLE();
+ PERFORM DBMS_OUTPUT.ENABLE();
+ PERFORM DBMS_OUTPUT.SERVEROUTPUT ('f');
+ PERFORM DBMS_OUTPUT.PUT_LINE ('ORAFCE TEST 1');
+ PERFORM DBMS_OUTPUT.DISABLE();
+ PERFORM DBMS_OUTPUT.ENABLE();
+ SELECT INTO buff,stts line,status FROM DBMS_OUTPUT.GET_LINE();
+ INSERT INTO dbms_output_test VALUES (buff, stts);
+
+ PERFORM DBMS_OUTPUT.DISABLE();
+ PERFORM DBMS_OUTPUT.ENABLE();
+ PERFORM DBMS_OUTPUT.DISABLE();
+ PERFORM DBMS_OUTPUT.PUT_LINE ('ORAFCE TEST 2');
+ PERFORM DBMS_OUTPUT.ENABLE();
+ SELECT INTO buff,stts line,status FROM DBMS_OUTPUT.GET_LINE();
+ INSERT INTO dbms_output_test VALUES (buff, stts);
+
+ PERFORM DBMS_OUTPUT.DISABLE();
+ PERFORM DBMS_OUTPUT.ENABLE();
+ PERFORM DBMS_OUTPUT.PUT_LINE ('ORAFCE TEST 3');
+ PERFORM DBMS_OUTPUT.DISABLE();
+ SELECT INTO buff,stts line,status FROM DBMS_OUTPUT.GET_LINE();
+ INSERT INTO dbms_output_test VALUES (buff, stts);
+ PERFORM DBMS_OUTPUT.ENABLE();
+
+ PERFORM DBMS_OUTPUT.DISABLE();
+ PERFORM DBMS_OUTPUT.ENABLE();
+ PERFORM DBMS_OUTPUT.DISABLE();
+ PERFORM DBMS_OUTPUT.PUT ('ORAFCE TEST 4');
+ PERFORM DBMS_OUTPUT.ENABLE();
+ PERFORM DBMS_OUTPUT.NEW_LINE();
+ SELECT INTO buff,stts line,status FROM DBMS_OUTPUT.GET_LINE();
+ INSERT INTO dbms_output_test VALUES (buff, stts);
+
+ PERFORM DBMS_OUTPUT.DISABLE();
+ PERFORM DBMS_OUTPUT.ENABLE();
+ PERFORM DBMS_OUTPUT.PUT ('ORAFCE TEST 5');
+ PERFORM DBMS_OUTPUT.DISABLE();
+ PERFORM DBMS_OUTPUT.NEW_LINE();
+ PERFORM DBMS_OUTPUT.ENABLE();
+ SELECT INTO buff,stts line,status FROM DBMS_OUTPUT.GET_LINE();
+ INSERT INTO dbms_output_test VALUES (buff, stts);
+
+ PERFORM DBMS_OUTPUT.DISABLE();
+ PERFORM DBMS_OUTPUT.ENABLE();
+END;
+$$ LANGUAGE plpgsql;
+SELECT dbms_output_test();
+SELECT * FROM dbms_output_test;
+DROP TABLE dbms_output_test;
+DROP FUNCTION dbms_output_test();
+
+-- DBMS_OUTPUT.DISABLE [2]
+CREATE TABLE dbms_output_test (buff VARCHAR(20), status INTEGER);
+CREATE FUNCTION dbms_output_test() RETURNS VOID AS $$
+DECLARE
+ buff VARCHAR(20);
+ stts INTEGER := 10;
+BEGIN
+ PERFORM DBMS_OUTPUT.DISABLE();
+ PERFORM DBMS_OUTPUT.ENABLE();
+ PERFORM DBMS_OUTPUT.SERVEROUTPUT ('f');
+ PERFORM DBMS_OUTPUT.DISABLE();
+ PERFORM DBMS_OUTPUT.PUT_LINE ('ORAFCE TEST 1');
+ SELECT INTO buff,stts lines[1],numlines FROM DBMS_OUTPUT.GET_LINES(stts);
+ INSERT INTO dbms_output_test VALUES (buff, stts);
+ PERFORM DBMS_OUTPUT.ENABLE();
+END;
+$$ LANGUAGE plpgsql;
+SELECT dbms_output_test();
+SELECT * FROM dbms_output_test;
+DROP TABLE dbms_output_test;
+DROP FUNCTION dbms_output_test();
+
+-- DBMS_OUTPUT.ENABLE [1]
+CREATE TABLE dbms_output_test (buff VARCHAR(20), status INTEGER);
+CREATE FUNCTION dbms_output_test() RETURNS VOID AS $$
+DECLARE
+ buff VARCHAR(20);
+ status INTEGER;
+ num INTEGER := 2000;
+BEGIN
+ PERFORM DBMS_OUTPUT.DISABLE();
+ PERFORM DBMS_OUTPUT.ENABLE();
+ PERFORM DBMS_OUTPUT.SERVEROUTPUT ('t');
+ PERFORM DBMS_OUTPUT.ENABLE(2000);
+ PERFORM DBMS_OUTPUT.PUT ('ORAFCE TEST 1');
+ PERFORM DBMS_OUTPUT.NEW_LINE();
+ PERFORM DBMS_OUTPUT.ENABLE();
+END;
+$$ LANGUAGE plpgsql;
+SELECT dbms_output_test();
+SELECT * FROM dbms_output_test;
+DROP TABLE dbms_output_test;
+DROP FUNCTION dbms_output_test();
+
+-- DBMS_OUTPUT.ENABLE [2]
+CREATE TABLE dbms_output_test (buff VARCHAR(20), status INTEGER);
+CREATE FUNCTION dbms_output_test() RETURNS VOID AS $$
+DECLARE
+ buff VARCHAR(20);
+ stts INTEGER;
+BEGIN
+ PERFORM DBMS_OUTPUT.DISABLE();
+ PERFORM DBMS_OUTPUT.ENABLE();
+ PERFORM DBMS_OUTPUT.SERVEROUTPUT ('f');
+ PERFORM DBMS_OUTPUT.DISABLE();
+ PERFORM DBMS_OUTPUT.ENABLE();
+ PERFORM DBMS_OUTPUT.PUT_LINE ('ORAFCE TEST 1');
+ SELECT INTO buff,stts line,status FROM DBMS_OUTPUT.GET_LINE();
+ INSERT INTO dbms_output_test VALUES (buff, stts);
+ PERFORM DBMS_OUTPUT.PUT ('ORAFCE TEST 2');
+ PERFORM DBMS_OUTPUT.NEW_LINE();
+ SELECT INTO buff,stts line,status FROM DBMS_OUTPUT.GET_LINE();
+ INSERT INTO dbms_output_test VALUES (buff, stts);
+ PERFORM DBMS_OUTPUT.ENABLE();
+END;
+$$ LANGUAGE plpgsql;
+SELECT dbms_output_test();
+SELECT * FROM dbms_output_test;
+DROP TABLE dbms_output_test;
+DROP FUNCTION dbms_output_test();
+
+-- DBMS_OUTPUT.ENABLE [3]
+CREATE TABLE dbms_output_test (buff VARCHAR(20), status INTEGER);
+CREATE FUNCTION dbms_output_test() RETURNS VOID AS $$
+DECLARE
+ buff VARCHAR(20);
+ stts INTEGER := 10;
+BEGIN
+ PERFORM DBMS_OUTPUT.DISABLE();
+ PERFORM DBMS_OUTPUT.ENABLE();
+ PERFORM DBMS_OUTPUT.SERVEROUTPUT ('f');
+ PERFORM DBMS_OUTPUT.DISABLE();
+ PERFORM DBMS_OUTPUT.ENABLE();
+ PERFORM DBMS_OUTPUT.PUT_LINE ('ORAFCE TEST 1');
+ SELECT INTO buff,stts lines[1],numlines FROM DBMS_OUTPUT.GET_LINES(stts);
+ INSERT INTO dbms_output_test VALUES (buff, stts);
+
+END;
+$$ LANGUAGE plpgsql;
+SELECT dbms_output_test();
+SELECT * FROM dbms_output_test;
+DROP TABLE dbms_output_test;
+DROP FUNCTION dbms_output_test();
+
+-- DBMS_OUTPUT.ENABLE [4]
+CREATE FUNCTION dbms_output_test() RETURNS VOID AS $$
+BEGIN
+ PERFORM DBMS_OUTPUT.DISABLE();
+ PERFORM DBMS_OUTPUT.ENABLE();
+ PERFORM DBMS_OUTPUT.SERVEROUTPUT ('t');
+ PERFORM DBMS_OUTPUT.DISABLE();
+ PERFORM DBMS_OUTPUT.ENABLE();
+ FOR j IN 1..2000 LOOP
+ PERFORM DBMS_OUTPUT.PUT ('A');
+ END LOOP;
+ PERFORM DBMS_OUTPUT.NEW_LINE();
+END;
+$$ LANGUAGE plpgsql;
+SELECT dbms_output_test();
+DROP FUNCTION dbms_output_test();
+
+-- DBMS_OUTPUT.ENABLE [5]
+CREATE TABLE dbms_output_test (buff VARCHAR(20), status INTEGER);
+CREATE FUNCTION dbms_output_test() RETURNS VOID AS $$
+DECLARE
+ buff VARCHAR(20);
+ stts INTEGER;
+BEGIN
+ PERFORM DBMS_OUTPUT.DISABLE();
+ PERFORM DBMS_OUTPUT.ENABLE();
+ PERFORM DBMS_OUTPUT.SERVEROUTPUT ('f');
+ PERFORM DBMS_OUTPUT.DISABLE();
+ PERFORM DBMS_OUTPUT.ENABLE(NULL);
+ PERFORM DBMS_OUTPUT.PUT_LINE ('ORAFCE TEST 1');
+ SELECT INTO buff,stts line,status FROM DBMS_OUTPUT.GET_LINE();
+ INSERT INTO dbms_output_test VALUES (buff, stts);
+ PERFORM DBMS_OUTPUT.DISABLE();
+ PERFORM DBMS_OUTPUT.ENABLE();
+END;
+$$ LANGUAGE plpgsql;
+SELECT dbms_output_test();
+SELECT * FROM dbms_output_test;
+DROP TABLE dbms_output_test;
+DROP FUNCTION dbms_output_test();
+
+-- DBMS_OUTPUT.ENABLE [6]
+CREATE TABLE dbms_output_test (buff VARCHAR(20), status INTEGER);
+CREATE FUNCTION dbms_output_test() RETURNS VOID AS $$
+DECLARE
+ buff VARCHAR(20);
+ stts INTEGER;
+BEGIN
+ PERFORM DBMS_OUTPUT.DISABLE();
+ PERFORM DBMS_OUTPUT.ENABLE();
+ PERFORM DBMS_OUTPUT.SERVEROUTPUT ('f');
+ PERFORM DBMS_OUTPUT.PUT_LINE ('ORAFCE TEST 1');
+ PERFORM DBMS_OUTPUT.ENABLE();
+ SELECT INTO buff,stts line,status FROM DBMS_OUTPUT.GET_LINE();
+ INSERT INTO dbms_output_test VALUES (buff, stts);
+ PERFORM DBMS_OUTPUT.DISABLE();
+ PERFORM DBMS_OUTPUT.ENABLE();
+END;
+$$ LANGUAGE plpgsql;
+SELECT dbms_output_test();
+SELECT * FROM dbms_output_test;
+DROP TABLE dbms_output_test;
+DROP FUNCTION dbms_output_test();
+
+-- SERVEROUTPUT [1]
+CREATE FUNCTION dbms_output_test() RETURNS VOID AS $$
+BEGIN
+ PERFORM DBMS_OUTPUT.DISABLE();
+ PERFORM DBMS_OUTPUT.ENABLE();
+ PERFORM DBMS_OUTPUT.SERVEROUTPUT ('f');
+ PERFORM DBMS_OUTPUT.PUT_LINE ('ORAFCE TEST 1');
+END;
+$$ LANGUAGE plpgsql;
+SELECT dbms_output_test();
+DROP FUNCTION dbms_output_test();
+
+CREATE FUNCTION dbms_output_test() RETURNS VOID AS $$
+BEGIn
+ PERFORM DBMS_OUTPUT.DISABLE();
+ PERFORM DBMS_OUTPUT.ENABLE();
+ PERFORM DBMS_OUTPUT.SERVEROUTPUT ('t');
+ PERFORM DBMS_OUTPUT.PUT_LINE ('ORAFCE TEST 2');
+END;
+$$ LANGUAGE plpgsql;
+SELECT dbms_output_test();
+DROP FUNCTION dbms_output_test();
+
+-- SERVEROUTPUT [2]
+CREATE FUNCTION dbms_output_test() RETURNS VOID AS $$
+BEGIN
+ PERFORM DBMS_OUTPUT.DISABLE();
+ PERFORM DBMS_OUTPUT.ENABLE();
+ PERFORM DBMS_OUTPUT.SERVEROUTPUT ('f');
+ PERFORM DBMS_OUTPUT.PUT ('ORAFCE TEST 1');
+ PERFORM DBMS_OUTPUT.NEW_LINE();
+END;
+$$ LANGUAGE plpgsql;
+SELECT dbms_output_test();
+DROP FUNCTION dbms_output_test();
+
+CREATE FUNCTION dbms_output_test() RETURNS VOID AS $$
+BEGIN
+ PERFORM DBMS_OUTPUT.DISABLE();
+ PERFORM DBMS_OUTPUT.ENABLE();
+ PERFORM DBMS_OUTPUT.SERVEROUTPUT ('t');
+ PERFORM DBMS_OUTPUT.PUT ('ORAFCE TEST 2');
+ PERFORM DBMS_OUTPUT.NEW_LINE();
+END;
+$$ LANGUAGE plpgsql;
+SELECT dbms_output_test();
+DROP FUNCTION dbms_output_test();
+
+-- SERVEROUTPUT [3]
+CREATE FUNCTION dbms_output_test() RETURNS VOID AS $$
+BEGIN
+ PERFORM DBMS_OUTPUT.DISABLE();
+ PERFORM DBMS_OUTPUT.ENABLE();
+ PERFORM DBMS_OUTPUT.SERVEROUTPUT ('f');
+ PERFORM DBMS_OUTPUT.DISABLE();
+END;
+$$ LANGUAGE plpgsql;
+SELECT dbms_output_test();
+DROP FUNCTION dbms_output_test();
+
+CREATE FUNCTION dbms_output_test() RETURNS VOID AS $$
+BEGIN
+ PERFORM DBMS_OUTPUT.DISABLE();
+ PERFORM DBMS_OUTPUT.ENABLE();
+ PERFORM DBMS_OUTPUT.SERVEROUTPUT ('t');
+ PERFORM DBMS_OUTPUT.PUT_LINE ('ORAFCE TEST 1');
+END;
+$$ LANGUAGE plpgsql;
+SELECT dbms_output_test();
+DROP FUNCTION dbms_output_test();
http://git-wip-us.apache.org/repos/asf/incubator-hawq/blob/e74af545/contrib/orafce/sql/dbms_pipe.sql
----------------------------------------------------------------------
diff --git a/contrib/orafce/sql/dbms_pipe.sql b/contrib/orafce/sql/dbms_pipe.sql
new file mode 100644
index 0000000..853b9d1
--- /dev/null
+++ b/contrib/orafce/sql/dbms_pipe.sql
@@ -0,0 +1,58 @@
+CREATE TYPE testt AS (x integer, y integer, v varchar);
+
+CREATE OR REPLACE FUNCTION st(integer, integer, varchar)
+RETURNS void AS $$
+DECLARE t testt; r record;
+BEGIN t.x := $1; t.y := $2; t.v := $3;
+ select into r 10,10,'boo';
+ PERFORM dbms_pipe.pack_message(t);
+END;
+$$ LANGUAGE plpgsql;
+
+CREATE OR REPLACE FUNCTION sk()
+RETURNS void AS $$
+DECLARE t testt;
+ o testt;
+BEGIN t.x := 1; t.y := 2; t.v := 'Pavel Stehule';
+ RAISE NOTICE 'SEND';
+ PERFORM dbms_pipe.pack_message(t);
+ PERFORM dbms_pipe.send_message('boo',4,10);
+ RAISE NOTICE 'RECEIVE';
+-- PERFORM dbms_pipe.receive_message('boo',4);
+-- SELECT INTO o * from dbms_pipe.unpack_message_record() as (x integer, y integer, v varchar);
+-- RAISE NOTICE 'received %', o.v;
+END;
+$$ LANGUAGE plpgsql;
+
+
+
+CREATE OR REPLACE FUNCTION SessionA() RETURNS void AS $$
+BEGIN
+ FOR i IN 1..100000 LOOP
+ PERFORM dbms_pipe.pack_message('Prvni '||i);
+ PERFORM dbms_pipe.pack_message('Druhy '||i);
+ RAISE NOTICE 'SEND';
+ IF dbms_pipe.send_message('pipe_name',4,10) = 1 THEN
+ RAISE NOTICE 'Timeout';
+ PERFORM pg_sleep(5);
+ PERFORM dbms_pipe.send_message('pipe_name',4,10);
+ END IF;
+ PERFORM pg_sleep(random());
+ END LOOP;
+END; $$ LANGUAGE plpgsql;
+
+CREATE OR REPLACE FUNCTION SessionB() RETURNS void AS $$
+BEGIN
+ FOR i IN 1..100000 LOOP
+ IF dbms_pipe.receive_message('pipe_name',4) = 1 THEN
+ RAISE NOTICE 'Timeout';
+ PERFORM pg_sleep(5);
+ CONTINUE;
+ END IF;
+ RAISE NOTICE 'RECEIVE % %', dbms_pipe.unpack_message_text(),
+ dbms_pipe.unpack_message_text();
+ PERFORM pg_sleep(random());
+ END LOOP;
+END; $$ LANGUAGE plpgsql;
+
+