diff --git a/src/common/backend/tsearch/to_tsany.cpp b/src/common/backend/tsearch/to_tsany.cpp index a682148de..3a229baf0 100644 --- a/src/common/backend/tsearch/to_tsany.cpp +++ b/src/common/backend/tsearch/to_tsany.cpp @@ -227,6 +227,9 @@ Datum to_tsvector(PG_FUNCTION_ARGS) { ts_check_feature_disable(); text* in = PG_GETARG_TEXT_P(0); + + FUNC_CHECK_HUGE_POINTER(false, in, "to_txvector()"); + Oid cfgId; cfgId = getTSCurrentConfig(true); diff --git a/src/common/backend/utils/adt/a_compat.cpp b/src/common/backend/utils/adt/a_compat.cpp index 9078e49cf..7361c3fa2 100644 --- a/src/common/backend/utils/adt/a_compat.cpp +++ b/src/common/backend/utils/adt/a_compat.cpp @@ -39,11 +39,8 @@ static text* dotrim(const char* string, int stringlen, const char* set, int setl Datum lower(PG_FUNCTION_ARGS) { text* in_string = PG_GETARG_TEXT_PP(0); - if (unlikely(VARATT_IS_HUGE_TOAST_POINTER(in_string))) { - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("lower() arguments cannot exceed 1GB"))); - } + FUNC_CHECK_HUGE_POINTER(false, in_string, "lower()"); + char* out_string = NULL; text* result = NULL; @@ -71,11 +68,8 @@ Datum lower(PG_FUNCTION_ARGS) Datum upper(PG_FUNCTION_ARGS) { text* in_string = PG_GETARG_TEXT_PP(0); - if (unlikely(VARATT_IS_HUGE_TOAST_POINTER(in_string))) { - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("upper() arguments cannot exceed 1GB"))); - } + FUNC_CHECK_HUGE_POINTER(false, in_string, "upper()"); + char* out_string = NULL; text* result = NULL; @@ -108,6 +102,7 @@ Datum initcap(PG_FUNCTION_ARGS) text* in_string = PG_GETARG_TEXT_PP(0); char* out_string = NULL; text* result = NULL; + FUNC_CHECK_HUGE_POINTER(false, in_string, "initcap()"); out_string = str_initcap(VARDATA_ANY(in_string), VARSIZE_ANY_EXHDR(in_string), PG_GET_COLLATION()); result = cstring_to_text(out_string); @@ -144,6 +139,8 @@ Datum lpad(PG_FUNCTION_ARGS) int bytelen; errno_t ss_rc; + FUNC_CHECK_HUGE_POINTER(false, string1, "lpad()"); + /* Negative len is silently taken as zero */ if (len < 0) len = 0; @@ -236,6 +233,7 @@ Datum rpad(PG_FUNCTION_ARGS) text* ret = NULL; char *ptr1 = NULL, *ptr2 = NULL, *ptr2start = NULL, *ptr2end = NULL, *ptr_ret = NULL; int m, s1len, s2len; + FUNC_CHECK_HUGE_POINTER(false, string1, "rpad()"); int bytelen; errno_t ss_rc; @@ -328,6 +326,8 @@ Datum btrim(PG_FUNCTION_ARGS) text* set = PG_GETARG_TEXT_PP(1); text* ret = NULL; + FUNC_CHECK_HUGE_POINTER(false, string, "btrim()"); + ret = dotrim(VARDATA_ANY(string), VARSIZE_ANY_EXHDR(string), VARDATA_ANY(set), VARSIZE_ANY_EXHDR(set), true, true); if ((ret == NULL || 0 == VARSIZE_ANY_EXHDR(ret)) && u_sess->attr.attr_sql.sql_compatibility == A_FORMAT) @@ -347,6 +347,8 @@ Datum btrim1(PG_FUNCTION_ARGS) text* string = PG_GETARG_TEXT_PP(0); text* ret = NULL; + FUNC_CHECK_HUGE_POINTER(false, string, "btrim1()"); + ret = dotrim(VARDATA_ANY(string), VARSIZE_ANY_EXHDR(string), " ", 1, true, true); if ((ret == NULL || 0 == VARSIZE_ANY_EXHDR(ret)) && u_sess->attr.attr_sql.sql_compatibility == A_FORMAT) @@ -512,6 +514,8 @@ Datum byteatrim(PG_FUNCTION_ARGS) char *ptr = NULL, *end = NULL, *ptr2 = NULL, *ptr2start = NULL, *end2 = NULL; int m, stringlen, setlen; + FUNC_CHECK_HUGE_POINTER(false, string, "byteatrim()"); + stringlen = VARSIZE_ANY_EXHDR(string); setlen = VARSIZE_ANY_EXHDR(set); @@ -580,6 +584,8 @@ Datum ltrim(PG_FUNCTION_ARGS) text* set = PG_GETARG_TEXT_PP(1); text* ret = NULL; + FUNC_CHECK_HUGE_POINTER(false, string, "ltrim()"); + ret = dotrim(VARDATA_ANY(string), VARSIZE_ANY_EXHDR(string), VARDATA_ANY(set), VARSIZE_ANY_EXHDR(set), true, false); if ((ret == NULL || 0 == VARSIZE_ANY_EXHDR(ret)) && u_sess->attr.attr_sql.sql_compatibility == A_FORMAT) @@ -598,6 +604,7 @@ Datum ltrim1(PG_FUNCTION_ARGS) { text* string = PG_GETARG_TEXT_PP(0); text* ret = NULL; + FUNC_CHECK_HUGE_POINTER(false, string, "ltrim1()"); ret = dotrim(VARDATA_ANY(string), VARSIZE_ANY_EXHDR(string), " ", 1, true, false); @@ -627,6 +634,7 @@ Datum rtrim(PG_FUNCTION_ARGS) text* string = PG_GETARG_TEXT_PP(0); text* set = PG_GETARG_TEXT_PP(1); text* ret = NULL; + FUNC_CHECK_HUGE_POINTER(false, string, "rtrim()"); ret = dotrim(VARDATA_ANY(string), VARSIZE_ANY_EXHDR(string), VARDATA_ANY(set), VARSIZE_ANY_EXHDR(set), false, true); @@ -646,6 +654,7 @@ Datum rtrim1(PG_FUNCTION_ARGS) { text* string = PG_GETARG_TEXT_PP(0); text* ret = NULL; + FUNC_CHECK_HUGE_POINTER(false, string, "rtrim1"); if (u_sess->attr.attr_sql.sql_compatibility == A_FORMAT && CHAR_COERCE_COMPAT) { /* @@ -695,6 +704,8 @@ Datum translate(PG_FUNCTION_ARGS) int from_index; errno_t ss_rc; + FUNC_CHECK_HUGE_POINTER(false, string, "translate()"); + m = VARSIZE_ANY_EXHDR(string); if (m <= 0) PG_RETURN_TEXT_P(string); @@ -805,6 +816,8 @@ Datum ascii(PG_FUNCTION_ARGS) int encoding = GetDatabaseEncoding(); unsigned char* data = NULL; + FUNC_CHECK_HUGE_POINTER(false, string, "ascii()"); + if (VARSIZE_ANY_EXHDR(string) <= 0) PG_RETURN_INT32(0); @@ -956,6 +969,9 @@ Datum repeat(PG_FUNCTION_ARGS) { text* string = PG_GETARG_TEXT_PP(0); int32 count = PG_GETARG_INT32(1); + + FUNC_CHECK_HUGE_POINTER(false, string, "repeat()"); + text* result = NULL; int slen, tlen; int i; diff --git a/src/common/backend/utils/adt/like.cpp b/src/common/backend/utils/adt/like.cpp index 9aafceeaf..33733df41 100644 --- a/src/common/backend/utils/adt/like.cpp +++ b/src/common/backend/utils/adt/like.cpp @@ -252,11 +252,8 @@ Datum textlike(PG_FUNCTION_ARGS) { text* str = PG_GETARG_TEXT_PP(0); text* pat = PG_GETARG_TEXT_PP(1); - if (unlikely(VARATT_IS_HUGE_TOAST_POINTER(str))) { - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("like 'partten' cannot exceed 1GB"))); - } + FUNC_CHECK_HUGE_POINTER(false, str, "textlike()"); + bool result = false; char *s, *p; int slen, plen; @@ -275,6 +272,8 @@ Datum textnlike(PG_FUNCTION_ARGS) { text* str = PG_GETARG_TEXT_PP(0); text* pat = PG_GETARG_TEXT_PP(1); + FUNC_CHECK_HUGE_POINTER(false, str, "textnlike()"); + bool result = false; char *s, *p; int slen, plen; @@ -293,6 +292,8 @@ Datum bytealike(PG_FUNCTION_ARGS) { bytea* str = PG_GETARG_BYTEA_PP(0); bytea* pat = PG_GETARG_BYTEA_PP(1); + FUNC_CHECK_HUGE_POINTER(false, str, "bytealike()"); + bool result = false; char *s, *p; int slen, plen; @@ -311,6 +312,8 @@ Datum byteanlike(PG_FUNCTION_ARGS) { bytea* str = PG_GETARG_BYTEA_PP(0); bytea* pat = PG_GETARG_BYTEA_PP(1); + FUNC_CHECK_HUGE_POINTER(false, str, "byteanlike()"); + bool result = false; char *s, *p; int slen, plen; @@ -330,6 +333,8 @@ byteawithoutorderwithequalcollike(PG_FUNCTION_ARGS) { bytea *str = PG_GETARG_BYTEA_PP(0); bytea *pat = PG_GETARG_BYTEA_PP(1); + FUNC_CHECK_HUGE_POINTER(false, str, "byteanlike()"); + bool result = false; char *s, *p; int slen, plen; @@ -349,6 +354,8 @@ byteawithoutorderwithequalcolnlike(PG_FUNCTION_ARGS) { bytea *str = PG_GETARG_BYTEA_PP(0); bytea *pat = PG_GETARG_BYTEA_PP(1); + FUNC_CHECK_HUGE_POINTER(false, str, "byteanlike()"); + bool result = false; char *s, *p; int slen, plen; @@ -367,6 +374,8 @@ Datum rawlike(PG_FUNCTION_ARGS) { bytea* str = PG_GETARG_BYTEA_PP(0); bytea* pat = PG_GETARG_BYTEA_PP(1); + FUNC_CHECK_HUGE_POINTER(false, str, "rawlike()"); + bool result = false; char *s, *p; int slen, plen; @@ -384,6 +393,8 @@ Datum rawnlike(PG_FUNCTION_ARGS) { bytea* str = PG_GETARG_BYTEA_PP(0); bytea* pat = PG_GETARG_BYTEA_PP(1); + FUNC_CHECK_HUGE_POINTER(false, str, "rawnlike()"); + bool result = false; char *s, *p; int slen, plen; @@ -431,6 +442,8 @@ Datum texticlike(PG_FUNCTION_ARGS) { text* str = PG_GETARG_TEXT_PP(0); text* pat = PG_GETARG_TEXT_PP(1); + FUNC_CHECK_HUGE_POINTER(false, str, "textclike()"); + bool result = false; result = (Generic_Text_IC_like(str, pat, PG_GET_COLLATION()) == LIKE_TRUE); @@ -442,6 +455,8 @@ Datum texticnlike(PG_FUNCTION_ARGS) { text* str = PG_GETARG_TEXT_PP(0); text* pat = PG_GETARG_TEXT_PP(1); + FUNC_CHECK_HUGE_POINTER(false, str, "texticnlike()"); + bool result = false; result = (Generic_Text_IC_like(str, pat, PG_GET_COLLATION()) != LIKE_TRUE); @@ -457,6 +472,8 @@ Datum like_escape(PG_FUNCTION_ARGS) { text* pat = PG_GETARG_TEXT_PP(0); text* esc = PG_GETARG_TEXT_PP(1); + FUNC_CHECK_HUGE_POINTER(false, pat, "like_escape()"); + text* result = NULL; if (pg_database_encoding_max_length() == 1) @@ -475,6 +492,8 @@ Datum like_escape_bytea(PG_FUNCTION_ARGS) { bytea* pat = PG_GETARG_BYTEA_PP(0); bytea* esc = PG_GETARG_BYTEA_PP(1); + FUNC_CHECK_HUGE_POINTER(false, pat, "like_escape_bytea()"); + bytea* result = SB_do_like_escape((text*)pat, (text*)esc); PG_RETURN_BYTEA_P((bytea*)result); diff --git a/src/common/backend/utils/adt/nlssort.cpp b/src/common/backend/utils/adt/nlssort.cpp index 5358be459..a0ddfb22f 100644 --- a/src/common/backend/utils/adt/nlssort.cpp +++ b/src/common/backend/utils/adt/nlssort.cpp @@ -62,6 +62,8 @@ Datum nlssort(PG_FUNCTION_ARGS) PG_RETURN_NULL(); } + FUNC_CHECK_HUGE_POINTER(PG_ARGISNULL(0), PG_GETARG_TEXT_P(0), "nlssort()"); + nlssort_arg = text_to_cstring(PG_GETARG_TEXT_P(1)); if (check_nlssort_args(nlssort_arg, &sort_method)) { /* the first argument is null or "" */ diff --git a/src/common/backend/utils/adt/regexp.cpp b/src/common/backend/utils/adt/regexp.cpp index f1825a567..6f4762fb0 100644 --- a/src/common/backend/utils/adt/regexp.cpp +++ b/src/common/backend/utils/adt/regexp.cpp @@ -598,6 +598,8 @@ Datum regexp_replace(PG_FUNCTION_ARGS) if (pattern == NULL) PG_RETURN_TEXT_P(src); + + FUNC_CHECK_HUGE_POINTER(false, src, "to_txvector()"); re = RE_compile_and_cache(pattern, re_flags.cflags, PG_GET_COLLATION()); result = replace_text_regexp(src, (void*)re, r, position, occurrence); @@ -880,6 +882,8 @@ Datum regexp_count(PG_FUNCTION_ARGS) PG_RETURN_NULL(); } + FUNC_CHECK_HUGE_POINTER(false, src, "regexp_count()"); + re_flags.glob = true; regexp_matches_ctx* matchctx = setup_regexp_matches(src, pattern, &re_flags, PG_GET_COLLATION(), false, false, position - 1); @@ -1040,6 +1044,8 @@ Datum regexp_matches(PG_FUNCTION_ARGS) FuncCallContext* funcctx = NULL; regexp_matches_ctx* matchctx = NULL; + FUNC_CHECK_HUGE_POINTER(PG_ARGISNULL(0), PG_GETARG_TEXT_PP(0), "regexp_matches()"); + if (SRF_IS_FIRSTCALL()) { text* pattern = PG_GETARG_TEXT_PP(1); text* flags = PG_GETARG_TEXT_PP_IF_EXISTS(2); @@ -1278,6 +1284,8 @@ Datum regexp_split_to_table(PG_FUNCTION_ARGS) FuncCallContext* funcctx = NULL; regexp_matches_ctx* splitctx = NULL; + FUNC_CHECK_HUGE_POINTER(PG_ARGISNULL(0), PG_GETARG_TEXT_PP(0), "regexp_split_to_table()"); + if (SRF_IS_FIRSTCALL()) { text* pattern = PG_GETARG_TEXT_PP(1); text* flags = PG_GETARG_TEXT_PP_IF_EXISTS(2); @@ -1341,6 +1349,8 @@ Datum regexp_split_to_array(PG_FUNCTION_ARGS) text* flags = PG_GETARG_TEXT_PP_IF_EXISTS(2); pg_re_flags re_flags; + FUNC_CHECK_HUGE_POINTER(PG_ARGISNULL(0), PG_GETARG_TEXT_PP(0), "regexp_split_to_array()"); + /* Determine options */ parse_re_flags(&re_flags, flags); /* User mustn't specify 'g' */ diff --git a/src/common/backend/utils/adt/varchar.cpp b/src/common/backend/utils/adt/varchar.cpp index 998602bd6..d6405f642 100644 --- a/src/common/backend/utils/adt/varchar.cpp +++ b/src/common/backend/utils/adt/varchar.cpp @@ -705,6 +705,8 @@ Datum bpcharoctetlen(PG_FUNCTION_ARGS) { Datum arg = PG_GETARG_DATUM(0); + FUNC_CHECK_HUGE_POINTER(PG_ARGISNULL(0), DatumGetPointer(arg), "bpcharoctetlen()"); + /* We need not detoast the input at all */ PG_RETURN_INT32(toast_raw_datum_size(arg) - VARHDRSZ); } diff --git a/src/common/backend/utils/adt/varlena.cpp b/src/common/backend/utils/adt/varlena.cpp index 64378b723..3d5c48aab 100644 --- a/src/common/backend/utils/adt/varlena.cpp +++ b/src/common/backend/utils/adt/varlena.cpp @@ -213,6 +213,7 @@ char* text_to_cstring(const text* t) ereport(ERROR, (errcode(ERRCODE_UNEXPECTED_NULL_VALUE), errmsg("invalid null pointer input for text_to_cstring()"))); } + FUNC_CHECK_HUGE_POINTER(false, t, "text_to_cstring()"); /* must cast away the const, unfortunately */ text* tunpacked = pg_detoast_datum_packed((struct varlena*)t); @@ -245,6 +246,9 @@ char* text_to_cstring(const text* t) void text_to_cstring_buffer(const text* src, char* dst, size_t dst_len) { /* must cast away the const, unfortunately */ + + FUNC_CHECK_HUGE_POINTER((src == NULL), src, "text_to_cstring_buffer()"); + text* srcunpacked = pg_detoast_datum_packed((struct varlena*)src); size_t src_len = VARSIZE_ANY_EXHDR(srcunpacked); @@ -499,6 +503,8 @@ Datum rawout(PG_FUNCTION_ARGS) Datum rawtotext(PG_FUNCTION_ARGS) { Datum arg1 = PG_GETARG_DATUM(0); + + FUNC_CHECK_HUGE_POINTER(PG_ARGISNULL(0), DatumGetPointer(arg1), "rawtotext()"); Datum cstring_result; Datum result; @@ -513,10 +519,8 @@ Datum rawtotext(PG_FUNCTION_ARGS) Datum texttoraw(PG_FUNCTION_ARGS) { Datum arg1 = PG_GETARG_DATUM(0); - if (VARATT_IS_HUGE_TOAST_POINTER(DatumGetPointer(arg1))) { - ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("texttoraw could not support more than 1GB clob/blob data"))); - } + + FUNC_CHECK_HUGE_POINTER(PG_ARGISNULL(0), DatumGetPointer(arg1), "rawtotext()"); Datum result; Datum cstring_arg1; @@ -621,7 +625,6 @@ Datum bytea_string_agg_finalfn(PG_FUNCTION_ARGS) Datum textin(PG_FUNCTION_ARGS) { char* inputText = PG_GETARG_CSTRING(0); - PG_RETURN_TEXT_P(cstring_to_text(inputText)); } @@ -791,6 +794,8 @@ Datum textoctetlen(PG_FUNCTION_ARGS) { Datum str = PG_GETARG_DATUM(0); + FUNC_CHECK_HUGE_POINTER(PG_ARGISNULL(0), DatumGetPointer(str), "textoctetlen()"); + /* We need not detoast the input at all */ PG_RETURN_INT32(toast_raw_datum_size(str) - VARHDRSZ); } @@ -1270,11 +1275,7 @@ Datum text_substr_orclcompat(PG_FUNCTION_ARGS) mblen_converter fun_mblen; fun_mblen = *pg_wchar_table[GetDatabaseEncoding()].mblen; - if (VARATT_IS_HUGE_TOAST_POINTER((varlena *)DatumGetPointer(str))) { - struct varlena* dest_ptr = (struct varlena*)DatumGetPointer(str); - struct varlena* res_ptr = heap_tuple_untoast_attr_slice(dest_ptr, start, length); - return PointerGetDatum(res_ptr); - } + FUNC_CHECK_HUGE_POINTER(PG_ARGISNULL(0), DatumGetPointer(str), "text_substr()"); is_compress = (VARATT_IS_COMPRESSED(DatumGetPointer(str)) || VARATT_IS_EXTERNAL(DatumGetPointer(str))); // orclcompat is true, withlen is true @@ -1303,10 +1304,7 @@ Datum text_substr_no_len_orclcompat(PG_FUNCTION_ARGS) mblen_converter fun_mblen; fun_mblen = *pg_wchar_table[GetDatabaseEncoding()].mblen; - if (VARATT_IS_HUGE_TOAST_POINTER((varlena *)DatumGetPointer(str))) { - ereport(ERROR, (errcode(ERRCODE_UNRECOGNIZED_NODE_TYPE), - errmsg("The data is lob that larger than 1GB, you must use a substr with len(substr(str, start, len))"))); - } + FUNC_CHECK_HUGE_POINTER(PG_ARGISNULL(0), DatumGetPointer(str), "text_substr()"); is_compress = (VARATT_IS_COMPRESSED(DatumGetPointer(str)) || VARATT_IS_EXTERNAL(DatumGetPointer(str))); // orclcompat is true, withlen is false @@ -1331,6 +1329,8 @@ Datum textoverlay(PG_FUNCTION_ARGS) { text* t1 = PG_GETARG_TEXT_PP(0); text* t2 = PG_GETARG_TEXT_PP(1); + + FUNC_CHECK_HUGE_POINTER(false, t1, "textoverlay()"); int sp = PG_GETARG_INT32(2); /* substring start position */ int sl = PG_GETARG_INT32(3); /* substring length */ @@ -1341,6 +1341,7 @@ Datum textoverlay_no_len(PG_FUNCTION_ARGS) { text* t1 = PG_GETARG_TEXT_PP(0); text* t2 = PG_GETARG_TEXT_PP(1); + FUNC_CHECK_HUGE_POINTER(false, t1, "textoverlay()"); int sp = PG_GETARG_INT32(2); /* substring start position */ int sl; @@ -1384,6 +1385,7 @@ Datum textpos(PG_FUNCTION_ARGS) { text* str = PG_GETARG_TEXT_PP(0); text* search_str = PG_GETARG_TEXT_PP(1); + FUNC_CHECK_HUGE_POINTER(PG_ARGISNULL(0), str, "textpos()"); PG_RETURN_INT32((int32)text_position(str, search_str)); } @@ -1864,7 +1866,8 @@ Datum texteq(PG_FUNCTION_ARGS) { Datum arg1 = PG_GETARG_DATUM(0); Datum arg2 = PG_GETARG_DATUM(1); - if (VARATT_IS_HUGE_TOAST_POINTER(DatumGetPointer(arg1)) && VARATT_IS_HUGE_TOAST_POINTER(DatumGetPointer(arg2))) { + + if (VARATT_IS_HUGE_TOAST_POINTER(DatumGetPointer(arg1)) || VARATT_IS_HUGE_TOAST_POINTER(DatumGetPointer(arg2))) { ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("texteq could not support more than 1GB clob/blob data"))); } @@ -1899,7 +1902,7 @@ Datum textne(PG_FUNCTION_ARGS) { Datum arg1 = PG_GETARG_DATUM(0); Datum arg2 = PG_GETARG_DATUM(1); - if (VARATT_IS_HUGE_TOAST_POINTER(DatumGetPointer(arg1)) && VARATT_IS_HUGE_TOAST_POINTER(DatumGetPointer(arg2))) { + if (VARATT_IS_HUGE_TOAST_POINTER(DatumGetPointer(arg1)) || VARATT_IS_HUGE_TOAST_POINTER(DatumGetPointer(arg2))) { ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("textne could not support more than 1GB clob/blob data"))); } @@ -2009,10 +2012,7 @@ Datum text_lt(PG_FUNCTION_ARGS) { text* arg1 = PG_GETARG_TEXT_PP(0); text* arg2 = PG_GETARG_TEXT_PP(1); - if (VARATT_IS_HUGE_TOAST_POINTER((varlena *)arg1) || VARATT_IS_HUGE_TOAST_POINTER((varlena *)arg2)) { - ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("text_lt could not support more than 1GB clob/blob data"))); - } + FUNC_CHECK_HUGE_POINTER(false, arg1, "text_lt()"); bool result = false; result = (text_cmp(arg1, arg2, PG_GET_COLLATION()) < 0); @@ -2027,10 +2027,8 @@ Datum text_le(PG_FUNCTION_ARGS) { text* arg1 = PG_GETARG_TEXT_PP(0); text* arg2 = PG_GETARG_TEXT_PP(1); - if (VARATT_IS_HUGE_TOAST_POINTER((varlena *)arg1) || VARATT_IS_HUGE_TOAST_POINTER((varlena *)arg2)) { - ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("text_le could not support more than 1GB clob/blob data"))); - } + FUNC_CHECK_HUGE_POINTER(false, arg1, "text_le()"); + bool result = false; result = (text_cmp(arg1, arg2, PG_GET_COLLATION()) <= 0); @@ -2045,10 +2043,8 @@ Datum text_gt(PG_FUNCTION_ARGS) { text* arg1 = PG_GETARG_TEXT_PP(0); text* arg2 = PG_GETARG_TEXT_PP(1); - if (VARATT_IS_HUGE_TOAST_POINTER((varlena *)arg1) || VARATT_IS_HUGE_TOAST_POINTER((varlena *)arg2)) { - ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("text_gt could not support more than 1GB clob/blob data"))); - } + FUNC_CHECK_HUGE_POINTER(false, arg1, "text_gt()"); + bool result = false; result = (text_cmp(arg1, arg2, PG_GET_COLLATION()) > 0); @@ -2063,10 +2059,8 @@ Datum text_ge(PG_FUNCTION_ARGS) { text* arg1 = PG_GETARG_TEXT_PP(0); text* arg2 = PG_GETARG_TEXT_PP(1); - if (VARATT_IS_HUGE_TOAST_POINTER((varlena *)arg1) && VARATT_IS_HUGE_TOAST_POINTER((varlena *)arg2)) { - ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("text_ge could not support more than 1GB clob/blob data"))); - } + FUNC_CHECK_HUGE_POINTER(false, arg1, "text_ge()"); + bool result = false; result = (text_cmp(arg1, arg2, PG_GET_COLLATION()) >= 0); @@ -2081,10 +2075,8 @@ Datum bttextcmp(PG_FUNCTION_ARGS) { text* arg1 = PG_GETARG_TEXT_PP(0); text* arg2 = PG_GETARG_TEXT_PP(1); - if (VARATT_IS_HUGE_TOAST_POINTER((varlena *)arg1) || VARATT_IS_HUGE_TOAST_POINTER((varlena *)arg2)) { - ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("bttextcmp could not support more than 1GB clob/blob data"))); - } + FUNC_CHECK_HUGE_POINTER(false, arg1, "bttextcmp()"); + int32 result; result = text_cmp(arg1, arg2, PG_GET_COLLATION()); @@ -2789,10 +2781,7 @@ Datum text_larger(PG_FUNCTION_ARGS) { text* arg1 = PG_GETARG_TEXT_PP(0); text* arg2 = PG_GETARG_TEXT_PP(1); - if (VARATT_IS_HUGE_TOAST_POINTER((varlena *)arg1) || VARATT_IS_HUGE_TOAST_POINTER((varlena *)arg2)) { - ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("text_larger could not support more than 1GB clob/blob data"))); - } + FUNC_CHECK_HUGE_POINTER(false, arg1, "text_larger()"); text* result = NULL; result = ((text_cmp(arg1, arg2, PG_GET_COLLATION()) > 0) ? arg1 : arg2); @@ -2804,10 +2793,7 @@ Datum text_smaller(PG_FUNCTION_ARGS) { text* arg1 = PG_GETARG_TEXT_PP(0); text* arg2 = PG_GETARG_TEXT_PP(1); - if (VARATT_IS_HUGE_TOAST_POINTER((varlena *)arg1) || VARATT_IS_HUGE_TOAST_POINTER((varlena *)arg2)) { - ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("text_smaller could not support more than 1GB clob/blob data"))); - } + FUNC_CHECK_HUGE_POINTER(false, arg1, "text_smaller()"); text* result = NULL; result = ((text_cmp(arg1, arg2, PG_GET_COLLATION()) < 0) ? arg1 : arg2); @@ -2845,10 +2831,8 @@ Datum text_pattern_lt(PG_FUNCTION_ARGS) { text* arg1 = PG_GETARG_TEXT_PP(0); text* arg2 = PG_GETARG_TEXT_PP(1); - if (VARATT_IS_HUGE_TOAST_POINTER((varlena *)arg1) || VARATT_IS_HUGE_TOAST_POINTER((varlena *)arg2)) { - ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("text_pattern_lt could not support more than 1GB clob/blob data"))); - } + + FUNC_CHECK_HUGE_POINTER(false, arg1, "text_pattern()"); int result; result = internal_text_pattern_compare(arg1, arg2); @@ -2863,10 +2847,8 @@ Datum text_pattern_le(PG_FUNCTION_ARGS) { text* arg1 = PG_GETARG_TEXT_PP(0); text* arg2 = PG_GETARG_TEXT_PP(1); - if (VARATT_IS_HUGE_TOAST_POINTER((varlena *)arg1) || VARATT_IS_HUGE_TOAST_POINTER((varlena *)arg2)) { - ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("text_pattern_le could not support more than 1GB clob/blob data"))); - } + + FUNC_CHECK_HUGE_POINTER(false, arg1, "text_pattern()"); int result; result = internal_text_pattern_compare(arg1, arg2); @@ -2881,10 +2863,8 @@ Datum text_pattern_ge(PG_FUNCTION_ARGS) { text* arg1 = PG_GETARG_TEXT_PP(0); text* arg2 = PG_GETARG_TEXT_PP(1); - if (VARATT_IS_HUGE_TOAST_POINTER((varlena *)arg1) || VARATT_IS_HUGE_TOAST_POINTER((varlena *)arg2)) { - ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("text_pattern_ge could not support more than 1GB clob/blob data"))); - } + FUNC_CHECK_HUGE_POINTER(false, arg1, "text_pattern()"); + int result; result = internal_text_pattern_compare(arg1, arg2); @@ -2899,10 +2879,8 @@ Datum text_pattern_gt(PG_FUNCTION_ARGS) { text* arg1 = PG_GETARG_TEXT_PP(0); text* arg2 = PG_GETARG_TEXT_PP(1); - if (VARATT_IS_HUGE_TOAST_POINTER((varlena *)arg1) || VARATT_IS_HUGE_TOAST_POINTER((varlena *)arg2)) { - ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("text_pattern_gt could not support more than 1GB clob/blob data"))); - } + FUNC_CHECK_HUGE_POINTER(false, arg1, "text_pattern()"); + int result; result = internal_text_pattern_compare(arg1, arg2); @@ -2917,10 +2895,8 @@ Datum bttext_pattern_cmp(PG_FUNCTION_ARGS) { text* arg1 = PG_GETARG_TEXT_PP(0); text* arg2 = PG_GETARG_TEXT_PP(1); - if (VARATT_IS_HUGE_TOAST_POINTER((varlena *)arg1) || VARATT_IS_HUGE_TOAST_POINTER((varlena *)arg2)) { - ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("bttext_pattern_cmp could not support more than 1GB clob/blob data"))); - } + FUNC_CHECK_HUGE_POINTER(false, arg1, "btext_pattern()"); + int result; result = internal_text_pattern_compare(arg1, arg2); @@ -2941,6 +2917,8 @@ Datum byteaoctetlen(PG_FUNCTION_ARGS) { Datum str = PG_GETARG_DATUM(0); + FUNC_CHECK_HUGE_POINTER(PG_ARGISNULL(0), PG_GETARG_TEXT_PP(0), "byteaoctetlen()"); + /* We need not detoast the input at all */ PG_RETURN_INT32(toast_raw_datum_size(str) - VARHDRSZ); } @@ -3747,7 +3725,6 @@ Datum byteaeq(PG_FUNCTION_ARGS) Datum arg2 = PG_GETARG_DATUM(1); bool result = false; Size len1, len2; - /* * We can use a fast path for unequal lengths, which might save us from * having to detoast one or both values. @@ -3776,6 +3753,8 @@ Datum byteane(PG_FUNCTION_ARGS) bool result = false; Size len1, len2; + FUNC_CHECK_HUGE_POINTER(PG_ARGISNULL(0), DatumGetPointer(arg1), "byteane()"); + /* * We can use a fast path for unequal lengths, which might save us from * having to detoast one or both values. @@ -3801,6 +3780,8 @@ Datum bytealt(PG_FUNCTION_ARGS) { bytea* arg1 = PG_GETARG_BYTEA_PP(0); bytea* arg2 = PG_GETARG_BYTEA_PP(1); + + FUNC_CHECK_HUGE_POINTER(false, arg1, "bytealt()"); int len1, len2; int cmp; @@ -3822,6 +3803,8 @@ Datum byteale(PG_FUNCTION_ARGS) int len1, len2; int cmp; + FUNC_CHECK_HUGE_POINTER(false, arg1, "bytealt()"); + len1 = VARSIZE_ANY_EXHDR(arg1); len2 = VARSIZE_ANY_EXHDR(arg2); @@ -3839,6 +3822,7 @@ Datum byteagt(PG_FUNCTION_ARGS) bytea* arg2 = PG_GETARG_BYTEA_PP(1); int len1, len2; int cmp; + FUNC_CHECK_HUGE_POINTER(false, arg1, "byteagt()"); len1 = VARSIZE_ANY_EXHDR(arg1); len2 = VARSIZE_ANY_EXHDR(arg2); @@ -3857,6 +3841,7 @@ Datum byteage(PG_FUNCTION_ARGS) bytea* arg2 = PG_GETARG_BYTEA_PP(1); int len1, len2; int cmp; + FUNC_CHECK_HUGE_POINTER(false, arg1, "bytealt()"); len1 = VARSIZE_ANY_EXHDR(arg1); len2 = VARSIZE_ANY_EXHDR(arg2); @@ -3873,6 +3858,7 @@ Datum byteacmp(PG_FUNCTION_ARGS) { bytea* arg1 = PG_GETARG_BYTEA_PP(0); bytea* arg2 = PG_GETARG_BYTEA_PP(1); + FUNC_CHECK_HUGE_POINTER(false, arg1, "byteacmp()"); int len1, len2; int cmp; @@ -3911,6 +3897,8 @@ Datum raweq(PG_FUNCTION_ARGS) int len1, len2; bool result = false; + FUNC_CHECK_HUGE_POINTER(PG_ARGISNULL(0), arg1, "raweq()"); + len1 = VARSIZE_ANY_EXHDR(arg1); len2 = VARSIZE_ANY_EXHDR(arg2); @@ -3932,6 +3920,7 @@ Datum rawne(PG_FUNCTION_ARGS) bytea* arg2 = PG_GETARG_BYTEA_PP(1); int len1, len2; bool result = false; + FUNC_CHECK_HUGE_POINTER(false, arg1, "rawne()"); len1 = VARSIZE_ANY_EXHDR(arg1); len2 = VARSIZE_ANY_EXHDR(arg2); @@ -3954,6 +3943,7 @@ Datum rawlt(PG_FUNCTION_ARGS) bytea* arg2 = PG_GETARG_BYTEA_PP(1); int len1, len2; int cmp; + FUNC_CHECK_HUGE_POINTER(false, arg1, "rawlt()"); len1 = VARSIZE_ANY_EXHDR(arg1); len2 = VARSIZE_ANY_EXHDR(arg2); @@ -3972,6 +3962,7 @@ Datum rawle(PG_FUNCTION_ARGS) bytea* arg2 = PG_GETARG_BYTEA_PP(1); int len1, len2; int cmp; + FUNC_CHECK_HUGE_POINTER(false, arg1, "rawle()"); len1 = VARSIZE_ANY_EXHDR(arg1); len2 = VARSIZE_ANY_EXHDR(arg2); @@ -3990,6 +3981,7 @@ Datum rawgt(PG_FUNCTION_ARGS) bytea* arg2 = PG_GETARG_BYTEA_PP(1); int len1, len2; int cmp; + FUNC_CHECK_HUGE_POINTER(false, arg1, "rawgt()"); len1 = VARSIZE_ANY_EXHDR(arg1); len2 = VARSIZE_ANY_EXHDR(arg2); @@ -4008,6 +4000,7 @@ Datum rawge(PG_FUNCTION_ARGS) bytea* arg2 = PG_GETARG_BYTEA_PP(1); int len1, len2; int cmp; + FUNC_CHECK_HUGE_POINTER(false, arg1, "rawge()"); len1 = VARSIZE_ANY_EXHDR(arg1); len2 = VARSIZE_ANY_EXHDR(arg2); @@ -4026,6 +4019,7 @@ Datum rawcmp(PG_FUNCTION_ARGS) bytea* arg2 = PG_GETARG_BYTEA_PP(1); int len1, len2; int cmp; + FUNC_CHECK_HUGE_POINTER(false, arg1, "rawcmp()"); len1 = VARSIZE_ANY_EXHDR(arg1); len2 = VARSIZE_ANY_EXHDR(arg2); diff --git a/src/common/backend/utils/mb/mbutils.cpp b/src/common/backend/utils/mb/mbutils.cpp index c204fd0d1..1c386f89b 100644 --- a/src/common/backend/utils/mb/mbutils.cpp +++ b/src/common/backend/utils/mb/mbutils.cpp @@ -349,6 +349,7 @@ Datum pg_convert_to_nocase(PG_FUNCTION_ARGS) Datum dest_encoding_name = PG_GETARG_DATUM(1); Datum src_encoding_name = DirectFunctionCall1(namein, CStringGetDatum(u_sess->mb_cxt.DatabaseEncoding->name)); Datum result; + FUNC_CHECK_HUGE_POINTER(PG_ARGISNULL(0), DatumGetPointer(string), "pg_convert()"); /* * pg_convert expects a bytea as its first argument. We're passing it a diff --git a/src/common/pl/plpgsql/src/pl_exec.cpp b/src/common/pl/plpgsql/src/pl_exec.cpp index a7699c812..ca84ee556 100644 --- a/src/common/pl/plpgsql/src/pl_exec.cpp +++ b/src/common/pl/plpgsql/src/pl_exec.cpp @@ -6086,10 +6086,6 @@ static int exec_stmt_dynexecute(PLpgSQL_execstate* estate, PLpgSQL_stmt_dynexecu } plpgsql_estate = estate; -#ifndef ENABLE_MULTIPLE_NODES - t_thrd.xact_cxt.isSelectInto = stmt->into; -#endif - /* * Execute the query without preparing a saved plan. @@ -6142,7 +6138,6 @@ static int exec_stmt_dynexecute(PLpgSQL_execstate* estate, PLpgSQL_stmt_dynexecu estate->cursor_return_data = saved_cursor_data; estate->cursor_return_numbers = saved_cursor_numbers; - t_thrd.xact_cxt.isSelectInto = false; return PLPGSQL_RC_OK; } diff --git a/src/gausskernel/runtime/executor/execQual.cpp b/src/gausskernel/runtime/executor/execQual.cpp index 4bbfd3156..f6783ca9f 100644 --- a/src/gausskernel/runtime/executor/execQual.cpp +++ b/src/gausskernel/runtime/executor/execQual.cpp @@ -6157,17 +6157,19 @@ static bool ExecTargetList(List* targetlist, ExprContext* econtext, Datum* value isClobAndNotNull = (IsA(tle->expr, Param)) && (!isnull[resind]) && (((Param*)tle->expr)->paramtype == CLOBOID || ((Param*)tle->expr)->paramtype == BLOBOID); if (isClobAndNotNull) { - /* if type is lob pointer, we should fetch real value from tuple. */ - if (VARATT_IS_EXTERNAL_LOB(values[resind])) { - struct varatt_lob_pointer* lob_pointer = (varatt_lob_pointer*)(VARDATA_EXTERNAL(values[resind])); - bool is_null = false; + /* if is big lob, fetch and copy from toast */ + if (VARATT_IS_HUGE_TOAST_POINTER(values[resind])) { + Datum new_attr = (Datum)0; Oid update_oid = econtext->ecxt_scantuple != NULL ? ((HeapTuple)(econtext->ecxt_scantuple->tts_tuple))->t_tableOid : InvalidOid; - values[resind] = fetch_lob_value_from_tuple(lob_pointer, update_oid, &is_null); - isnull[resind] = is_null; + Relation update_rel = heap_open(update_oid, RowExclusiveLock); + struct varlena *old_value = (struct varlena *)DatumGetPointer(values[resind]); + struct varlena *new_value = heap_tuple_fetch_and_copy(update_rel, old_value,true); + new_attr = PointerGetDatum(new_value); + heap_close(update_rel, NoLock); + values[resind] = new_attr; } } - ELOG_FIELD_NAME_END; if (itemIsDone[resind] != ExprSingleResult) { @@ -6314,9 +6316,6 @@ TupleTableSlot* ExecProject(ProjectionInfo* projInfo, ExprDoneCond* isDone) if (numSimpleVars > 0) { Datum* values = slot->tts_values; bool* isnull = slot->tts_isnull; -#ifndef ENABLE_MULTIPLE_NODES - Datum* lobPointers = slot->tts_lobPointers; -#endif int* varSlotOffsets = projInfo->pi_varSlotOffsets; int* varNumbers = projInfo->pi_varNumbers; int i; @@ -6330,26 +6329,7 @@ TupleTableSlot* ExecProject(ProjectionInfo* projInfo, ExprDoneCond* isDone) Assert (varNumber < varSlot->tts_tupleDescriptor->natts); Assert (i < slot->tts_tupleDescriptor->natts); -#ifndef ENABLE_MULTIPLE_NODES - Form_pg_attribute attr = varSlot->tts_tupleDescriptor->attrs[varNumber]; - if (t_thrd.xact_cxt.isSelectInto && (attr->atttypid == CLOBOID || attr->atttypid == BLOBOID)) { - struct varlena *toast_pointer_lob = NULL; - toast_pointer_lob = toast_pointer_fetch_data(varSlot, attr, varNumber); - Assert(toast_pointer_lob != NULL); - if (!projInfo->pi_topPlan) { - values[i] = varSlot->tts_values[varNumber]; - lobPointers[i] = PointerGetDatum(toast_pointer_lob); - } else { - values[i] = PointerGetDatum(toast_pointer_lob); - lobPointers[i] = (Datum)0; - } - } else { - values[i] = varSlot->tts_values[varNumber]; - lobPointers[i] = (Datum)0; - } -#else values[i] = varSlot->tts_values[varNumber]; -#endif isnull[i] = varSlot->tts_isnull[varNumber]; } } else { diff --git a/src/include/postgres.h b/src/include/postgres.h index b0aebcdf6..af42226e0 100644 --- a/src/include/postgres.h +++ b/src/include/postgres.h @@ -323,6 +323,16 @@ typedef enum { #define VARATT_IS_1B_E(PTR) ((((varattrib_1b*)(PTR))->va_header) == 0x80) #define VARATT_IS_HUGE_TOAST_POINTER(PTR) ((((varattrib_1b*)(PTR))->va_header) == 0x80 && \ ((((varattrib_1b_e*)(PTR))->va_tag) & 0x01) == 0x01) + +#define FUNC_CHECK_HUGE_POINTER(is_null, ptr, funcName) \ + do { \ + if (!is_null && unlikely(VARATT_IS_HUGE_TOAST_POINTER((varlena *)ptr))) { \ + ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), \ + errmsg("%s could not support larger than 1GB clob/blob data", funcName), \ + errcause("parameter larger than 1GB"), erraction("parameter must less than 1GB"))); \ + } \ + } while (0) + #define VARATT_NOT_PAD_BYTE(PTR) (*((uint8*)(PTR)) != 0) /* VARSIZE_4B() should only be used on known-aligned data */ @@ -345,6 +355,16 @@ typedef enum { #define VARATT_IS_1B_E(PTR) ((((varattrib_1b*)(PTR))->va_header) == 0x01) #define VARATT_IS_HUGE_TOAST_POINTER(PTR) ((((varattrib_1b*)(PTR))->va_header) == 0x01 && \ ((((varattrib_1b_e*)(PTR))->va_tag) >> 7) == 0x01) + +#define FUNC_CHECK_HUGE_POINTER(is_null, ptr, funcName) \ + do { \ + if (!is_null && VARATT_IS_HUGE_TOAST_POINTER((varlena *)ptr)) { \ + ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), \ + errmsg("%s could not support larger than 1GB clob/blob data", funcName), \ + errcause("parameter larger than 1GB"), erraction("parameter must less than 1GB"))); \ + } \ + } while (0) + #define VARATT_NOT_PAD_BYTE(PTR) (*((uint8*)(PTR)) != 0) /* VARSIZE_4B() should only be used on known-aligned data */