forked from huawei/openGauss-server
fix clob > 1G unspport error
Offering: openGaussDev More detail:fix clob > 1G unspport error Match-id-f3aa081fe8c987e3f540d857a091175c5d28c690
This commit is contained in:
parent
6d95c39328
commit
f602677e45
|
@ -4596,16 +4596,10 @@ static int exec_stmt_return(PLpgSQL_execstate* estate, PLpgSQL_stmt_return* stmt
|
|||
case PLPGSQL_DTYPE_VAR: {
|
||||
PLpgSQL_var* var = (PLpgSQL_var*)retvar;
|
||||
Datum value = var->value;
|
||||
if (is_external_clob(var->datatype->typoid, var->isnull, value)) {
|
||||
bool is_null = false;
|
||||
bool is_have_huge_clob = false;
|
||||
struct varatt_lob_pointer* lob_pointer = (varatt_lob_pointer*)(VARDATA_EXTERNAL(value));
|
||||
value = fetch_lob_value_from_tuple(lob_pointer, InvalidOid, &is_null, &is_have_huge_clob);
|
||||
if (is_have_huge_clob) {
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("huge clob do not support as return parameter")));
|
||||
}
|
||||
if (is_huge_clob(var->datatype->typoid, var->isnull, value)) {
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("huge clob do not support as return parameter")));
|
||||
}
|
||||
if (need_param_seperation) {
|
||||
estate->paramval = value;
|
||||
|
@ -7423,16 +7417,10 @@ void exec_assign_value(PLpgSQL_execstate* estate, PLpgSQL_datum* target, Datum v
|
|||
MemoryContext oldcontext = NULL;
|
||||
AttrNumber attrno = ((PLpgSQL_arrayelem*)target)->assignattrno;
|
||||
|
||||
if (is_external_clob(valtype, *isNull, value)) {
|
||||
bool is_null = false;
|
||||
bool is_have_huge_clob = false;
|
||||
struct varatt_lob_pointer* lob_pointer = (varatt_lob_pointer*)(VARDATA_EXTERNAL(value));
|
||||
value = fetch_lob_value_from_tuple(lob_pointer, InvalidOid, &is_null, &is_have_huge_clob);
|
||||
if (is_have_huge_clob) {
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("huge clob do not support as array element.")));
|
||||
}
|
||||
if (is_huge_clob(valtype, *isNull, value)) {
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("huge clob do not support as array element.")));
|
||||
}
|
||||
/*
|
||||
* We need to do subscript evaluation, which might require
|
||||
|
@ -7711,16 +7699,10 @@ void exec_assign_value(PLpgSQL_execstate* estate, PLpgSQL_datum* target, Datum v
|
|||
MemoryContext oldcontext = NULL;
|
||||
AttrNumber attrno = ((PLpgSQL_tableelem*)target)->assignattrno;
|
||||
|
||||
if (is_external_clob(valtype, *isNull, value)) {
|
||||
bool is_null = false;
|
||||
bool is_have_huge_clob = false;
|
||||
struct varatt_lob_pointer* lob_pointer = (varatt_lob_pointer*)(VARDATA_EXTERNAL(value));
|
||||
value = fetch_lob_value_from_tuple(lob_pointer, InvalidOid, &is_null, &is_have_huge_clob);
|
||||
if (is_have_huge_clob) {
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("huge clob do not support as table of element.")));
|
||||
}
|
||||
if (is_huge_clob(valtype, *isNull, value)) {
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("huge clob do not support as table of element.")));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -7993,12 +7975,6 @@ void exec_assign_value(PLpgSQL_execstate* estate, PLpgSQL_datum* target, Datum v
|
|||
/*
|
||||
* Target has a assign list
|
||||
*/
|
||||
if (is_external_clob(valtype, *isNull, value)) {
|
||||
bool is_null = false;
|
||||
bool is_have_huge_clob = false;
|
||||
struct varatt_lob_pointer* lob_pointer = (varatt_lob_pointer*)(VARDATA_EXTERNAL(value));
|
||||
value = fetch_lob_value_from_tuple(lob_pointer, InvalidOid, &is_null, &is_have_huge_clob);
|
||||
}
|
||||
PLpgSQL_assignlist* assignvar = (PLpgSQL_assignlist*)target;
|
||||
List* assignlist = assignvar->assignlist;
|
||||
PLpgSQL_datum* assigntarget = estate->datums[assignvar->targetno];
|
||||
|
@ -10794,17 +10770,10 @@ HeapTuple make_tuple_from_row(PLpgSQL_execstate* estate, PLpgSQL_row* row, Tuple
|
|||
exec_eval_datum(estate, estate->datums[row->varnos[i]], &fieldtypeid, &fieldtypmod, &dvalues[i], &nulls[i]);
|
||||
}
|
||||
|
||||
if (is_external_clob(fieldtypeid, nulls[i], dvalues[i])) {
|
||||
bool is_null = false;
|
||||
bool is_have_huge_clob = false;
|
||||
struct varatt_lob_pointer* lob_pointer = (varatt_lob_pointer*)(VARDATA_EXTERNAL(dvalues[i]));
|
||||
dvalues[i] = fetch_lob_value_from_tuple(lob_pointer, InvalidOid, &is_null, &is_have_huge_clob);
|
||||
if (is_have_huge_clob) {
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("huge clob do not support concat a row")));
|
||||
}
|
||||
nulls[i] = is_null;
|
||||
if (is_huge_clob(fieldtypeid, nulls[i], dvalues[i])) {
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("huge clob do not support concat a row")));
|
||||
}
|
||||
|
||||
if (estate->is_exception && fieldtypeid == REFCURSOROID) {
|
||||
|
|
|
@ -152,6 +152,7 @@ static Datum ExecEvalGroupingIdExpr(
|
|||
GroupingIdExprState* gstate, ExprContext* econtext, bool* isNull, ExprDoneCond* isDone);
|
||||
static bool func_has_refcursor_args(Oid Funcid, FunctionCallInfoData* fcinfo);
|
||||
extern struct varlena *heap_tuple_fetch_and_copy(Relation rel, struct varlena *attr, bool needcheck);
|
||||
static void check_huge_clob_paramter(FunctionCallInfoData* fcinfo, bool is_have_huge_clob);
|
||||
|
||||
THR_LOCAL PLpgSQL_execstate* plpgsql_estate = NULL;
|
||||
|
||||
|
@ -1692,6 +1693,7 @@ static ExprDoneCond ExecEvalFuncArgs(
|
|||
i = 0;
|
||||
econtext->is_cursor = false;
|
||||
u_sess->plsql_cxt.func_tableof_index = NIL;
|
||||
bool is_have_huge_clob = false;
|
||||
foreach (arg, argList) {
|
||||
ExprState* argstate = (ExprState*)lfirst(arg);
|
||||
ExprDoneCond thisArgIsDone;
|
||||
|
@ -1719,6 +1721,9 @@ static ExprDoneCond ExecEvalFuncArgs(
|
|||
}
|
||||
fcinfo->argTypes[i] = argstate->resultType;
|
||||
econtext->is_cursor = false;
|
||||
if (is_huge_clob(fcinfo->argTypes[i], fcinfo->argnull[i], fcinfo->arg[i])) {
|
||||
is_have_huge_clob = true;
|
||||
}
|
||||
|
||||
if (thisArgIsDone != ExprSingleResult) {
|
||||
/*
|
||||
|
@ -1734,6 +1739,7 @@ static ExprDoneCond ExecEvalFuncArgs(
|
|||
}
|
||||
i++;
|
||||
}
|
||||
check_huge_clob_paramter(fcinfo, is_have_huge_clob);
|
||||
|
||||
Assert(i == fcinfo->nargs);
|
||||
|
||||
|
@ -2274,6 +2280,7 @@ static Datum ExecMakeFunctionResultNoSets(
|
|||
bool savedProConfigIsSet = u_sess->SPI_cxt.is_proconfig_set;
|
||||
bool proIsProcedure = false;
|
||||
bool supportTranaction = false;
|
||||
bool is_have_huge_clob = false;
|
||||
|
||||
#ifdef ENABLE_MULTIPLE_NODES
|
||||
if (IS_PGXC_COORDINATOR && (t_thrd.proc->workingVersionNum >= STP_SUPPORT_COMMIT_ROLLBACK)) {
|
||||
|
@ -2400,6 +2407,9 @@ static Datum ExecMakeFunctionResultNoSets(
|
|||
if (has_refcursor && fcinfo->argTypes[i] == REFCURSOROID)
|
||||
econtext->is_cursor = true;
|
||||
fcinfo->arg[i] = ExecEvalExpr(argstate, econtext, &fcinfo->argnull[i], NULL);
|
||||
if (is_huge_clob(fcinfo->argTypes[i], fcinfo->argnull[i], fcinfo->arg[i])) {
|
||||
is_have_huge_clob = true;
|
||||
}
|
||||
ExecTableOfIndexInfo execTableOfIndexInfo;
|
||||
initExecTableOfIndexInfo(&execTableOfIndexInfo, econtext);
|
||||
ExecEvalParamExternTableOfIndex((Node*)argstate->expr, &execTableOfIndexInfo);
|
||||
|
@ -2452,6 +2462,7 @@ static Datum ExecMakeFunctionResultNoSets(
|
|||
pgstat_init_function_usage(fcinfo, &fcusage);
|
||||
|
||||
fcinfo->isnull = false;
|
||||
check_huge_clob_paramter(fcinfo, is_have_huge_clob);
|
||||
if (u_sess->instr_cxt.global_instr != NULL && fcinfo->flinfo->fn_addr == plpgsql_call_handler) {
|
||||
StreamInstrumentation* save_global_instr = u_sess->instr_cxt.global_instr;
|
||||
u_sess->instr_cxt.global_instr = NULL;
|
||||
|
@ -5991,6 +6002,21 @@ static HeapTuple get_tuple(Relation relation, ItemPointer tid)
|
|||
return new_tuple;
|
||||
}
|
||||
|
||||
static void check_huge_clob_paramter(FunctionCallInfoData* fcinfo, bool is_have_huge_clob)
|
||||
{
|
||||
if (!is_have_huge_clob || IsSystemObjOid(fcinfo->flinfo->fn_oid)) {
|
||||
return;
|
||||
}
|
||||
Oid schema_oid = get_func_namespace(fcinfo->flinfo->fn_oid);
|
||||
if (IsPackageSchemaOid(schema_oid)) {
|
||||
return;
|
||||
}
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
errmsg("huge clob do not support as function in parameter")));
|
||||
}
|
||||
|
||||
|
||||
bool is_external_clob(Oid type_oid, bool is_null, Datum value)
|
||||
{
|
||||
if (type_oid == CLOBOID && !is_null && VARATT_IS_EXTERNAL_LOB(value)) {
|
||||
|
@ -5999,7 +6025,37 @@ bool is_external_clob(Oid type_oid, bool is_null, Datum value)
|
|||
return false;
|
||||
}
|
||||
|
||||
Datum fetch_lob_value_from_tuple(varatt_lob_pointer* lob_pointer, Oid update_oid, bool* is_null, bool* is_huge_clob)
|
||||
bool is_huge_clob(Oid type_oid, bool is_null, Datum value)
|
||||
{
|
||||
if (!is_external_clob(type_oid, is_null, value)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
struct varatt_lob_pointer* lob_pointer = (varatt_lob_pointer*)(VARDATA_EXTERNAL(value));
|
||||
bool is_huge_clob = false;
|
||||
/* get relation by relid */
|
||||
ItemPointerData tuple_ctid;
|
||||
tuple_ctid.ip_blkid.bi_hi = lob_pointer->bi_hi;
|
||||
tuple_ctid.ip_blkid.bi_lo = lob_pointer->bi_lo;
|
||||
tuple_ctid.ip_posid = lob_pointer->ip_posid;
|
||||
Relation relation = heap_open(lob_pointer->relid, RowExclusiveLock);
|
||||
HeapTuple origin_tuple = get_tuple(relation, &tuple_ctid);
|
||||
if (!HeapTupleIsValid(origin_tuple)) {
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_CACHE_LOOKUP_FAILED),
|
||||
errmsg("cache lookup failed for tuple from relation %u", lob_pointer->relid)));
|
||||
}
|
||||
bool attr_is_null = false;
|
||||
Datum attr = fastgetattr(origin_tuple, lob_pointer->columid, relation->rd_att, &attr_is_null);
|
||||
if (!attr_is_null && VARATT_IS_HUGE_TOAST_POINTER(attr)) {
|
||||
is_huge_clob = true;
|
||||
}
|
||||
heap_close(relation, NoLock);
|
||||
heap_freetuple(origin_tuple);
|
||||
return is_huge_clob;
|
||||
}
|
||||
|
||||
Datum fetch_lob_value_from_tuple(varatt_lob_pointer* lob_pointer, Oid update_oid, bool* is_null)
|
||||
{
|
||||
/* get relation by relid */
|
||||
ItemPointerData tuple_ctid;
|
||||
|
@ -6015,9 +6071,7 @@ Datum fetch_lob_value_from_tuple(varatt_lob_pointer* lob_pointer, Oid update_oid
|
|||
}
|
||||
|
||||
Datum attr = fastgetattr(origin_tuple, lob_pointer->columid, relation->rd_att, is_null);
|
||||
if (!*is_null && VARATT_IS_HUGE_TOAST_POINTER(attr) && is_huge_clob != NULL) {
|
||||
*is_huge_clob = true;
|
||||
}
|
||||
|
||||
|
||||
if (!OidIsValid(update_oid)) {
|
||||
heap_close(relation, NoLock);
|
||||
|
@ -6109,7 +6163,7 @@ static bool ExecTargetList(List* targetlist, ExprContext* econtext, Datum* value
|
|||
bool is_null = false;
|
||||
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, NULL);
|
||||
values[resind] = fetch_lob_value_from_tuple(lob_pointer, update_oid, &is_null);
|
||||
isnull[resind] = is_null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -279,8 +279,7 @@ extern bool create_toast_by_sid(Oid *toastOid);
|
|||
extern Oid get_toast_oid();
|
||||
extern varlena* toast_huge_write_datum_slice(struct varlena* attr1, struct varlena* attr2, int64 sliceoffset, int32 length);
|
||||
extern varlena* toast_pointer_fetch_data(TupleTableSlot* varSlot, Form_pg_attribute attr, int varNumber);
|
||||
extern Datum fetch_lob_value_from_tuple(varatt_lob_pointer* lob_pointer, Oid update_oid,
|
||||
bool* is_null, bool* is_huge_clob = NULL);
|
||||
extern Datum fetch_lob_value_from_tuple(varatt_lob_pointer* lob_pointer, Oid update_oid, bool* is_null);
|
||||
|
||||
inline Datum fetch_real_lob_if_need(Datum toast_pointer)
|
||||
{
|
||||
|
@ -288,7 +287,7 @@ inline Datum fetch_real_lob_if_need(Datum toast_pointer)
|
|||
if (VARATT_IS_EXTERNAL_LOB(toast_pointer)) {
|
||||
bool isNull = false;
|
||||
struct varatt_lob_pointer* lob_pointer = (varatt_lob_pointer*)(VARDATA_EXTERNAL(toast_pointer));
|
||||
ret = fetch_lob_value_from_tuple(lob_pointer, InvalidOid, &isNull, NULL);
|
||||
ret = fetch_lob_value_from_tuple(lob_pointer, InvalidOid, &isNull);
|
||||
if (unlikely(isNull)) {
|
||||
ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg("Invalid lob pointer.")));
|
||||
|
|
|
@ -280,6 +280,7 @@ extern void initExecTableOfIndexInfo(ExecTableOfIndexInfo* execTableOfIndexInfo,
|
|||
extern bool ExecEvalParamExternTableOfIndexById(ExecTableOfIndexInfo* execTableOfIndexInfo);
|
||||
extern void ExecEvalParamExternTableOfIndex(Node* node, ExecTableOfIndexInfo* execTableOfIndexInfo);
|
||||
extern bool is_external_clob(Oid type_oid, bool is_null, Datum value);
|
||||
extern bool is_huge_clob(Oid type_oid, bool is_null, Datum value);
|
||||
|
||||
/*
|
||||
* prototypes from functions in execTuples.c
|
||||
|
|
|
@ -67,6 +67,22 @@ ERROR: huge clob do not support as function in parameter
|
|||
CONTEXT: PL/pgSQL function pro_cb4_031(clob,clob) line 5 at assignment
|
||||
SQL statement "CALL pro_cb4_031(v1,v2)"
|
||||
PL/pgSQL function pro_cb4_031_1() line 7 at PERFORM
|
||||
create or replace procedure pro_cb4_005 is
|
||||
v1 clob;
|
||||
v2 clob;
|
||||
v3 clob;
|
||||
v4 integer;
|
||||
begin
|
||||
execute immediate 'select b from cloblongtbl where a=1' into v1;
|
||||
dbe_lob.read(v1,10,2,v2);
|
||||
end;
|
||||
/
|
||||
call pro_cb4_005();
|
||||
pro_cb4_005
|
||||
-------------
|
||||
|
||||
(1 row)
|
||||
|
||||
--I2.clob > 1G out
|
||||
create or replace procedure pro_cb4_031(c1 out clob,c2 out clob)
|
||||
is
|
||||
|
@ -215,7 +231,6 @@ select a,b,length(b),c,length(c) from cloblongtbl where a>5 and a<10 order by 1,
|
|||
(0 rows)
|
||||
|
||||
update cloblongtbl set c='cloblessthan1G';
|
||||
ERROR: tuple concurrently updated
|
||||
--I6.record
|
||||
create or replace procedure pro_cb4_031 is
|
||||
type ty1 is record(c1 int,c2 clob);
|
||||
|
@ -251,8 +266,11 @@ close cor1;
|
|||
end;
|
||||
/
|
||||
call pro_cb4_037();
|
||||
ERROR: huge clob do not support as record element.
|
||||
CONTEXT: PL/pgSQL function pro_cb4_037() line 10 at FETCH
|
||||
pro_cb4_037
|
||||
-------------
|
||||
|
||||
(1 row)
|
||||
|
||||
create or replace procedure test_self_update is
|
||||
v1 clob;
|
||||
begin
|
||||
|
@ -270,11 +288,36 @@ call test_self_update();
|
|||
|
||||
(1 row)
|
||||
|
||||
create or replace procedure test_update_delete is
|
||||
v1 clob;
|
||||
begin
|
||||
execute immediate 'select b from cloblongtbl where a=1' into v1;
|
||||
update cloblongtbl set b=v1 where a=1;
|
||||
rollback;
|
||||
update cloblongtbl set b=v1 where a=2;
|
||||
commit;
|
||||
end;
|
||||
/
|
||||
call test_update_delete();
|
||||
test_update_delete
|
||||
--------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
begin;
|
||||
delete from cloblongtbl where a < 3;
|
||||
rollback;
|
||||
begin;
|
||||
delete from cloblongtbl where a = 1;
|
||||
delete from cloblongtbl where a = 2;
|
||||
rollback;
|
||||
drop table if exists cloblongtbl;
|
||||
-- clean
|
||||
drop schema if exists huge_clob cascade;
|
||||
NOTICE: drop cascades to 4 other objects
|
||||
DETAIL: drop cascades to function pro_cb4_031_1()
|
||||
NOTICE: drop cascades to 6 other objects
|
||||
DETAIL: drop cascades to function pro_cb4_005()
|
||||
drop cascades to function pro_cb4_031_1()
|
||||
drop cascades to function pro_cb4_031()
|
||||
drop cascades to function pro_cb4_037()
|
||||
drop cascades to function test_self_update()
|
||||
drop cascades to function test_update_delete()
|
||||
|
|
|
@ -56,6 +56,19 @@ end;
|
|||
|
||||
call pro_cb4_031_1();
|
||||
|
||||
create or replace procedure pro_cb4_005 is
|
||||
v1 clob;
|
||||
v2 clob;
|
||||
v3 clob;
|
||||
v4 integer;
|
||||
begin
|
||||
execute immediate 'select b from cloblongtbl where a=1' into v1;
|
||||
dbe_lob.read(v1,10,2,v2);
|
||||
end;
|
||||
/
|
||||
|
||||
call pro_cb4_005();
|
||||
|
||||
--I2.clob > 1G out
|
||||
create or replace procedure pro_cb4_031(c1 out clob,c2 out clob)
|
||||
is
|
||||
|
|
Loading…
Reference in New Issue