public inbox for [email protected]help / color / mirror / Atom feed
[PATCH 2/8] Expand the external data before forming the tuple 49+ messages / 2 participants [nested] [flat]
* [PATCH 2/8] Expand the external data before forming the tuple @ 2021-03-04 09:25 Dilip Kumar <[email protected]> 0 siblings, 0 replies; 49+ messages in thread From: Dilip Kumar @ 2021-03-04 09:25 UTC (permalink / raw) All the callers of HeapTupleGetDatum and HeapTupleHeaderGetDatum, who might contain the external varlena in their tuple, try to flatten the external varlena before forming the tuple wherever it is possible. Dilip Kumar based on idea by Robert Haas --- src/backend/executor/execExprInterp.c | 29 +++++++++++++++++++++++++-- src/backend/utils/adt/jsonfuncs.c | 8 ++++++-- src/pl/plpgsql/src/pl_exec.c | 5 ++++- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index 20949a5dec..c3754acca4 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -2840,12 +2840,25 @@ ExecEvalRow(ExprState *state, ExprEvalStep *op) { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < op->d.row.tupdesc->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(op->d.row.tupdesc, i); + + if (op->d.row.elemnulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.row.elemvalues[i]))) + continue; + + op->d.row.elemvalues[i] = + PointerGetDatum(PG_DETOAST_DATUM_PACKED(op->d.row.elemvalues[i])); + } + /* build tuple from evaluated field values */ tuple = heap_form_tuple(op->d.row.tupdesc, op->d.row.elemvalues, op->d.row.elemnulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } @@ -3085,12 +3098,24 @@ ExecEvalFieldStoreForm(ExprState *state, ExprEvalStep *op, ExprContext *econtext { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < (*op->d.fieldstore.argdesc)->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(*op->d.fieldstore.argdesc, i); + + if (op->d.fieldstore.nulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.fieldstore.values[i]))) + continue; + op->d.fieldstore.values[i] = PointerGetDatum( + PG_DETOAST_DATUM_PACKED(op->d.fieldstore.values[i])); + } + /* argdesc should already be valid from the DeForm step */ tuple = heap_form_tuple(*op->d.fieldstore.argdesc, op->d.fieldstore.values, op->d.fieldstore.nulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c index 511467280f..c3d464f42b 100644 --- a/src/backend/utils/adt/jsonfuncs.c +++ b/src/backend/utils/adt/jsonfuncs.c @@ -2968,7 +2968,7 @@ populate_composite(CompositeIOData *io, /* populate resulting record tuple */ tuple = populate_record(io->tupdesc, &io->record_io, defaultval, mcxt, &jso); - result = HeapTupleHeaderGetDatum(tuple); + result = HeapTupleHeaderGetRawDatum(tuple); JsObjectFree(&jso); } @@ -3387,6 +3387,10 @@ populate_record(TupleDesc tupdesc, nulls[i] ? (Datum) 0 : values[i], &field, &nulls[i]); + + if (!nulls[i] && att->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(values[i]))) + values[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(values[i])); } res = heap_form_tuple(tupdesc, values, nulls); @@ -3765,7 +3769,7 @@ populate_recordset_record(PopulateRecordsetState *state, JsObject *obj) /* if it's domain over composite, check domain constraints */ if (cache->c.typcat == TYPECAT_COMPOSITE_DOMAIN) - domain_check(HeapTupleHeaderGetDatum(tuphead), false, + domain_check(HeapTupleHeaderGetRawDatum(tuphead), false, cache->argtype, &cache->c.io.composite.domain_info, cache->fn_mcxt); diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index b4c70aaa7f..fd073767bc 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -5326,7 +5326,7 @@ exec_eval_datum(PLpgSQL_execstate *estate, elog(ERROR, "row not compatible with its own tupdesc"); *typeid = row->rowtupdesc->tdtypeid; *typetypmod = row->rowtupdesc->tdtypmod; - *value = HeapTupleGetDatum(tup); + *value = HeapTupleGetRawDatum(tup); *isnull = false; MemoryContextSwitchTo(oldcontext); break; @@ -7300,6 +7300,9 @@ make_tuple_from_row(PLpgSQL_execstate *estate, &dvalues[i], &nulls[i]); if (fieldtypeid != TupleDescAttr(tupdesc, i)->atttypid) return NULL; + if (!nulls[i] && TupleDescAttr(tupdesc, i)->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(dvalues[i]))) + dvalues[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(dvalues[i])); /* XXX should we insist on typmod match, too? */ } -- 2.17.0 --C94crkcyjafcjHxo Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-Disallow-compressed-data-inside-container-types.patch" ^ permalink raw reply [nested|flat] 49+ messages in thread
* [PATCH 2/8] Expand the external data before forming the tuple @ 2021-03-04 09:25 Dilip Kumar <[email protected]> 0 siblings, 0 replies; 49+ messages in thread From: Dilip Kumar @ 2021-03-04 09:25 UTC (permalink / raw) All the callers of HeapTupleGetDatum and HeapTupleHeaderGetDatum, who might contain the external varlena in their tuple, try to flatten the external varlena before forming the tuple wherever it is possible. Dilip Kumar based on idea by Robert Haas --- src/backend/executor/execExprInterp.c | 29 +++++++++++++++++++++++++-- src/backend/utils/adt/jsonfuncs.c | 8 ++++++-- src/pl/plpgsql/src/pl_exec.c | 5 ++++- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index 20949a5dec..c3754acca4 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -2840,12 +2840,25 @@ ExecEvalRow(ExprState *state, ExprEvalStep *op) { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < op->d.row.tupdesc->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(op->d.row.tupdesc, i); + + if (op->d.row.elemnulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.row.elemvalues[i]))) + continue; + + op->d.row.elemvalues[i] = + PointerGetDatum(PG_DETOAST_DATUM_PACKED(op->d.row.elemvalues[i])); + } + /* build tuple from evaluated field values */ tuple = heap_form_tuple(op->d.row.tupdesc, op->d.row.elemvalues, op->d.row.elemnulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } @@ -3085,12 +3098,24 @@ ExecEvalFieldStoreForm(ExprState *state, ExprEvalStep *op, ExprContext *econtext { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < (*op->d.fieldstore.argdesc)->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(*op->d.fieldstore.argdesc, i); + + if (op->d.fieldstore.nulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.fieldstore.values[i]))) + continue; + op->d.fieldstore.values[i] = PointerGetDatum( + PG_DETOAST_DATUM_PACKED(op->d.fieldstore.values[i])); + } + /* argdesc should already be valid from the DeForm step */ tuple = heap_form_tuple(*op->d.fieldstore.argdesc, op->d.fieldstore.values, op->d.fieldstore.nulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c index 511467280f..c3d464f42b 100644 --- a/src/backend/utils/adt/jsonfuncs.c +++ b/src/backend/utils/adt/jsonfuncs.c @@ -2968,7 +2968,7 @@ populate_composite(CompositeIOData *io, /* populate resulting record tuple */ tuple = populate_record(io->tupdesc, &io->record_io, defaultval, mcxt, &jso); - result = HeapTupleHeaderGetDatum(tuple); + result = HeapTupleHeaderGetRawDatum(tuple); JsObjectFree(&jso); } @@ -3387,6 +3387,10 @@ populate_record(TupleDesc tupdesc, nulls[i] ? (Datum) 0 : values[i], &field, &nulls[i]); + + if (!nulls[i] && att->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(values[i]))) + values[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(values[i])); } res = heap_form_tuple(tupdesc, values, nulls); @@ -3765,7 +3769,7 @@ populate_recordset_record(PopulateRecordsetState *state, JsObject *obj) /* if it's domain over composite, check domain constraints */ if (cache->c.typcat == TYPECAT_COMPOSITE_DOMAIN) - domain_check(HeapTupleHeaderGetDatum(tuphead), false, + domain_check(HeapTupleHeaderGetRawDatum(tuphead), false, cache->argtype, &cache->c.io.composite.domain_info, cache->fn_mcxt); diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index b4c70aaa7f..fd073767bc 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -5326,7 +5326,7 @@ exec_eval_datum(PLpgSQL_execstate *estate, elog(ERROR, "row not compatible with its own tupdesc"); *typeid = row->rowtupdesc->tdtypeid; *typetypmod = row->rowtupdesc->tdtypmod; - *value = HeapTupleGetDatum(tup); + *value = HeapTupleGetRawDatum(tup); *isnull = false; MemoryContextSwitchTo(oldcontext); break; @@ -7300,6 +7300,9 @@ make_tuple_from_row(PLpgSQL_execstate *estate, &dvalues[i], &nulls[i]); if (fieldtypeid != TupleDescAttr(tupdesc, i)->atttypid) return NULL; + if (!nulls[i] && TupleDescAttr(tupdesc, i)->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(dvalues[i]))) + dvalues[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(dvalues[i])); /* XXX should we insist on typmod match, too? */ } -- 2.17.0 --cvVnyQ+4j833TQvp Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-Disallow-compressed-data-inside-container-types.patch" ^ permalink raw reply [nested|flat] 49+ messages in thread
* [PATCH 2/8] Expand the external data before forming the tuple @ 2021-03-04 09:25 Dilip Kumar <[email protected]> 0 siblings, 0 replies; 49+ messages in thread From: Dilip Kumar @ 2021-03-04 09:25 UTC (permalink / raw) All the callers of HeapTupleGetDatum and HeapTupleHeaderGetDatum, who might contain the external varlena in their tuple, try to flatten the external varlena before forming the tuple wherever it is possible. Dilip Kumar based on idea by Robert Haas --- src/backend/executor/execExprInterp.c | 29 +++++++++++++++++++++++++-- src/backend/utils/adt/jsonfuncs.c | 8 ++++++-- src/pl/plpgsql/src/pl_exec.c | 5 ++++- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index 20949a5dec..c3754acca4 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -2840,12 +2840,25 @@ ExecEvalRow(ExprState *state, ExprEvalStep *op) { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < op->d.row.tupdesc->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(op->d.row.tupdesc, i); + + if (op->d.row.elemnulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.row.elemvalues[i]))) + continue; + + op->d.row.elemvalues[i] = + PointerGetDatum(PG_DETOAST_DATUM_PACKED(op->d.row.elemvalues[i])); + } + /* build tuple from evaluated field values */ tuple = heap_form_tuple(op->d.row.tupdesc, op->d.row.elemvalues, op->d.row.elemnulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } @@ -3085,12 +3098,24 @@ ExecEvalFieldStoreForm(ExprState *state, ExprEvalStep *op, ExprContext *econtext { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < (*op->d.fieldstore.argdesc)->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(*op->d.fieldstore.argdesc, i); + + if (op->d.fieldstore.nulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.fieldstore.values[i]))) + continue; + op->d.fieldstore.values[i] = PointerGetDatum( + PG_DETOAST_DATUM_PACKED(op->d.fieldstore.values[i])); + } + /* argdesc should already be valid from the DeForm step */ tuple = heap_form_tuple(*op->d.fieldstore.argdesc, op->d.fieldstore.values, op->d.fieldstore.nulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c index 511467280f..c3d464f42b 100644 --- a/src/backend/utils/adt/jsonfuncs.c +++ b/src/backend/utils/adt/jsonfuncs.c @@ -2968,7 +2968,7 @@ populate_composite(CompositeIOData *io, /* populate resulting record tuple */ tuple = populate_record(io->tupdesc, &io->record_io, defaultval, mcxt, &jso); - result = HeapTupleHeaderGetDatum(tuple); + result = HeapTupleHeaderGetRawDatum(tuple); JsObjectFree(&jso); } @@ -3387,6 +3387,10 @@ populate_record(TupleDesc tupdesc, nulls[i] ? (Datum) 0 : values[i], &field, &nulls[i]); + + if (!nulls[i] && att->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(values[i]))) + values[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(values[i])); } res = heap_form_tuple(tupdesc, values, nulls); @@ -3765,7 +3769,7 @@ populate_recordset_record(PopulateRecordsetState *state, JsObject *obj) /* if it's domain over composite, check domain constraints */ if (cache->c.typcat == TYPECAT_COMPOSITE_DOMAIN) - domain_check(HeapTupleHeaderGetDatum(tuphead), false, + domain_check(HeapTupleHeaderGetRawDatum(tuphead), false, cache->argtype, &cache->c.io.composite.domain_info, cache->fn_mcxt); diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index b4c70aaa7f..fd073767bc 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -5326,7 +5326,7 @@ exec_eval_datum(PLpgSQL_execstate *estate, elog(ERROR, "row not compatible with its own tupdesc"); *typeid = row->rowtupdesc->tdtypeid; *typetypmod = row->rowtupdesc->tdtypmod; - *value = HeapTupleGetDatum(tup); + *value = HeapTupleGetRawDatum(tup); *isnull = false; MemoryContextSwitchTo(oldcontext); break; @@ -7300,6 +7300,9 @@ make_tuple_from_row(PLpgSQL_execstate *estate, &dvalues[i], &nulls[i]); if (fieldtypeid != TupleDescAttr(tupdesc, i)->atttypid) return NULL; + if (!nulls[i] && TupleDescAttr(tupdesc, i)->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(dvalues[i]))) + dvalues[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(dvalues[i])); /* XXX should we insist on typmod match, too? */ } -- 2.17.0 --C94crkcyjafcjHxo Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-Disallow-compressed-data-inside-container-types.patch" ^ permalink raw reply [nested|flat] 49+ messages in thread
* [PATCH 2/8] Expand the external data before forming the tuple @ 2021-03-04 09:25 Dilip Kumar <[email protected]> 0 siblings, 0 replies; 49+ messages in thread From: Dilip Kumar @ 2021-03-04 09:25 UTC (permalink / raw) All the callers of HeapTupleGetDatum and HeapTupleHeaderGetDatum, who might contain the external varlena in their tuple, try to flatten the external varlena before forming the tuple wherever it is possible. Dilip Kumar based on idea by Robert Haas --- src/backend/executor/execExprInterp.c | 29 +++++++++++++++++++++++++-- src/backend/utils/adt/jsonfuncs.c | 8 ++++++-- src/pl/plpgsql/src/pl_exec.c | 5 ++++- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index 20949a5dec..c3754acca4 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -2840,12 +2840,25 @@ ExecEvalRow(ExprState *state, ExprEvalStep *op) { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < op->d.row.tupdesc->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(op->d.row.tupdesc, i); + + if (op->d.row.elemnulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.row.elemvalues[i]))) + continue; + + op->d.row.elemvalues[i] = + PointerGetDatum(PG_DETOAST_DATUM_PACKED(op->d.row.elemvalues[i])); + } + /* build tuple from evaluated field values */ tuple = heap_form_tuple(op->d.row.tupdesc, op->d.row.elemvalues, op->d.row.elemnulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } @@ -3085,12 +3098,24 @@ ExecEvalFieldStoreForm(ExprState *state, ExprEvalStep *op, ExprContext *econtext { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < (*op->d.fieldstore.argdesc)->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(*op->d.fieldstore.argdesc, i); + + if (op->d.fieldstore.nulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.fieldstore.values[i]))) + continue; + op->d.fieldstore.values[i] = PointerGetDatum( + PG_DETOAST_DATUM_PACKED(op->d.fieldstore.values[i])); + } + /* argdesc should already be valid from the DeForm step */ tuple = heap_form_tuple(*op->d.fieldstore.argdesc, op->d.fieldstore.values, op->d.fieldstore.nulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c index 511467280f..c3d464f42b 100644 --- a/src/backend/utils/adt/jsonfuncs.c +++ b/src/backend/utils/adt/jsonfuncs.c @@ -2968,7 +2968,7 @@ populate_composite(CompositeIOData *io, /* populate resulting record tuple */ tuple = populate_record(io->tupdesc, &io->record_io, defaultval, mcxt, &jso); - result = HeapTupleHeaderGetDatum(tuple); + result = HeapTupleHeaderGetRawDatum(tuple); JsObjectFree(&jso); } @@ -3387,6 +3387,10 @@ populate_record(TupleDesc tupdesc, nulls[i] ? (Datum) 0 : values[i], &field, &nulls[i]); + + if (!nulls[i] && att->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(values[i]))) + values[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(values[i])); } res = heap_form_tuple(tupdesc, values, nulls); @@ -3765,7 +3769,7 @@ populate_recordset_record(PopulateRecordsetState *state, JsObject *obj) /* if it's domain over composite, check domain constraints */ if (cache->c.typcat == TYPECAT_COMPOSITE_DOMAIN) - domain_check(HeapTupleHeaderGetDatum(tuphead), false, + domain_check(HeapTupleHeaderGetRawDatum(tuphead), false, cache->argtype, &cache->c.io.composite.domain_info, cache->fn_mcxt); diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index b4c70aaa7f..fd073767bc 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -5326,7 +5326,7 @@ exec_eval_datum(PLpgSQL_execstate *estate, elog(ERROR, "row not compatible with its own tupdesc"); *typeid = row->rowtupdesc->tdtypeid; *typetypmod = row->rowtupdesc->tdtypmod; - *value = HeapTupleGetDatum(tup); + *value = HeapTupleGetRawDatum(tup); *isnull = false; MemoryContextSwitchTo(oldcontext); break; @@ -7300,6 +7300,9 @@ make_tuple_from_row(PLpgSQL_execstate *estate, &dvalues[i], &nulls[i]); if (fieldtypeid != TupleDescAttr(tupdesc, i)->atttypid) return NULL; + if (!nulls[i] && TupleDescAttr(tupdesc, i)->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(dvalues[i]))) + dvalues[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(dvalues[i])); /* XXX should we insist on typmod match, too? */ } -- 2.17.0 --cvVnyQ+4j833TQvp Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-Disallow-compressed-data-inside-container-types.patch" ^ permalink raw reply [nested|flat] 49+ messages in thread
* [PATCH 2/8] Expand the external data before forming the tuple @ 2021-03-04 09:25 Dilip Kumar <[email protected]> 0 siblings, 0 replies; 49+ messages in thread From: Dilip Kumar @ 2021-03-04 09:25 UTC (permalink / raw) All the callers of HeapTupleGetDatum and HeapTupleHeaderGetDatum, who might contain the external varlena in their tuple, try to flatten the external varlena before forming the tuple wherever it is possible. Dilip Kumar based on idea by Robert Haas --- src/backend/executor/execExprInterp.c | 29 +++++++++++++++++++++++++-- src/backend/utils/adt/jsonfuncs.c | 8 ++++++-- src/pl/plpgsql/src/pl_exec.c | 5 ++++- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index 20949a5dec..c3754acca4 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -2840,12 +2840,25 @@ ExecEvalRow(ExprState *state, ExprEvalStep *op) { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < op->d.row.tupdesc->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(op->d.row.tupdesc, i); + + if (op->d.row.elemnulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.row.elemvalues[i]))) + continue; + + op->d.row.elemvalues[i] = + PointerGetDatum(PG_DETOAST_DATUM_PACKED(op->d.row.elemvalues[i])); + } + /* build tuple from evaluated field values */ tuple = heap_form_tuple(op->d.row.tupdesc, op->d.row.elemvalues, op->d.row.elemnulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } @@ -3085,12 +3098,24 @@ ExecEvalFieldStoreForm(ExprState *state, ExprEvalStep *op, ExprContext *econtext { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < (*op->d.fieldstore.argdesc)->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(*op->d.fieldstore.argdesc, i); + + if (op->d.fieldstore.nulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.fieldstore.values[i]))) + continue; + op->d.fieldstore.values[i] = PointerGetDatum( + PG_DETOAST_DATUM_PACKED(op->d.fieldstore.values[i])); + } + /* argdesc should already be valid from the DeForm step */ tuple = heap_form_tuple(*op->d.fieldstore.argdesc, op->d.fieldstore.values, op->d.fieldstore.nulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c index 511467280f..c3d464f42b 100644 --- a/src/backend/utils/adt/jsonfuncs.c +++ b/src/backend/utils/adt/jsonfuncs.c @@ -2968,7 +2968,7 @@ populate_composite(CompositeIOData *io, /* populate resulting record tuple */ tuple = populate_record(io->tupdesc, &io->record_io, defaultval, mcxt, &jso); - result = HeapTupleHeaderGetDatum(tuple); + result = HeapTupleHeaderGetRawDatum(tuple); JsObjectFree(&jso); } @@ -3387,6 +3387,10 @@ populate_record(TupleDesc tupdesc, nulls[i] ? (Datum) 0 : values[i], &field, &nulls[i]); + + if (!nulls[i] && att->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(values[i]))) + values[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(values[i])); } res = heap_form_tuple(tupdesc, values, nulls); @@ -3765,7 +3769,7 @@ populate_recordset_record(PopulateRecordsetState *state, JsObject *obj) /* if it's domain over composite, check domain constraints */ if (cache->c.typcat == TYPECAT_COMPOSITE_DOMAIN) - domain_check(HeapTupleHeaderGetDatum(tuphead), false, + domain_check(HeapTupleHeaderGetRawDatum(tuphead), false, cache->argtype, &cache->c.io.composite.domain_info, cache->fn_mcxt); diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index b4c70aaa7f..fd073767bc 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -5326,7 +5326,7 @@ exec_eval_datum(PLpgSQL_execstate *estate, elog(ERROR, "row not compatible with its own tupdesc"); *typeid = row->rowtupdesc->tdtypeid; *typetypmod = row->rowtupdesc->tdtypmod; - *value = HeapTupleGetDatum(tup); + *value = HeapTupleGetRawDatum(tup); *isnull = false; MemoryContextSwitchTo(oldcontext); break; @@ -7300,6 +7300,9 @@ make_tuple_from_row(PLpgSQL_execstate *estate, &dvalues[i], &nulls[i]); if (fieldtypeid != TupleDescAttr(tupdesc, i)->atttypid) return NULL; + if (!nulls[i] && TupleDescAttr(tupdesc, i)->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(dvalues[i]))) + dvalues[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(dvalues[i])); /* XXX should we insist on typmod match, too? */ } -- 2.17.0 --C94crkcyjafcjHxo Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-Disallow-compressed-data-inside-container-types.patch" ^ permalink raw reply [nested|flat] 49+ messages in thread
* [PATCH 2/8] Expand the external data before forming the tuple @ 2021-03-04 09:25 Dilip Kumar <[email protected]> 0 siblings, 0 replies; 49+ messages in thread From: Dilip Kumar @ 2021-03-04 09:25 UTC (permalink / raw) All the callers of HeapTupleGetDatum and HeapTupleHeaderGetDatum, who might contain the external varlena in their tuple, try to flatten the external varlena before forming the tuple wherever it is possible. Dilip Kumar based on idea by Robert Haas --- src/backend/executor/execExprInterp.c | 29 +++++++++++++++++++++++++-- src/backend/utils/adt/jsonfuncs.c | 8 ++++++-- src/pl/plpgsql/src/pl_exec.c | 5 ++++- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index 20949a5dec..c3754acca4 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -2840,12 +2840,25 @@ ExecEvalRow(ExprState *state, ExprEvalStep *op) { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < op->d.row.tupdesc->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(op->d.row.tupdesc, i); + + if (op->d.row.elemnulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.row.elemvalues[i]))) + continue; + + op->d.row.elemvalues[i] = + PointerGetDatum(PG_DETOAST_DATUM_PACKED(op->d.row.elemvalues[i])); + } + /* build tuple from evaluated field values */ tuple = heap_form_tuple(op->d.row.tupdesc, op->d.row.elemvalues, op->d.row.elemnulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } @@ -3085,12 +3098,24 @@ ExecEvalFieldStoreForm(ExprState *state, ExprEvalStep *op, ExprContext *econtext { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < (*op->d.fieldstore.argdesc)->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(*op->d.fieldstore.argdesc, i); + + if (op->d.fieldstore.nulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.fieldstore.values[i]))) + continue; + op->d.fieldstore.values[i] = PointerGetDatum( + PG_DETOAST_DATUM_PACKED(op->d.fieldstore.values[i])); + } + /* argdesc should already be valid from the DeForm step */ tuple = heap_form_tuple(*op->d.fieldstore.argdesc, op->d.fieldstore.values, op->d.fieldstore.nulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c index 511467280f..c3d464f42b 100644 --- a/src/backend/utils/adt/jsonfuncs.c +++ b/src/backend/utils/adt/jsonfuncs.c @@ -2968,7 +2968,7 @@ populate_composite(CompositeIOData *io, /* populate resulting record tuple */ tuple = populate_record(io->tupdesc, &io->record_io, defaultval, mcxt, &jso); - result = HeapTupleHeaderGetDatum(tuple); + result = HeapTupleHeaderGetRawDatum(tuple); JsObjectFree(&jso); } @@ -3387,6 +3387,10 @@ populate_record(TupleDesc tupdesc, nulls[i] ? (Datum) 0 : values[i], &field, &nulls[i]); + + if (!nulls[i] && att->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(values[i]))) + values[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(values[i])); } res = heap_form_tuple(tupdesc, values, nulls); @@ -3765,7 +3769,7 @@ populate_recordset_record(PopulateRecordsetState *state, JsObject *obj) /* if it's domain over composite, check domain constraints */ if (cache->c.typcat == TYPECAT_COMPOSITE_DOMAIN) - domain_check(HeapTupleHeaderGetDatum(tuphead), false, + domain_check(HeapTupleHeaderGetRawDatum(tuphead), false, cache->argtype, &cache->c.io.composite.domain_info, cache->fn_mcxt); diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index b4c70aaa7f..fd073767bc 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -5326,7 +5326,7 @@ exec_eval_datum(PLpgSQL_execstate *estate, elog(ERROR, "row not compatible with its own tupdesc"); *typeid = row->rowtupdesc->tdtypeid; *typetypmod = row->rowtupdesc->tdtypmod; - *value = HeapTupleGetDatum(tup); + *value = HeapTupleGetRawDatum(tup); *isnull = false; MemoryContextSwitchTo(oldcontext); break; @@ -7300,6 +7300,9 @@ make_tuple_from_row(PLpgSQL_execstate *estate, &dvalues[i], &nulls[i]); if (fieldtypeid != TupleDescAttr(tupdesc, i)->atttypid) return NULL; + if (!nulls[i] && TupleDescAttr(tupdesc, i)->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(dvalues[i]))) + dvalues[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(dvalues[i])); /* XXX should we insist on typmod match, too? */ } -- 2.17.0 --cvVnyQ+4j833TQvp Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-Disallow-compressed-data-inside-container-types.patch" ^ permalink raw reply [nested|flat] 49+ messages in thread
* [PATCH 2/8] Expand the external data before forming the tuple @ 2021-03-04 09:25 Dilip Kumar <[email protected]> 0 siblings, 0 replies; 49+ messages in thread From: Dilip Kumar @ 2021-03-04 09:25 UTC (permalink / raw) All the callers of HeapTupleGetDatum and HeapTupleHeaderGetDatum, who might contain the external varlena in their tuple, try to flatten the external varlena before forming the tuple wherever it is possible. Dilip Kumar based on idea by Robert Haas --- src/backend/executor/execExprInterp.c | 29 +++++++++++++++++++++++++-- src/backend/utils/adt/jsonfuncs.c | 8 ++++++-- src/pl/plpgsql/src/pl_exec.c | 5 ++++- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index 20949a5dec..c3754acca4 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -2840,12 +2840,25 @@ ExecEvalRow(ExprState *state, ExprEvalStep *op) { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < op->d.row.tupdesc->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(op->d.row.tupdesc, i); + + if (op->d.row.elemnulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.row.elemvalues[i]))) + continue; + + op->d.row.elemvalues[i] = + PointerGetDatum(PG_DETOAST_DATUM_PACKED(op->d.row.elemvalues[i])); + } + /* build tuple from evaluated field values */ tuple = heap_form_tuple(op->d.row.tupdesc, op->d.row.elemvalues, op->d.row.elemnulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } @@ -3085,12 +3098,24 @@ ExecEvalFieldStoreForm(ExprState *state, ExprEvalStep *op, ExprContext *econtext { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < (*op->d.fieldstore.argdesc)->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(*op->d.fieldstore.argdesc, i); + + if (op->d.fieldstore.nulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.fieldstore.values[i]))) + continue; + op->d.fieldstore.values[i] = PointerGetDatum( + PG_DETOAST_DATUM_PACKED(op->d.fieldstore.values[i])); + } + /* argdesc should already be valid from the DeForm step */ tuple = heap_form_tuple(*op->d.fieldstore.argdesc, op->d.fieldstore.values, op->d.fieldstore.nulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c index 511467280f..c3d464f42b 100644 --- a/src/backend/utils/adt/jsonfuncs.c +++ b/src/backend/utils/adt/jsonfuncs.c @@ -2968,7 +2968,7 @@ populate_composite(CompositeIOData *io, /* populate resulting record tuple */ tuple = populate_record(io->tupdesc, &io->record_io, defaultval, mcxt, &jso); - result = HeapTupleHeaderGetDatum(tuple); + result = HeapTupleHeaderGetRawDatum(tuple); JsObjectFree(&jso); } @@ -3387,6 +3387,10 @@ populate_record(TupleDesc tupdesc, nulls[i] ? (Datum) 0 : values[i], &field, &nulls[i]); + + if (!nulls[i] && att->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(values[i]))) + values[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(values[i])); } res = heap_form_tuple(tupdesc, values, nulls); @@ -3765,7 +3769,7 @@ populate_recordset_record(PopulateRecordsetState *state, JsObject *obj) /* if it's domain over composite, check domain constraints */ if (cache->c.typcat == TYPECAT_COMPOSITE_DOMAIN) - domain_check(HeapTupleHeaderGetDatum(tuphead), false, + domain_check(HeapTupleHeaderGetRawDatum(tuphead), false, cache->argtype, &cache->c.io.composite.domain_info, cache->fn_mcxt); diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index b4c70aaa7f..fd073767bc 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -5326,7 +5326,7 @@ exec_eval_datum(PLpgSQL_execstate *estate, elog(ERROR, "row not compatible with its own tupdesc"); *typeid = row->rowtupdesc->tdtypeid; *typetypmod = row->rowtupdesc->tdtypmod; - *value = HeapTupleGetDatum(tup); + *value = HeapTupleGetRawDatum(tup); *isnull = false; MemoryContextSwitchTo(oldcontext); break; @@ -7300,6 +7300,9 @@ make_tuple_from_row(PLpgSQL_execstate *estate, &dvalues[i], &nulls[i]); if (fieldtypeid != TupleDescAttr(tupdesc, i)->atttypid) return NULL; + if (!nulls[i] && TupleDescAttr(tupdesc, i)->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(dvalues[i]))) + dvalues[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(dvalues[i])); /* XXX should we insist on typmod match, too? */ } -- 2.17.0 --C94crkcyjafcjHxo Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-Disallow-compressed-data-inside-container-types.patch" ^ permalink raw reply [nested|flat] 49+ messages in thread
* [PATCH 2/8] Expand the external data before forming the tuple @ 2021-03-04 09:25 Dilip Kumar <[email protected]> 0 siblings, 0 replies; 49+ messages in thread From: Dilip Kumar @ 2021-03-04 09:25 UTC (permalink / raw) All the callers of HeapTupleGetDatum and HeapTupleHeaderGetDatum, who might contain the external varlena in their tuple, try to flatten the external varlena before forming the tuple wherever it is possible. Dilip Kumar based on idea by Robert Haas --- src/backend/executor/execExprInterp.c | 29 +++++++++++++++++++++++++-- src/backend/utils/adt/jsonfuncs.c | 8 ++++++-- src/pl/plpgsql/src/pl_exec.c | 5 ++++- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index 20949a5dec..c3754acca4 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -2840,12 +2840,25 @@ ExecEvalRow(ExprState *state, ExprEvalStep *op) { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < op->d.row.tupdesc->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(op->d.row.tupdesc, i); + + if (op->d.row.elemnulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.row.elemvalues[i]))) + continue; + + op->d.row.elemvalues[i] = + PointerGetDatum(PG_DETOAST_DATUM_PACKED(op->d.row.elemvalues[i])); + } + /* build tuple from evaluated field values */ tuple = heap_form_tuple(op->d.row.tupdesc, op->d.row.elemvalues, op->d.row.elemnulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } @@ -3085,12 +3098,24 @@ ExecEvalFieldStoreForm(ExprState *state, ExprEvalStep *op, ExprContext *econtext { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < (*op->d.fieldstore.argdesc)->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(*op->d.fieldstore.argdesc, i); + + if (op->d.fieldstore.nulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.fieldstore.values[i]))) + continue; + op->d.fieldstore.values[i] = PointerGetDatum( + PG_DETOAST_DATUM_PACKED(op->d.fieldstore.values[i])); + } + /* argdesc should already be valid from the DeForm step */ tuple = heap_form_tuple(*op->d.fieldstore.argdesc, op->d.fieldstore.values, op->d.fieldstore.nulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c index 511467280f..c3d464f42b 100644 --- a/src/backend/utils/adt/jsonfuncs.c +++ b/src/backend/utils/adt/jsonfuncs.c @@ -2968,7 +2968,7 @@ populate_composite(CompositeIOData *io, /* populate resulting record tuple */ tuple = populate_record(io->tupdesc, &io->record_io, defaultval, mcxt, &jso); - result = HeapTupleHeaderGetDatum(tuple); + result = HeapTupleHeaderGetRawDatum(tuple); JsObjectFree(&jso); } @@ -3387,6 +3387,10 @@ populate_record(TupleDesc tupdesc, nulls[i] ? (Datum) 0 : values[i], &field, &nulls[i]); + + if (!nulls[i] && att->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(values[i]))) + values[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(values[i])); } res = heap_form_tuple(tupdesc, values, nulls); @@ -3765,7 +3769,7 @@ populate_recordset_record(PopulateRecordsetState *state, JsObject *obj) /* if it's domain over composite, check domain constraints */ if (cache->c.typcat == TYPECAT_COMPOSITE_DOMAIN) - domain_check(HeapTupleHeaderGetDatum(tuphead), false, + domain_check(HeapTupleHeaderGetRawDatum(tuphead), false, cache->argtype, &cache->c.io.composite.domain_info, cache->fn_mcxt); diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index b4c70aaa7f..fd073767bc 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -5326,7 +5326,7 @@ exec_eval_datum(PLpgSQL_execstate *estate, elog(ERROR, "row not compatible with its own tupdesc"); *typeid = row->rowtupdesc->tdtypeid; *typetypmod = row->rowtupdesc->tdtypmod; - *value = HeapTupleGetDatum(tup); + *value = HeapTupleGetRawDatum(tup); *isnull = false; MemoryContextSwitchTo(oldcontext); break; @@ -7300,6 +7300,9 @@ make_tuple_from_row(PLpgSQL_execstate *estate, &dvalues[i], &nulls[i]); if (fieldtypeid != TupleDescAttr(tupdesc, i)->atttypid) return NULL; + if (!nulls[i] && TupleDescAttr(tupdesc, i)->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(dvalues[i]))) + dvalues[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(dvalues[i])); /* XXX should we insist on typmod match, too? */ } -- 2.17.0 --cvVnyQ+4j833TQvp Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-Disallow-compressed-data-inside-container-types.patch" ^ permalink raw reply [nested|flat] 49+ messages in thread
* [PATCH 2/8] Expand the external data before forming the tuple @ 2021-03-04 09:25 Dilip Kumar <[email protected]> 0 siblings, 0 replies; 49+ messages in thread From: Dilip Kumar @ 2021-03-04 09:25 UTC (permalink / raw) All the callers of HeapTupleGetDatum and HeapTupleHeaderGetDatum, who might contain the external varlena in their tuple, try to flatten the external varlena before forming the tuple wherever it is possible. Dilip Kumar based on idea by Robert Haas --- src/backend/executor/execExprInterp.c | 29 +++++++++++++++++++++++++-- src/backend/utils/adt/jsonfuncs.c | 8 ++++++-- src/pl/plpgsql/src/pl_exec.c | 5 ++++- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index 20949a5dec..c3754acca4 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -2840,12 +2840,25 @@ ExecEvalRow(ExprState *state, ExprEvalStep *op) { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < op->d.row.tupdesc->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(op->d.row.tupdesc, i); + + if (op->d.row.elemnulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.row.elemvalues[i]))) + continue; + + op->d.row.elemvalues[i] = + PointerGetDatum(PG_DETOAST_DATUM_PACKED(op->d.row.elemvalues[i])); + } + /* build tuple from evaluated field values */ tuple = heap_form_tuple(op->d.row.tupdesc, op->d.row.elemvalues, op->d.row.elemnulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } @@ -3085,12 +3098,24 @@ ExecEvalFieldStoreForm(ExprState *state, ExprEvalStep *op, ExprContext *econtext { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < (*op->d.fieldstore.argdesc)->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(*op->d.fieldstore.argdesc, i); + + if (op->d.fieldstore.nulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.fieldstore.values[i]))) + continue; + op->d.fieldstore.values[i] = PointerGetDatum( + PG_DETOAST_DATUM_PACKED(op->d.fieldstore.values[i])); + } + /* argdesc should already be valid from the DeForm step */ tuple = heap_form_tuple(*op->d.fieldstore.argdesc, op->d.fieldstore.values, op->d.fieldstore.nulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c index 511467280f..c3d464f42b 100644 --- a/src/backend/utils/adt/jsonfuncs.c +++ b/src/backend/utils/adt/jsonfuncs.c @@ -2968,7 +2968,7 @@ populate_composite(CompositeIOData *io, /* populate resulting record tuple */ tuple = populate_record(io->tupdesc, &io->record_io, defaultval, mcxt, &jso); - result = HeapTupleHeaderGetDatum(tuple); + result = HeapTupleHeaderGetRawDatum(tuple); JsObjectFree(&jso); } @@ -3387,6 +3387,10 @@ populate_record(TupleDesc tupdesc, nulls[i] ? (Datum) 0 : values[i], &field, &nulls[i]); + + if (!nulls[i] && att->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(values[i]))) + values[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(values[i])); } res = heap_form_tuple(tupdesc, values, nulls); @@ -3765,7 +3769,7 @@ populate_recordset_record(PopulateRecordsetState *state, JsObject *obj) /* if it's domain over composite, check domain constraints */ if (cache->c.typcat == TYPECAT_COMPOSITE_DOMAIN) - domain_check(HeapTupleHeaderGetDatum(tuphead), false, + domain_check(HeapTupleHeaderGetRawDatum(tuphead), false, cache->argtype, &cache->c.io.composite.domain_info, cache->fn_mcxt); diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index b4c70aaa7f..fd073767bc 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -5326,7 +5326,7 @@ exec_eval_datum(PLpgSQL_execstate *estate, elog(ERROR, "row not compatible with its own tupdesc"); *typeid = row->rowtupdesc->tdtypeid; *typetypmod = row->rowtupdesc->tdtypmod; - *value = HeapTupleGetDatum(tup); + *value = HeapTupleGetRawDatum(tup); *isnull = false; MemoryContextSwitchTo(oldcontext); break; @@ -7300,6 +7300,9 @@ make_tuple_from_row(PLpgSQL_execstate *estate, &dvalues[i], &nulls[i]); if (fieldtypeid != TupleDescAttr(tupdesc, i)->atttypid) return NULL; + if (!nulls[i] && TupleDescAttr(tupdesc, i)->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(dvalues[i]))) + dvalues[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(dvalues[i])); /* XXX should we insist on typmod match, too? */ } -- 2.17.0 --C94crkcyjafcjHxo Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-Disallow-compressed-data-inside-container-types.patch" ^ permalink raw reply [nested|flat] 49+ messages in thread
* [PATCH 2/8] Expand the external data before forming the tuple @ 2021-03-04 09:25 Dilip Kumar <[email protected]> 0 siblings, 0 replies; 49+ messages in thread From: Dilip Kumar @ 2021-03-04 09:25 UTC (permalink / raw) All the callers of HeapTupleGetDatum and HeapTupleHeaderGetDatum, who might contain the external varlena in their tuple, try to flatten the external varlena before forming the tuple wherever it is possible. Dilip Kumar based on idea by Robert Haas --- src/backend/executor/execExprInterp.c | 29 +++++++++++++++++++++++++-- src/backend/utils/adt/jsonfuncs.c | 8 ++++++-- src/pl/plpgsql/src/pl_exec.c | 5 ++++- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index 20949a5dec..c3754acca4 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -2840,12 +2840,25 @@ ExecEvalRow(ExprState *state, ExprEvalStep *op) { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < op->d.row.tupdesc->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(op->d.row.tupdesc, i); + + if (op->d.row.elemnulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.row.elemvalues[i]))) + continue; + + op->d.row.elemvalues[i] = + PointerGetDatum(PG_DETOAST_DATUM_PACKED(op->d.row.elemvalues[i])); + } + /* build tuple from evaluated field values */ tuple = heap_form_tuple(op->d.row.tupdesc, op->d.row.elemvalues, op->d.row.elemnulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } @@ -3085,12 +3098,24 @@ ExecEvalFieldStoreForm(ExprState *state, ExprEvalStep *op, ExprContext *econtext { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < (*op->d.fieldstore.argdesc)->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(*op->d.fieldstore.argdesc, i); + + if (op->d.fieldstore.nulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.fieldstore.values[i]))) + continue; + op->d.fieldstore.values[i] = PointerGetDatum( + PG_DETOAST_DATUM_PACKED(op->d.fieldstore.values[i])); + } + /* argdesc should already be valid from the DeForm step */ tuple = heap_form_tuple(*op->d.fieldstore.argdesc, op->d.fieldstore.values, op->d.fieldstore.nulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c index 511467280f..c3d464f42b 100644 --- a/src/backend/utils/adt/jsonfuncs.c +++ b/src/backend/utils/adt/jsonfuncs.c @@ -2968,7 +2968,7 @@ populate_composite(CompositeIOData *io, /* populate resulting record tuple */ tuple = populate_record(io->tupdesc, &io->record_io, defaultval, mcxt, &jso); - result = HeapTupleHeaderGetDatum(tuple); + result = HeapTupleHeaderGetRawDatum(tuple); JsObjectFree(&jso); } @@ -3387,6 +3387,10 @@ populate_record(TupleDesc tupdesc, nulls[i] ? (Datum) 0 : values[i], &field, &nulls[i]); + + if (!nulls[i] && att->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(values[i]))) + values[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(values[i])); } res = heap_form_tuple(tupdesc, values, nulls); @@ -3765,7 +3769,7 @@ populate_recordset_record(PopulateRecordsetState *state, JsObject *obj) /* if it's domain over composite, check domain constraints */ if (cache->c.typcat == TYPECAT_COMPOSITE_DOMAIN) - domain_check(HeapTupleHeaderGetDatum(tuphead), false, + domain_check(HeapTupleHeaderGetRawDatum(tuphead), false, cache->argtype, &cache->c.io.composite.domain_info, cache->fn_mcxt); diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index b4c70aaa7f..fd073767bc 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -5326,7 +5326,7 @@ exec_eval_datum(PLpgSQL_execstate *estate, elog(ERROR, "row not compatible with its own tupdesc"); *typeid = row->rowtupdesc->tdtypeid; *typetypmod = row->rowtupdesc->tdtypmod; - *value = HeapTupleGetDatum(tup); + *value = HeapTupleGetRawDatum(tup); *isnull = false; MemoryContextSwitchTo(oldcontext); break; @@ -7300,6 +7300,9 @@ make_tuple_from_row(PLpgSQL_execstate *estate, &dvalues[i], &nulls[i]); if (fieldtypeid != TupleDescAttr(tupdesc, i)->atttypid) return NULL; + if (!nulls[i] && TupleDescAttr(tupdesc, i)->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(dvalues[i]))) + dvalues[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(dvalues[i])); /* XXX should we insist on typmod match, too? */ } -- 2.17.0 --cvVnyQ+4j833TQvp Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-Disallow-compressed-data-inside-container-types.patch" ^ permalink raw reply [nested|flat] 49+ messages in thread
* [PATCH 2/8] Expand the external data before forming the tuple @ 2021-03-04 09:25 Dilip Kumar <[email protected]> 0 siblings, 0 replies; 49+ messages in thread From: Dilip Kumar @ 2021-03-04 09:25 UTC (permalink / raw) All the callers of HeapTupleGetDatum and HeapTupleHeaderGetDatum, who might contain the external varlena in their tuple, try to flatten the external varlena before forming the tuple wherever it is possible. Dilip Kumar based on idea by Robert Haas --- src/backend/executor/execExprInterp.c | 29 +++++++++++++++++++++++++-- src/backend/utils/adt/jsonfuncs.c | 8 ++++++-- src/pl/plpgsql/src/pl_exec.c | 5 ++++- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index 20949a5dec..c3754acca4 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -2840,12 +2840,25 @@ ExecEvalRow(ExprState *state, ExprEvalStep *op) { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < op->d.row.tupdesc->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(op->d.row.tupdesc, i); + + if (op->d.row.elemnulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.row.elemvalues[i]))) + continue; + + op->d.row.elemvalues[i] = + PointerGetDatum(PG_DETOAST_DATUM_PACKED(op->d.row.elemvalues[i])); + } + /* build tuple from evaluated field values */ tuple = heap_form_tuple(op->d.row.tupdesc, op->d.row.elemvalues, op->d.row.elemnulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } @@ -3085,12 +3098,24 @@ ExecEvalFieldStoreForm(ExprState *state, ExprEvalStep *op, ExprContext *econtext { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < (*op->d.fieldstore.argdesc)->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(*op->d.fieldstore.argdesc, i); + + if (op->d.fieldstore.nulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.fieldstore.values[i]))) + continue; + op->d.fieldstore.values[i] = PointerGetDatum( + PG_DETOAST_DATUM_PACKED(op->d.fieldstore.values[i])); + } + /* argdesc should already be valid from the DeForm step */ tuple = heap_form_tuple(*op->d.fieldstore.argdesc, op->d.fieldstore.values, op->d.fieldstore.nulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c index 511467280f..c3d464f42b 100644 --- a/src/backend/utils/adt/jsonfuncs.c +++ b/src/backend/utils/adt/jsonfuncs.c @@ -2968,7 +2968,7 @@ populate_composite(CompositeIOData *io, /* populate resulting record tuple */ tuple = populate_record(io->tupdesc, &io->record_io, defaultval, mcxt, &jso); - result = HeapTupleHeaderGetDatum(tuple); + result = HeapTupleHeaderGetRawDatum(tuple); JsObjectFree(&jso); } @@ -3387,6 +3387,10 @@ populate_record(TupleDesc tupdesc, nulls[i] ? (Datum) 0 : values[i], &field, &nulls[i]); + + if (!nulls[i] && att->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(values[i]))) + values[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(values[i])); } res = heap_form_tuple(tupdesc, values, nulls); @@ -3765,7 +3769,7 @@ populate_recordset_record(PopulateRecordsetState *state, JsObject *obj) /* if it's domain over composite, check domain constraints */ if (cache->c.typcat == TYPECAT_COMPOSITE_DOMAIN) - domain_check(HeapTupleHeaderGetDatum(tuphead), false, + domain_check(HeapTupleHeaderGetRawDatum(tuphead), false, cache->argtype, &cache->c.io.composite.domain_info, cache->fn_mcxt); diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index b4c70aaa7f..fd073767bc 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -5326,7 +5326,7 @@ exec_eval_datum(PLpgSQL_execstate *estate, elog(ERROR, "row not compatible with its own tupdesc"); *typeid = row->rowtupdesc->tdtypeid; *typetypmod = row->rowtupdesc->tdtypmod; - *value = HeapTupleGetDatum(tup); + *value = HeapTupleGetRawDatum(tup); *isnull = false; MemoryContextSwitchTo(oldcontext); break; @@ -7300,6 +7300,9 @@ make_tuple_from_row(PLpgSQL_execstate *estate, &dvalues[i], &nulls[i]); if (fieldtypeid != TupleDescAttr(tupdesc, i)->atttypid) return NULL; + if (!nulls[i] && TupleDescAttr(tupdesc, i)->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(dvalues[i]))) + dvalues[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(dvalues[i])); /* XXX should we insist on typmod match, too? */ } -- 2.17.0 --C94crkcyjafcjHxo Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-Disallow-compressed-data-inside-container-types.patch" ^ permalink raw reply [nested|flat] 49+ messages in thread
* [PATCH 2/8] Expand the external data before forming the tuple @ 2021-03-04 09:25 Dilip Kumar <[email protected]> 0 siblings, 0 replies; 49+ messages in thread From: Dilip Kumar @ 2021-03-04 09:25 UTC (permalink / raw) All the callers of HeapTupleGetDatum and HeapTupleHeaderGetDatum, who might contain the external varlena in their tuple, try to flatten the external varlena before forming the tuple wherever it is possible. Dilip Kumar based on idea by Robert Haas --- src/backend/executor/execExprInterp.c | 29 +++++++++++++++++++++++++-- src/backend/utils/adt/jsonfuncs.c | 8 ++++++-- src/pl/plpgsql/src/pl_exec.c | 5 ++++- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index 20949a5dec..c3754acca4 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -2840,12 +2840,25 @@ ExecEvalRow(ExprState *state, ExprEvalStep *op) { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < op->d.row.tupdesc->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(op->d.row.tupdesc, i); + + if (op->d.row.elemnulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.row.elemvalues[i]))) + continue; + + op->d.row.elemvalues[i] = + PointerGetDatum(PG_DETOAST_DATUM_PACKED(op->d.row.elemvalues[i])); + } + /* build tuple from evaluated field values */ tuple = heap_form_tuple(op->d.row.tupdesc, op->d.row.elemvalues, op->d.row.elemnulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } @@ -3085,12 +3098,24 @@ ExecEvalFieldStoreForm(ExprState *state, ExprEvalStep *op, ExprContext *econtext { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < (*op->d.fieldstore.argdesc)->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(*op->d.fieldstore.argdesc, i); + + if (op->d.fieldstore.nulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.fieldstore.values[i]))) + continue; + op->d.fieldstore.values[i] = PointerGetDatum( + PG_DETOAST_DATUM_PACKED(op->d.fieldstore.values[i])); + } + /* argdesc should already be valid from the DeForm step */ tuple = heap_form_tuple(*op->d.fieldstore.argdesc, op->d.fieldstore.values, op->d.fieldstore.nulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c index 511467280f..c3d464f42b 100644 --- a/src/backend/utils/adt/jsonfuncs.c +++ b/src/backend/utils/adt/jsonfuncs.c @@ -2968,7 +2968,7 @@ populate_composite(CompositeIOData *io, /* populate resulting record tuple */ tuple = populate_record(io->tupdesc, &io->record_io, defaultval, mcxt, &jso); - result = HeapTupleHeaderGetDatum(tuple); + result = HeapTupleHeaderGetRawDatum(tuple); JsObjectFree(&jso); } @@ -3387,6 +3387,10 @@ populate_record(TupleDesc tupdesc, nulls[i] ? (Datum) 0 : values[i], &field, &nulls[i]); + + if (!nulls[i] && att->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(values[i]))) + values[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(values[i])); } res = heap_form_tuple(tupdesc, values, nulls); @@ -3765,7 +3769,7 @@ populate_recordset_record(PopulateRecordsetState *state, JsObject *obj) /* if it's domain over composite, check domain constraints */ if (cache->c.typcat == TYPECAT_COMPOSITE_DOMAIN) - domain_check(HeapTupleHeaderGetDatum(tuphead), false, + domain_check(HeapTupleHeaderGetRawDatum(tuphead), false, cache->argtype, &cache->c.io.composite.domain_info, cache->fn_mcxt); diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index b4c70aaa7f..fd073767bc 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -5326,7 +5326,7 @@ exec_eval_datum(PLpgSQL_execstate *estate, elog(ERROR, "row not compatible with its own tupdesc"); *typeid = row->rowtupdesc->tdtypeid; *typetypmod = row->rowtupdesc->tdtypmod; - *value = HeapTupleGetDatum(tup); + *value = HeapTupleGetRawDatum(tup); *isnull = false; MemoryContextSwitchTo(oldcontext); break; @@ -7300,6 +7300,9 @@ make_tuple_from_row(PLpgSQL_execstate *estate, &dvalues[i], &nulls[i]); if (fieldtypeid != TupleDescAttr(tupdesc, i)->atttypid) return NULL; + if (!nulls[i] && TupleDescAttr(tupdesc, i)->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(dvalues[i]))) + dvalues[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(dvalues[i])); /* XXX should we insist on typmod match, too? */ } -- 2.17.0 --cvVnyQ+4j833TQvp Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-Disallow-compressed-data-inside-container-types.patch" ^ permalink raw reply [nested|flat] 49+ messages in thread
* [PATCH 2/8] Expand the external data before forming the tuple @ 2021-03-04 09:25 Dilip Kumar <[email protected]> 0 siblings, 0 replies; 49+ messages in thread From: Dilip Kumar @ 2021-03-04 09:25 UTC (permalink / raw) All the callers of HeapTupleGetDatum and HeapTupleHeaderGetDatum, who might contain the external varlena in their tuple, try to flatten the external varlena before forming the tuple wherever it is possible. Dilip Kumar based on idea by Robert Haas --- src/backend/executor/execExprInterp.c | 29 +++++++++++++++++++++++++-- src/backend/utils/adt/jsonfuncs.c | 8 ++++++-- src/pl/plpgsql/src/pl_exec.c | 5 ++++- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index 20949a5dec..c3754acca4 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -2840,12 +2840,25 @@ ExecEvalRow(ExprState *state, ExprEvalStep *op) { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < op->d.row.tupdesc->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(op->d.row.tupdesc, i); + + if (op->d.row.elemnulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.row.elemvalues[i]))) + continue; + + op->d.row.elemvalues[i] = + PointerGetDatum(PG_DETOAST_DATUM_PACKED(op->d.row.elemvalues[i])); + } + /* build tuple from evaluated field values */ tuple = heap_form_tuple(op->d.row.tupdesc, op->d.row.elemvalues, op->d.row.elemnulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } @@ -3085,12 +3098,24 @@ ExecEvalFieldStoreForm(ExprState *state, ExprEvalStep *op, ExprContext *econtext { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < (*op->d.fieldstore.argdesc)->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(*op->d.fieldstore.argdesc, i); + + if (op->d.fieldstore.nulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.fieldstore.values[i]))) + continue; + op->d.fieldstore.values[i] = PointerGetDatum( + PG_DETOAST_DATUM_PACKED(op->d.fieldstore.values[i])); + } + /* argdesc should already be valid from the DeForm step */ tuple = heap_form_tuple(*op->d.fieldstore.argdesc, op->d.fieldstore.values, op->d.fieldstore.nulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c index 511467280f..c3d464f42b 100644 --- a/src/backend/utils/adt/jsonfuncs.c +++ b/src/backend/utils/adt/jsonfuncs.c @@ -2968,7 +2968,7 @@ populate_composite(CompositeIOData *io, /* populate resulting record tuple */ tuple = populate_record(io->tupdesc, &io->record_io, defaultval, mcxt, &jso); - result = HeapTupleHeaderGetDatum(tuple); + result = HeapTupleHeaderGetRawDatum(tuple); JsObjectFree(&jso); } @@ -3387,6 +3387,10 @@ populate_record(TupleDesc tupdesc, nulls[i] ? (Datum) 0 : values[i], &field, &nulls[i]); + + if (!nulls[i] && att->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(values[i]))) + values[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(values[i])); } res = heap_form_tuple(tupdesc, values, nulls); @@ -3765,7 +3769,7 @@ populate_recordset_record(PopulateRecordsetState *state, JsObject *obj) /* if it's domain over composite, check domain constraints */ if (cache->c.typcat == TYPECAT_COMPOSITE_DOMAIN) - domain_check(HeapTupleHeaderGetDatum(tuphead), false, + domain_check(HeapTupleHeaderGetRawDatum(tuphead), false, cache->argtype, &cache->c.io.composite.domain_info, cache->fn_mcxt); diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index b4c70aaa7f..fd073767bc 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -5326,7 +5326,7 @@ exec_eval_datum(PLpgSQL_execstate *estate, elog(ERROR, "row not compatible with its own tupdesc"); *typeid = row->rowtupdesc->tdtypeid; *typetypmod = row->rowtupdesc->tdtypmod; - *value = HeapTupleGetDatum(tup); + *value = HeapTupleGetRawDatum(tup); *isnull = false; MemoryContextSwitchTo(oldcontext); break; @@ -7300,6 +7300,9 @@ make_tuple_from_row(PLpgSQL_execstate *estate, &dvalues[i], &nulls[i]); if (fieldtypeid != TupleDescAttr(tupdesc, i)->atttypid) return NULL; + if (!nulls[i] && TupleDescAttr(tupdesc, i)->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(dvalues[i]))) + dvalues[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(dvalues[i])); /* XXX should we insist on typmod match, too? */ } -- 2.17.0 --C94crkcyjafcjHxo Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-Disallow-compressed-data-inside-container-types.patch" ^ permalink raw reply [nested|flat] 49+ messages in thread
* [PATCH 2/8] Expand the external data before forming the tuple @ 2021-03-04 09:25 Dilip Kumar <[email protected]> 0 siblings, 0 replies; 49+ messages in thread From: Dilip Kumar @ 2021-03-04 09:25 UTC (permalink / raw) All the callers of HeapTupleGetDatum and HeapTupleHeaderGetDatum, who might contain the external varlena in their tuple, try to flatten the external varlena before forming the tuple wherever it is possible. Dilip Kumar based on idea by Robert Haas --- src/backend/executor/execExprInterp.c | 29 +++++++++++++++++++++++++-- src/backend/utils/adt/jsonfuncs.c | 8 ++++++-- src/pl/plpgsql/src/pl_exec.c | 5 ++++- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index 20949a5dec..c3754acca4 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -2840,12 +2840,25 @@ ExecEvalRow(ExprState *state, ExprEvalStep *op) { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < op->d.row.tupdesc->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(op->d.row.tupdesc, i); + + if (op->d.row.elemnulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.row.elemvalues[i]))) + continue; + + op->d.row.elemvalues[i] = + PointerGetDatum(PG_DETOAST_DATUM_PACKED(op->d.row.elemvalues[i])); + } + /* build tuple from evaluated field values */ tuple = heap_form_tuple(op->d.row.tupdesc, op->d.row.elemvalues, op->d.row.elemnulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } @@ -3085,12 +3098,24 @@ ExecEvalFieldStoreForm(ExprState *state, ExprEvalStep *op, ExprContext *econtext { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < (*op->d.fieldstore.argdesc)->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(*op->d.fieldstore.argdesc, i); + + if (op->d.fieldstore.nulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.fieldstore.values[i]))) + continue; + op->d.fieldstore.values[i] = PointerGetDatum( + PG_DETOAST_DATUM_PACKED(op->d.fieldstore.values[i])); + } + /* argdesc should already be valid from the DeForm step */ tuple = heap_form_tuple(*op->d.fieldstore.argdesc, op->d.fieldstore.values, op->d.fieldstore.nulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c index 511467280f..c3d464f42b 100644 --- a/src/backend/utils/adt/jsonfuncs.c +++ b/src/backend/utils/adt/jsonfuncs.c @@ -2968,7 +2968,7 @@ populate_composite(CompositeIOData *io, /* populate resulting record tuple */ tuple = populate_record(io->tupdesc, &io->record_io, defaultval, mcxt, &jso); - result = HeapTupleHeaderGetDatum(tuple); + result = HeapTupleHeaderGetRawDatum(tuple); JsObjectFree(&jso); } @@ -3387,6 +3387,10 @@ populate_record(TupleDesc tupdesc, nulls[i] ? (Datum) 0 : values[i], &field, &nulls[i]); + + if (!nulls[i] && att->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(values[i]))) + values[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(values[i])); } res = heap_form_tuple(tupdesc, values, nulls); @@ -3765,7 +3769,7 @@ populate_recordset_record(PopulateRecordsetState *state, JsObject *obj) /* if it's domain over composite, check domain constraints */ if (cache->c.typcat == TYPECAT_COMPOSITE_DOMAIN) - domain_check(HeapTupleHeaderGetDatum(tuphead), false, + domain_check(HeapTupleHeaderGetRawDatum(tuphead), false, cache->argtype, &cache->c.io.composite.domain_info, cache->fn_mcxt); diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index b4c70aaa7f..fd073767bc 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -5326,7 +5326,7 @@ exec_eval_datum(PLpgSQL_execstate *estate, elog(ERROR, "row not compatible with its own tupdesc"); *typeid = row->rowtupdesc->tdtypeid; *typetypmod = row->rowtupdesc->tdtypmod; - *value = HeapTupleGetDatum(tup); + *value = HeapTupleGetRawDatum(tup); *isnull = false; MemoryContextSwitchTo(oldcontext); break; @@ -7300,6 +7300,9 @@ make_tuple_from_row(PLpgSQL_execstate *estate, &dvalues[i], &nulls[i]); if (fieldtypeid != TupleDescAttr(tupdesc, i)->atttypid) return NULL; + if (!nulls[i] && TupleDescAttr(tupdesc, i)->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(dvalues[i]))) + dvalues[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(dvalues[i])); /* XXX should we insist on typmod match, too? */ } -- 2.17.0 --cvVnyQ+4j833TQvp Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-Disallow-compressed-data-inside-container-types.patch" ^ permalink raw reply [nested|flat] 49+ messages in thread
* [PATCH 2/8] Expand the external data before forming the tuple @ 2021-03-04 09:25 Dilip Kumar <[email protected]> 0 siblings, 0 replies; 49+ messages in thread From: Dilip Kumar @ 2021-03-04 09:25 UTC (permalink / raw) All the callers of HeapTupleGetDatum and HeapTupleHeaderGetDatum, who might contain the external varlena in their tuple, try to flatten the external varlena before forming the tuple wherever it is possible. Dilip Kumar based on idea by Robert Haas --- src/backend/executor/execExprInterp.c | 29 +++++++++++++++++++++++++-- src/backend/utils/adt/jsonfuncs.c | 8 ++++++-- src/pl/plpgsql/src/pl_exec.c | 5 ++++- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index 20949a5dec..c3754acca4 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -2840,12 +2840,25 @@ ExecEvalRow(ExprState *state, ExprEvalStep *op) { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < op->d.row.tupdesc->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(op->d.row.tupdesc, i); + + if (op->d.row.elemnulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.row.elemvalues[i]))) + continue; + + op->d.row.elemvalues[i] = + PointerGetDatum(PG_DETOAST_DATUM_PACKED(op->d.row.elemvalues[i])); + } + /* build tuple from evaluated field values */ tuple = heap_form_tuple(op->d.row.tupdesc, op->d.row.elemvalues, op->d.row.elemnulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } @@ -3085,12 +3098,24 @@ ExecEvalFieldStoreForm(ExprState *state, ExprEvalStep *op, ExprContext *econtext { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < (*op->d.fieldstore.argdesc)->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(*op->d.fieldstore.argdesc, i); + + if (op->d.fieldstore.nulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.fieldstore.values[i]))) + continue; + op->d.fieldstore.values[i] = PointerGetDatum( + PG_DETOAST_DATUM_PACKED(op->d.fieldstore.values[i])); + } + /* argdesc should already be valid from the DeForm step */ tuple = heap_form_tuple(*op->d.fieldstore.argdesc, op->d.fieldstore.values, op->d.fieldstore.nulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c index 511467280f..c3d464f42b 100644 --- a/src/backend/utils/adt/jsonfuncs.c +++ b/src/backend/utils/adt/jsonfuncs.c @@ -2968,7 +2968,7 @@ populate_composite(CompositeIOData *io, /* populate resulting record tuple */ tuple = populate_record(io->tupdesc, &io->record_io, defaultval, mcxt, &jso); - result = HeapTupleHeaderGetDatum(tuple); + result = HeapTupleHeaderGetRawDatum(tuple); JsObjectFree(&jso); } @@ -3387,6 +3387,10 @@ populate_record(TupleDesc tupdesc, nulls[i] ? (Datum) 0 : values[i], &field, &nulls[i]); + + if (!nulls[i] && att->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(values[i]))) + values[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(values[i])); } res = heap_form_tuple(tupdesc, values, nulls); @@ -3765,7 +3769,7 @@ populate_recordset_record(PopulateRecordsetState *state, JsObject *obj) /* if it's domain over composite, check domain constraints */ if (cache->c.typcat == TYPECAT_COMPOSITE_DOMAIN) - domain_check(HeapTupleHeaderGetDatum(tuphead), false, + domain_check(HeapTupleHeaderGetRawDatum(tuphead), false, cache->argtype, &cache->c.io.composite.domain_info, cache->fn_mcxt); diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index b4c70aaa7f..fd073767bc 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -5326,7 +5326,7 @@ exec_eval_datum(PLpgSQL_execstate *estate, elog(ERROR, "row not compatible with its own tupdesc"); *typeid = row->rowtupdesc->tdtypeid; *typetypmod = row->rowtupdesc->tdtypmod; - *value = HeapTupleGetDatum(tup); + *value = HeapTupleGetRawDatum(tup); *isnull = false; MemoryContextSwitchTo(oldcontext); break; @@ -7300,6 +7300,9 @@ make_tuple_from_row(PLpgSQL_execstate *estate, &dvalues[i], &nulls[i]); if (fieldtypeid != TupleDescAttr(tupdesc, i)->atttypid) return NULL; + if (!nulls[i] && TupleDescAttr(tupdesc, i)->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(dvalues[i]))) + dvalues[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(dvalues[i])); /* XXX should we insist on typmod match, too? */ } -- 2.17.0 --C94crkcyjafcjHxo Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-Disallow-compressed-data-inside-container-types.patch" ^ permalink raw reply [nested|flat] 49+ messages in thread
* [PATCH 2/8] Expand the external data before forming the tuple @ 2021-03-04 09:25 Dilip Kumar <[email protected]> 0 siblings, 0 replies; 49+ messages in thread From: Dilip Kumar @ 2021-03-04 09:25 UTC (permalink / raw) All the callers of HeapTupleGetDatum and HeapTupleHeaderGetDatum, who might contain the external varlena in their tuple, try to flatten the external varlena before forming the tuple wherever it is possible. Dilip Kumar based on idea by Robert Haas --- src/backend/executor/execExprInterp.c | 29 +++++++++++++++++++++++++-- src/backend/utils/adt/jsonfuncs.c | 8 ++++++-- src/pl/plpgsql/src/pl_exec.c | 5 ++++- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index 20949a5dec..c3754acca4 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -2840,12 +2840,25 @@ ExecEvalRow(ExprState *state, ExprEvalStep *op) { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < op->d.row.tupdesc->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(op->d.row.tupdesc, i); + + if (op->d.row.elemnulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.row.elemvalues[i]))) + continue; + + op->d.row.elemvalues[i] = + PointerGetDatum(PG_DETOAST_DATUM_PACKED(op->d.row.elemvalues[i])); + } + /* build tuple from evaluated field values */ tuple = heap_form_tuple(op->d.row.tupdesc, op->d.row.elemvalues, op->d.row.elemnulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } @@ -3085,12 +3098,24 @@ ExecEvalFieldStoreForm(ExprState *state, ExprEvalStep *op, ExprContext *econtext { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < (*op->d.fieldstore.argdesc)->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(*op->d.fieldstore.argdesc, i); + + if (op->d.fieldstore.nulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.fieldstore.values[i]))) + continue; + op->d.fieldstore.values[i] = PointerGetDatum( + PG_DETOAST_DATUM_PACKED(op->d.fieldstore.values[i])); + } + /* argdesc should already be valid from the DeForm step */ tuple = heap_form_tuple(*op->d.fieldstore.argdesc, op->d.fieldstore.values, op->d.fieldstore.nulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c index 511467280f..c3d464f42b 100644 --- a/src/backend/utils/adt/jsonfuncs.c +++ b/src/backend/utils/adt/jsonfuncs.c @@ -2968,7 +2968,7 @@ populate_composite(CompositeIOData *io, /* populate resulting record tuple */ tuple = populate_record(io->tupdesc, &io->record_io, defaultval, mcxt, &jso); - result = HeapTupleHeaderGetDatum(tuple); + result = HeapTupleHeaderGetRawDatum(tuple); JsObjectFree(&jso); } @@ -3387,6 +3387,10 @@ populate_record(TupleDesc tupdesc, nulls[i] ? (Datum) 0 : values[i], &field, &nulls[i]); + + if (!nulls[i] && att->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(values[i]))) + values[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(values[i])); } res = heap_form_tuple(tupdesc, values, nulls); @@ -3765,7 +3769,7 @@ populate_recordset_record(PopulateRecordsetState *state, JsObject *obj) /* if it's domain over composite, check domain constraints */ if (cache->c.typcat == TYPECAT_COMPOSITE_DOMAIN) - domain_check(HeapTupleHeaderGetDatum(tuphead), false, + domain_check(HeapTupleHeaderGetRawDatum(tuphead), false, cache->argtype, &cache->c.io.composite.domain_info, cache->fn_mcxt); diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index b4c70aaa7f..fd073767bc 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -5326,7 +5326,7 @@ exec_eval_datum(PLpgSQL_execstate *estate, elog(ERROR, "row not compatible with its own tupdesc"); *typeid = row->rowtupdesc->tdtypeid; *typetypmod = row->rowtupdesc->tdtypmod; - *value = HeapTupleGetDatum(tup); + *value = HeapTupleGetRawDatum(tup); *isnull = false; MemoryContextSwitchTo(oldcontext); break; @@ -7300,6 +7300,9 @@ make_tuple_from_row(PLpgSQL_execstate *estate, &dvalues[i], &nulls[i]); if (fieldtypeid != TupleDescAttr(tupdesc, i)->atttypid) return NULL; + if (!nulls[i] && TupleDescAttr(tupdesc, i)->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(dvalues[i]))) + dvalues[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(dvalues[i])); /* XXX should we insist on typmod match, too? */ } -- 2.17.0 --cvVnyQ+4j833TQvp Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-Disallow-compressed-data-inside-container-types.patch" ^ permalink raw reply [nested|flat] 49+ messages in thread
* [PATCH 2/8] Expand the external data before forming the tuple @ 2021-03-04 09:25 Dilip Kumar <[email protected]> 0 siblings, 0 replies; 49+ messages in thread From: Dilip Kumar @ 2021-03-04 09:25 UTC (permalink / raw) All the callers of HeapTupleGetDatum and HeapTupleHeaderGetDatum, who might contain the external varlena in their tuple, try to flatten the external varlena before forming the tuple wherever it is possible. Dilip Kumar based on idea by Robert Haas --- src/backend/executor/execExprInterp.c | 29 +++++++++++++++++++++++++-- src/backend/utils/adt/jsonfuncs.c | 8 ++++++-- src/pl/plpgsql/src/pl_exec.c | 5 ++++- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index 20949a5dec..c3754acca4 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -2840,12 +2840,25 @@ ExecEvalRow(ExprState *state, ExprEvalStep *op) { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < op->d.row.tupdesc->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(op->d.row.tupdesc, i); + + if (op->d.row.elemnulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.row.elemvalues[i]))) + continue; + + op->d.row.elemvalues[i] = + PointerGetDatum(PG_DETOAST_DATUM_PACKED(op->d.row.elemvalues[i])); + } + /* build tuple from evaluated field values */ tuple = heap_form_tuple(op->d.row.tupdesc, op->d.row.elemvalues, op->d.row.elemnulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } @@ -3085,12 +3098,24 @@ ExecEvalFieldStoreForm(ExprState *state, ExprEvalStep *op, ExprContext *econtext { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < (*op->d.fieldstore.argdesc)->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(*op->d.fieldstore.argdesc, i); + + if (op->d.fieldstore.nulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.fieldstore.values[i]))) + continue; + op->d.fieldstore.values[i] = PointerGetDatum( + PG_DETOAST_DATUM_PACKED(op->d.fieldstore.values[i])); + } + /* argdesc should already be valid from the DeForm step */ tuple = heap_form_tuple(*op->d.fieldstore.argdesc, op->d.fieldstore.values, op->d.fieldstore.nulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c index 511467280f..c3d464f42b 100644 --- a/src/backend/utils/adt/jsonfuncs.c +++ b/src/backend/utils/adt/jsonfuncs.c @@ -2968,7 +2968,7 @@ populate_composite(CompositeIOData *io, /* populate resulting record tuple */ tuple = populate_record(io->tupdesc, &io->record_io, defaultval, mcxt, &jso); - result = HeapTupleHeaderGetDatum(tuple); + result = HeapTupleHeaderGetRawDatum(tuple); JsObjectFree(&jso); } @@ -3387,6 +3387,10 @@ populate_record(TupleDesc tupdesc, nulls[i] ? (Datum) 0 : values[i], &field, &nulls[i]); + + if (!nulls[i] && att->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(values[i]))) + values[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(values[i])); } res = heap_form_tuple(tupdesc, values, nulls); @@ -3765,7 +3769,7 @@ populate_recordset_record(PopulateRecordsetState *state, JsObject *obj) /* if it's domain over composite, check domain constraints */ if (cache->c.typcat == TYPECAT_COMPOSITE_DOMAIN) - domain_check(HeapTupleHeaderGetDatum(tuphead), false, + domain_check(HeapTupleHeaderGetRawDatum(tuphead), false, cache->argtype, &cache->c.io.composite.domain_info, cache->fn_mcxt); diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index b4c70aaa7f..fd073767bc 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -5326,7 +5326,7 @@ exec_eval_datum(PLpgSQL_execstate *estate, elog(ERROR, "row not compatible with its own tupdesc"); *typeid = row->rowtupdesc->tdtypeid; *typetypmod = row->rowtupdesc->tdtypmod; - *value = HeapTupleGetDatum(tup); + *value = HeapTupleGetRawDatum(tup); *isnull = false; MemoryContextSwitchTo(oldcontext); break; @@ -7300,6 +7300,9 @@ make_tuple_from_row(PLpgSQL_execstate *estate, &dvalues[i], &nulls[i]); if (fieldtypeid != TupleDescAttr(tupdesc, i)->atttypid) return NULL; + if (!nulls[i] && TupleDescAttr(tupdesc, i)->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(dvalues[i]))) + dvalues[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(dvalues[i])); /* XXX should we insist on typmod match, too? */ } -- 2.17.0 --C94crkcyjafcjHxo Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-Disallow-compressed-data-inside-container-types.patch" ^ permalink raw reply [nested|flat] 49+ messages in thread
* [PATCH 2/8] Expand the external data before forming the tuple @ 2021-03-04 09:25 Dilip Kumar <[email protected]> 0 siblings, 0 replies; 49+ messages in thread From: Dilip Kumar @ 2021-03-04 09:25 UTC (permalink / raw) All the callers of HeapTupleGetDatum and HeapTupleHeaderGetDatum, who might contain the external varlena in their tuple, try to flatten the external varlena before forming the tuple wherever it is possible. Dilip Kumar based on idea by Robert Haas --- src/backend/executor/execExprInterp.c | 29 +++++++++++++++++++++++++-- src/backend/utils/adt/jsonfuncs.c | 8 ++++++-- src/pl/plpgsql/src/pl_exec.c | 5 ++++- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index 20949a5dec..c3754acca4 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -2840,12 +2840,25 @@ ExecEvalRow(ExprState *state, ExprEvalStep *op) { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < op->d.row.tupdesc->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(op->d.row.tupdesc, i); + + if (op->d.row.elemnulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.row.elemvalues[i]))) + continue; + + op->d.row.elemvalues[i] = + PointerGetDatum(PG_DETOAST_DATUM_PACKED(op->d.row.elemvalues[i])); + } + /* build tuple from evaluated field values */ tuple = heap_form_tuple(op->d.row.tupdesc, op->d.row.elemvalues, op->d.row.elemnulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } @@ -3085,12 +3098,24 @@ ExecEvalFieldStoreForm(ExprState *state, ExprEvalStep *op, ExprContext *econtext { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < (*op->d.fieldstore.argdesc)->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(*op->d.fieldstore.argdesc, i); + + if (op->d.fieldstore.nulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.fieldstore.values[i]))) + continue; + op->d.fieldstore.values[i] = PointerGetDatum( + PG_DETOAST_DATUM_PACKED(op->d.fieldstore.values[i])); + } + /* argdesc should already be valid from the DeForm step */ tuple = heap_form_tuple(*op->d.fieldstore.argdesc, op->d.fieldstore.values, op->d.fieldstore.nulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c index 511467280f..c3d464f42b 100644 --- a/src/backend/utils/adt/jsonfuncs.c +++ b/src/backend/utils/adt/jsonfuncs.c @@ -2968,7 +2968,7 @@ populate_composite(CompositeIOData *io, /* populate resulting record tuple */ tuple = populate_record(io->tupdesc, &io->record_io, defaultval, mcxt, &jso); - result = HeapTupleHeaderGetDatum(tuple); + result = HeapTupleHeaderGetRawDatum(tuple); JsObjectFree(&jso); } @@ -3387,6 +3387,10 @@ populate_record(TupleDesc tupdesc, nulls[i] ? (Datum) 0 : values[i], &field, &nulls[i]); + + if (!nulls[i] && att->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(values[i]))) + values[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(values[i])); } res = heap_form_tuple(tupdesc, values, nulls); @@ -3765,7 +3769,7 @@ populate_recordset_record(PopulateRecordsetState *state, JsObject *obj) /* if it's domain over composite, check domain constraints */ if (cache->c.typcat == TYPECAT_COMPOSITE_DOMAIN) - domain_check(HeapTupleHeaderGetDatum(tuphead), false, + domain_check(HeapTupleHeaderGetRawDatum(tuphead), false, cache->argtype, &cache->c.io.composite.domain_info, cache->fn_mcxt); diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index b4c70aaa7f..fd073767bc 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -5326,7 +5326,7 @@ exec_eval_datum(PLpgSQL_execstate *estate, elog(ERROR, "row not compatible with its own tupdesc"); *typeid = row->rowtupdesc->tdtypeid; *typetypmod = row->rowtupdesc->tdtypmod; - *value = HeapTupleGetDatum(tup); + *value = HeapTupleGetRawDatum(tup); *isnull = false; MemoryContextSwitchTo(oldcontext); break; @@ -7300,6 +7300,9 @@ make_tuple_from_row(PLpgSQL_execstate *estate, &dvalues[i], &nulls[i]); if (fieldtypeid != TupleDescAttr(tupdesc, i)->atttypid) return NULL; + if (!nulls[i] && TupleDescAttr(tupdesc, i)->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(dvalues[i]))) + dvalues[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(dvalues[i])); /* XXX should we insist on typmod match, too? */ } -- 2.17.0 --cvVnyQ+4j833TQvp Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-Disallow-compressed-data-inside-container-types.patch" ^ permalink raw reply [nested|flat] 49+ messages in thread
* [PATCH 2/8] Expand the external data before forming the tuple @ 2021-03-04 09:25 Dilip Kumar <[email protected]> 0 siblings, 0 replies; 49+ messages in thread From: Dilip Kumar @ 2021-03-04 09:25 UTC (permalink / raw) All the callers of HeapTupleGetDatum and HeapTupleHeaderGetDatum, who might contain the external varlena in their tuple, try to flatten the external varlena before forming the tuple wherever it is possible. Dilip Kumar based on idea by Robert Haas --- src/backend/executor/execExprInterp.c | 29 +++++++++++++++++++++++++-- src/backend/utils/adt/jsonfuncs.c | 8 ++++++-- src/pl/plpgsql/src/pl_exec.c | 5 ++++- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index 20949a5dec..c3754acca4 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -2840,12 +2840,25 @@ ExecEvalRow(ExprState *state, ExprEvalStep *op) { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < op->d.row.tupdesc->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(op->d.row.tupdesc, i); + + if (op->d.row.elemnulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.row.elemvalues[i]))) + continue; + + op->d.row.elemvalues[i] = + PointerGetDatum(PG_DETOAST_DATUM_PACKED(op->d.row.elemvalues[i])); + } + /* build tuple from evaluated field values */ tuple = heap_form_tuple(op->d.row.tupdesc, op->d.row.elemvalues, op->d.row.elemnulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } @@ -3085,12 +3098,24 @@ ExecEvalFieldStoreForm(ExprState *state, ExprEvalStep *op, ExprContext *econtext { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < (*op->d.fieldstore.argdesc)->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(*op->d.fieldstore.argdesc, i); + + if (op->d.fieldstore.nulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.fieldstore.values[i]))) + continue; + op->d.fieldstore.values[i] = PointerGetDatum( + PG_DETOAST_DATUM_PACKED(op->d.fieldstore.values[i])); + } + /* argdesc should already be valid from the DeForm step */ tuple = heap_form_tuple(*op->d.fieldstore.argdesc, op->d.fieldstore.values, op->d.fieldstore.nulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c index 511467280f..c3d464f42b 100644 --- a/src/backend/utils/adt/jsonfuncs.c +++ b/src/backend/utils/adt/jsonfuncs.c @@ -2968,7 +2968,7 @@ populate_composite(CompositeIOData *io, /* populate resulting record tuple */ tuple = populate_record(io->tupdesc, &io->record_io, defaultval, mcxt, &jso); - result = HeapTupleHeaderGetDatum(tuple); + result = HeapTupleHeaderGetRawDatum(tuple); JsObjectFree(&jso); } @@ -3387,6 +3387,10 @@ populate_record(TupleDesc tupdesc, nulls[i] ? (Datum) 0 : values[i], &field, &nulls[i]); + + if (!nulls[i] && att->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(values[i]))) + values[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(values[i])); } res = heap_form_tuple(tupdesc, values, nulls); @@ -3765,7 +3769,7 @@ populate_recordset_record(PopulateRecordsetState *state, JsObject *obj) /* if it's domain over composite, check domain constraints */ if (cache->c.typcat == TYPECAT_COMPOSITE_DOMAIN) - domain_check(HeapTupleHeaderGetDatum(tuphead), false, + domain_check(HeapTupleHeaderGetRawDatum(tuphead), false, cache->argtype, &cache->c.io.composite.domain_info, cache->fn_mcxt); diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index b4c70aaa7f..fd073767bc 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -5326,7 +5326,7 @@ exec_eval_datum(PLpgSQL_execstate *estate, elog(ERROR, "row not compatible with its own tupdesc"); *typeid = row->rowtupdesc->tdtypeid; *typetypmod = row->rowtupdesc->tdtypmod; - *value = HeapTupleGetDatum(tup); + *value = HeapTupleGetRawDatum(tup); *isnull = false; MemoryContextSwitchTo(oldcontext); break; @@ -7300,6 +7300,9 @@ make_tuple_from_row(PLpgSQL_execstate *estate, &dvalues[i], &nulls[i]); if (fieldtypeid != TupleDescAttr(tupdesc, i)->atttypid) return NULL; + if (!nulls[i] && TupleDescAttr(tupdesc, i)->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(dvalues[i]))) + dvalues[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(dvalues[i])); /* XXX should we insist on typmod match, too? */ } -- 2.17.0 --C94crkcyjafcjHxo Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-Disallow-compressed-data-inside-container-types.patch" ^ permalink raw reply [nested|flat] 49+ messages in thread
* [PATCH 2/8] Expand the external data before forming the tuple @ 2021-03-04 09:25 Dilip Kumar <[email protected]> 0 siblings, 0 replies; 49+ messages in thread From: Dilip Kumar @ 2021-03-04 09:25 UTC (permalink / raw) All the callers of HeapTupleGetDatum and HeapTupleHeaderGetDatum, who might contain the external varlena in their tuple, try to flatten the external varlena before forming the tuple wherever it is possible. Dilip Kumar based on idea by Robert Haas --- src/backend/executor/execExprInterp.c | 29 +++++++++++++++++++++++++-- src/backend/utils/adt/jsonfuncs.c | 8 ++++++-- src/pl/plpgsql/src/pl_exec.c | 5 ++++- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index 20949a5dec..c3754acca4 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -2840,12 +2840,25 @@ ExecEvalRow(ExprState *state, ExprEvalStep *op) { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < op->d.row.tupdesc->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(op->d.row.tupdesc, i); + + if (op->d.row.elemnulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.row.elemvalues[i]))) + continue; + + op->d.row.elemvalues[i] = + PointerGetDatum(PG_DETOAST_DATUM_PACKED(op->d.row.elemvalues[i])); + } + /* build tuple from evaluated field values */ tuple = heap_form_tuple(op->d.row.tupdesc, op->d.row.elemvalues, op->d.row.elemnulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } @@ -3085,12 +3098,24 @@ ExecEvalFieldStoreForm(ExprState *state, ExprEvalStep *op, ExprContext *econtext { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < (*op->d.fieldstore.argdesc)->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(*op->d.fieldstore.argdesc, i); + + if (op->d.fieldstore.nulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.fieldstore.values[i]))) + continue; + op->d.fieldstore.values[i] = PointerGetDatum( + PG_DETOAST_DATUM_PACKED(op->d.fieldstore.values[i])); + } + /* argdesc should already be valid from the DeForm step */ tuple = heap_form_tuple(*op->d.fieldstore.argdesc, op->d.fieldstore.values, op->d.fieldstore.nulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c index 511467280f..c3d464f42b 100644 --- a/src/backend/utils/adt/jsonfuncs.c +++ b/src/backend/utils/adt/jsonfuncs.c @@ -2968,7 +2968,7 @@ populate_composite(CompositeIOData *io, /* populate resulting record tuple */ tuple = populate_record(io->tupdesc, &io->record_io, defaultval, mcxt, &jso); - result = HeapTupleHeaderGetDatum(tuple); + result = HeapTupleHeaderGetRawDatum(tuple); JsObjectFree(&jso); } @@ -3387,6 +3387,10 @@ populate_record(TupleDesc tupdesc, nulls[i] ? (Datum) 0 : values[i], &field, &nulls[i]); + + if (!nulls[i] && att->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(values[i]))) + values[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(values[i])); } res = heap_form_tuple(tupdesc, values, nulls); @@ -3765,7 +3769,7 @@ populate_recordset_record(PopulateRecordsetState *state, JsObject *obj) /* if it's domain over composite, check domain constraints */ if (cache->c.typcat == TYPECAT_COMPOSITE_DOMAIN) - domain_check(HeapTupleHeaderGetDatum(tuphead), false, + domain_check(HeapTupleHeaderGetRawDatum(tuphead), false, cache->argtype, &cache->c.io.composite.domain_info, cache->fn_mcxt); diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index b4c70aaa7f..fd073767bc 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -5326,7 +5326,7 @@ exec_eval_datum(PLpgSQL_execstate *estate, elog(ERROR, "row not compatible with its own tupdesc"); *typeid = row->rowtupdesc->tdtypeid; *typetypmod = row->rowtupdesc->tdtypmod; - *value = HeapTupleGetDatum(tup); + *value = HeapTupleGetRawDatum(tup); *isnull = false; MemoryContextSwitchTo(oldcontext); break; @@ -7300,6 +7300,9 @@ make_tuple_from_row(PLpgSQL_execstate *estate, &dvalues[i], &nulls[i]); if (fieldtypeid != TupleDescAttr(tupdesc, i)->atttypid) return NULL; + if (!nulls[i] && TupleDescAttr(tupdesc, i)->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(dvalues[i]))) + dvalues[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(dvalues[i])); /* XXX should we insist on typmod match, too? */ } -- 2.17.0 --cvVnyQ+4j833TQvp Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-Disallow-compressed-data-inside-container-types.patch" ^ permalink raw reply [nested|flat] 49+ messages in thread
* [PATCH 2/8] Expand the external data before forming the tuple @ 2021-03-04 09:25 Dilip Kumar <[email protected]> 0 siblings, 0 replies; 49+ messages in thread From: Dilip Kumar @ 2021-03-04 09:25 UTC (permalink / raw) All the callers of HeapTupleGetDatum and HeapTupleHeaderGetDatum, who might contain the external varlena in their tuple, try to flatten the external varlena before forming the tuple wherever it is possible. Dilip Kumar based on idea by Robert Haas --- src/backend/executor/execExprInterp.c | 29 +++++++++++++++++++++++++-- src/backend/utils/adt/jsonfuncs.c | 8 ++++++-- src/pl/plpgsql/src/pl_exec.c | 5 ++++- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index 20949a5dec..c3754acca4 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -2840,12 +2840,25 @@ ExecEvalRow(ExprState *state, ExprEvalStep *op) { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < op->d.row.tupdesc->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(op->d.row.tupdesc, i); + + if (op->d.row.elemnulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.row.elemvalues[i]))) + continue; + + op->d.row.elemvalues[i] = + PointerGetDatum(PG_DETOAST_DATUM_PACKED(op->d.row.elemvalues[i])); + } + /* build tuple from evaluated field values */ tuple = heap_form_tuple(op->d.row.tupdesc, op->d.row.elemvalues, op->d.row.elemnulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } @@ -3085,12 +3098,24 @@ ExecEvalFieldStoreForm(ExprState *state, ExprEvalStep *op, ExprContext *econtext { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < (*op->d.fieldstore.argdesc)->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(*op->d.fieldstore.argdesc, i); + + if (op->d.fieldstore.nulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.fieldstore.values[i]))) + continue; + op->d.fieldstore.values[i] = PointerGetDatum( + PG_DETOAST_DATUM_PACKED(op->d.fieldstore.values[i])); + } + /* argdesc should already be valid from the DeForm step */ tuple = heap_form_tuple(*op->d.fieldstore.argdesc, op->d.fieldstore.values, op->d.fieldstore.nulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c index 511467280f..c3d464f42b 100644 --- a/src/backend/utils/adt/jsonfuncs.c +++ b/src/backend/utils/adt/jsonfuncs.c @@ -2968,7 +2968,7 @@ populate_composite(CompositeIOData *io, /* populate resulting record tuple */ tuple = populate_record(io->tupdesc, &io->record_io, defaultval, mcxt, &jso); - result = HeapTupleHeaderGetDatum(tuple); + result = HeapTupleHeaderGetRawDatum(tuple); JsObjectFree(&jso); } @@ -3387,6 +3387,10 @@ populate_record(TupleDesc tupdesc, nulls[i] ? (Datum) 0 : values[i], &field, &nulls[i]); + + if (!nulls[i] && att->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(values[i]))) + values[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(values[i])); } res = heap_form_tuple(tupdesc, values, nulls); @@ -3765,7 +3769,7 @@ populate_recordset_record(PopulateRecordsetState *state, JsObject *obj) /* if it's domain over composite, check domain constraints */ if (cache->c.typcat == TYPECAT_COMPOSITE_DOMAIN) - domain_check(HeapTupleHeaderGetDatum(tuphead), false, + domain_check(HeapTupleHeaderGetRawDatum(tuphead), false, cache->argtype, &cache->c.io.composite.domain_info, cache->fn_mcxt); diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index b4c70aaa7f..fd073767bc 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -5326,7 +5326,7 @@ exec_eval_datum(PLpgSQL_execstate *estate, elog(ERROR, "row not compatible with its own tupdesc"); *typeid = row->rowtupdesc->tdtypeid; *typetypmod = row->rowtupdesc->tdtypmod; - *value = HeapTupleGetDatum(tup); + *value = HeapTupleGetRawDatum(tup); *isnull = false; MemoryContextSwitchTo(oldcontext); break; @@ -7300,6 +7300,9 @@ make_tuple_from_row(PLpgSQL_execstate *estate, &dvalues[i], &nulls[i]); if (fieldtypeid != TupleDescAttr(tupdesc, i)->atttypid) return NULL; + if (!nulls[i] && TupleDescAttr(tupdesc, i)->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(dvalues[i]))) + dvalues[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(dvalues[i])); /* XXX should we insist on typmod match, too? */ } -- 2.17.0 --C94crkcyjafcjHxo Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-Disallow-compressed-data-inside-container-types.patch" ^ permalink raw reply [nested|flat] 49+ messages in thread
* [PATCH 2/8] Expand the external data before forming the tuple @ 2021-03-04 09:25 Dilip Kumar <[email protected]> 0 siblings, 0 replies; 49+ messages in thread From: Dilip Kumar @ 2021-03-04 09:25 UTC (permalink / raw) All the callers of HeapTupleGetDatum and HeapTupleHeaderGetDatum, who might contain the external varlena in their tuple, try to flatten the external varlena before forming the tuple wherever it is possible. Dilip Kumar based on idea by Robert Haas --- src/backend/executor/execExprInterp.c | 29 +++++++++++++++++++++++++-- src/backend/utils/adt/jsonfuncs.c | 8 ++++++-- src/pl/plpgsql/src/pl_exec.c | 5 ++++- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index 20949a5dec..c3754acca4 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -2840,12 +2840,25 @@ ExecEvalRow(ExprState *state, ExprEvalStep *op) { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < op->d.row.tupdesc->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(op->d.row.tupdesc, i); + + if (op->d.row.elemnulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.row.elemvalues[i]))) + continue; + + op->d.row.elemvalues[i] = + PointerGetDatum(PG_DETOAST_DATUM_PACKED(op->d.row.elemvalues[i])); + } + /* build tuple from evaluated field values */ tuple = heap_form_tuple(op->d.row.tupdesc, op->d.row.elemvalues, op->d.row.elemnulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } @@ -3085,12 +3098,24 @@ ExecEvalFieldStoreForm(ExprState *state, ExprEvalStep *op, ExprContext *econtext { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < (*op->d.fieldstore.argdesc)->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(*op->d.fieldstore.argdesc, i); + + if (op->d.fieldstore.nulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.fieldstore.values[i]))) + continue; + op->d.fieldstore.values[i] = PointerGetDatum( + PG_DETOAST_DATUM_PACKED(op->d.fieldstore.values[i])); + } + /* argdesc should already be valid from the DeForm step */ tuple = heap_form_tuple(*op->d.fieldstore.argdesc, op->d.fieldstore.values, op->d.fieldstore.nulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c index 511467280f..c3d464f42b 100644 --- a/src/backend/utils/adt/jsonfuncs.c +++ b/src/backend/utils/adt/jsonfuncs.c @@ -2968,7 +2968,7 @@ populate_composite(CompositeIOData *io, /* populate resulting record tuple */ tuple = populate_record(io->tupdesc, &io->record_io, defaultval, mcxt, &jso); - result = HeapTupleHeaderGetDatum(tuple); + result = HeapTupleHeaderGetRawDatum(tuple); JsObjectFree(&jso); } @@ -3387,6 +3387,10 @@ populate_record(TupleDesc tupdesc, nulls[i] ? (Datum) 0 : values[i], &field, &nulls[i]); + + if (!nulls[i] && att->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(values[i]))) + values[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(values[i])); } res = heap_form_tuple(tupdesc, values, nulls); @@ -3765,7 +3769,7 @@ populate_recordset_record(PopulateRecordsetState *state, JsObject *obj) /* if it's domain over composite, check domain constraints */ if (cache->c.typcat == TYPECAT_COMPOSITE_DOMAIN) - domain_check(HeapTupleHeaderGetDatum(tuphead), false, + domain_check(HeapTupleHeaderGetRawDatum(tuphead), false, cache->argtype, &cache->c.io.composite.domain_info, cache->fn_mcxt); diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index b4c70aaa7f..fd073767bc 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -5326,7 +5326,7 @@ exec_eval_datum(PLpgSQL_execstate *estate, elog(ERROR, "row not compatible with its own tupdesc"); *typeid = row->rowtupdesc->tdtypeid; *typetypmod = row->rowtupdesc->tdtypmod; - *value = HeapTupleGetDatum(tup); + *value = HeapTupleGetRawDatum(tup); *isnull = false; MemoryContextSwitchTo(oldcontext); break; @@ -7300,6 +7300,9 @@ make_tuple_from_row(PLpgSQL_execstate *estate, &dvalues[i], &nulls[i]); if (fieldtypeid != TupleDescAttr(tupdesc, i)->atttypid) return NULL; + if (!nulls[i] && TupleDescAttr(tupdesc, i)->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(dvalues[i]))) + dvalues[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(dvalues[i])); /* XXX should we insist on typmod match, too? */ } -- 2.17.0 --cvVnyQ+4j833TQvp Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-Disallow-compressed-data-inside-container-types.patch" ^ permalink raw reply [nested|flat] 49+ messages in thread
* [PATCH 2/8] Expand the external data before forming the tuple @ 2021-03-04 09:25 Dilip Kumar <[email protected]> 0 siblings, 0 replies; 49+ messages in thread From: Dilip Kumar @ 2021-03-04 09:25 UTC (permalink / raw) All the callers of HeapTupleGetDatum and HeapTupleHeaderGetDatum, who might contain the external varlena in their tuple, try to flatten the external varlena before forming the tuple wherever it is possible. Dilip Kumar based on idea by Robert Haas --- src/backend/executor/execExprInterp.c | 29 +++++++++++++++++++++++++-- src/backend/utils/adt/jsonfuncs.c | 8 ++++++-- src/pl/plpgsql/src/pl_exec.c | 5 ++++- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index 20949a5dec..c3754acca4 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -2840,12 +2840,25 @@ ExecEvalRow(ExprState *state, ExprEvalStep *op) { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < op->d.row.tupdesc->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(op->d.row.tupdesc, i); + + if (op->d.row.elemnulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.row.elemvalues[i]))) + continue; + + op->d.row.elemvalues[i] = + PointerGetDatum(PG_DETOAST_DATUM_PACKED(op->d.row.elemvalues[i])); + } + /* build tuple from evaluated field values */ tuple = heap_form_tuple(op->d.row.tupdesc, op->d.row.elemvalues, op->d.row.elemnulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } @@ -3085,12 +3098,24 @@ ExecEvalFieldStoreForm(ExprState *state, ExprEvalStep *op, ExprContext *econtext { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < (*op->d.fieldstore.argdesc)->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(*op->d.fieldstore.argdesc, i); + + if (op->d.fieldstore.nulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.fieldstore.values[i]))) + continue; + op->d.fieldstore.values[i] = PointerGetDatum( + PG_DETOAST_DATUM_PACKED(op->d.fieldstore.values[i])); + } + /* argdesc should already be valid from the DeForm step */ tuple = heap_form_tuple(*op->d.fieldstore.argdesc, op->d.fieldstore.values, op->d.fieldstore.nulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c index 511467280f..c3d464f42b 100644 --- a/src/backend/utils/adt/jsonfuncs.c +++ b/src/backend/utils/adt/jsonfuncs.c @@ -2968,7 +2968,7 @@ populate_composite(CompositeIOData *io, /* populate resulting record tuple */ tuple = populate_record(io->tupdesc, &io->record_io, defaultval, mcxt, &jso); - result = HeapTupleHeaderGetDatum(tuple); + result = HeapTupleHeaderGetRawDatum(tuple); JsObjectFree(&jso); } @@ -3387,6 +3387,10 @@ populate_record(TupleDesc tupdesc, nulls[i] ? (Datum) 0 : values[i], &field, &nulls[i]); + + if (!nulls[i] && att->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(values[i]))) + values[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(values[i])); } res = heap_form_tuple(tupdesc, values, nulls); @@ -3765,7 +3769,7 @@ populate_recordset_record(PopulateRecordsetState *state, JsObject *obj) /* if it's domain over composite, check domain constraints */ if (cache->c.typcat == TYPECAT_COMPOSITE_DOMAIN) - domain_check(HeapTupleHeaderGetDatum(tuphead), false, + domain_check(HeapTupleHeaderGetRawDatum(tuphead), false, cache->argtype, &cache->c.io.composite.domain_info, cache->fn_mcxt); diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index b4c70aaa7f..fd073767bc 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -5326,7 +5326,7 @@ exec_eval_datum(PLpgSQL_execstate *estate, elog(ERROR, "row not compatible with its own tupdesc"); *typeid = row->rowtupdesc->tdtypeid; *typetypmod = row->rowtupdesc->tdtypmod; - *value = HeapTupleGetDatum(tup); + *value = HeapTupleGetRawDatum(tup); *isnull = false; MemoryContextSwitchTo(oldcontext); break; @@ -7300,6 +7300,9 @@ make_tuple_from_row(PLpgSQL_execstate *estate, &dvalues[i], &nulls[i]); if (fieldtypeid != TupleDescAttr(tupdesc, i)->atttypid) return NULL; + if (!nulls[i] && TupleDescAttr(tupdesc, i)->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(dvalues[i]))) + dvalues[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(dvalues[i])); /* XXX should we insist on typmod match, too? */ } -- 2.17.0 --C94crkcyjafcjHxo Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-Disallow-compressed-data-inside-container-types.patch" ^ permalink raw reply [nested|flat] 49+ messages in thread
* [PATCH 2/8] Expand the external data before forming the tuple @ 2021-03-04 09:25 Dilip Kumar <[email protected]> 0 siblings, 0 replies; 49+ messages in thread From: Dilip Kumar @ 2021-03-04 09:25 UTC (permalink / raw) All the callers of HeapTupleGetDatum and HeapTupleHeaderGetDatum, who might contain the external varlena in their tuple, try to flatten the external varlena before forming the tuple wherever it is possible. Dilip Kumar based on idea by Robert Haas --- src/backend/executor/execExprInterp.c | 29 +++++++++++++++++++++++++-- src/backend/utils/adt/jsonfuncs.c | 8 ++++++-- src/pl/plpgsql/src/pl_exec.c | 5 ++++- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index 20949a5dec..c3754acca4 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -2840,12 +2840,25 @@ ExecEvalRow(ExprState *state, ExprEvalStep *op) { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < op->d.row.tupdesc->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(op->d.row.tupdesc, i); + + if (op->d.row.elemnulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.row.elemvalues[i]))) + continue; + + op->d.row.elemvalues[i] = + PointerGetDatum(PG_DETOAST_DATUM_PACKED(op->d.row.elemvalues[i])); + } + /* build tuple from evaluated field values */ tuple = heap_form_tuple(op->d.row.tupdesc, op->d.row.elemvalues, op->d.row.elemnulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } @@ -3085,12 +3098,24 @@ ExecEvalFieldStoreForm(ExprState *state, ExprEvalStep *op, ExprContext *econtext { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < (*op->d.fieldstore.argdesc)->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(*op->d.fieldstore.argdesc, i); + + if (op->d.fieldstore.nulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.fieldstore.values[i]))) + continue; + op->d.fieldstore.values[i] = PointerGetDatum( + PG_DETOAST_DATUM_PACKED(op->d.fieldstore.values[i])); + } + /* argdesc should already be valid from the DeForm step */ tuple = heap_form_tuple(*op->d.fieldstore.argdesc, op->d.fieldstore.values, op->d.fieldstore.nulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c index 511467280f..c3d464f42b 100644 --- a/src/backend/utils/adt/jsonfuncs.c +++ b/src/backend/utils/adt/jsonfuncs.c @@ -2968,7 +2968,7 @@ populate_composite(CompositeIOData *io, /* populate resulting record tuple */ tuple = populate_record(io->tupdesc, &io->record_io, defaultval, mcxt, &jso); - result = HeapTupleHeaderGetDatum(tuple); + result = HeapTupleHeaderGetRawDatum(tuple); JsObjectFree(&jso); } @@ -3387,6 +3387,10 @@ populate_record(TupleDesc tupdesc, nulls[i] ? (Datum) 0 : values[i], &field, &nulls[i]); + + if (!nulls[i] && att->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(values[i]))) + values[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(values[i])); } res = heap_form_tuple(tupdesc, values, nulls); @@ -3765,7 +3769,7 @@ populate_recordset_record(PopulateRecordsetState *state, JsObject *obj) /* if it's domain over composite, check domain constraints */ if (cache->c.typcat == TYPECAT_COMPOSITE_DOMAIN) - domain_check(HeapTupleHeaderGetDatum(tuphead), false, + domain_check(HeapTupleHeaderGetRawDatum(tuphead), false, cache->argtype, &cache->c.io.composite.domain_info, cache->fn_mcxt); diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index b4c70aaa7f..fd073767bc 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -5326,7 +5326,7 @@ exec_eval_datum(PLpgSQL_execstate *estate, elog(ERROR, "row not compatible with its own tupdesc"); *typeid = row->rowtupdesc->tdtypeid; *typetypmod = row->rowtupdesc->tdtypmod; - *value = HeapTupleGetDatum(tup); + *value = HeapTupleGetRawDatum(tup); *isnull = false; MemoryContextSwitchTo(oldcontext); break; @@ -7300,6 +7300,9 @@ make_tuple_from_row(PLpgSQL_execstate *estate, &dvalues[i], &nulls[i]); if (fieldtypeid != TupleDescAttr(tupdesc, i)->atttypid) return NULL; + if (!nulls[i] && TupleDescAttr(tupdesc, i)->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(dvalues[i]))) + dvalues[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(dvalues[i])); /* XXX should we insist on typmod match, too? */ } -- 2.17.0 --cvVnyQ+4j833TQvp Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-Disallow-compressed-data-inside-container-types.patch" ^ permalink raw reply [nested|flat] 49+ messages in thread
* [PATCH 2/8] Expand the external data before forming the tuple @ 2021-03-04 09:25 Dilip Kumar <[email protected]> 0 siblings, 0 replies; 49+ messages in thread From: Dilip Kumar @ 2021-03-04 09:25 UTC (permalink / raw) All the callers of HeapTupleGetDatum and HeapTupleHeaderGetDatum, who might contain the external varlena in their tuple, try to flatten the external varlena before forming the tuple wherever it is possible. Dilip Kumar based on idea by Robert Haas --- src/backend/executor/execExprInterp.c | 29 +++++++++++++++++++++++++-- src/backend/utils/adt/jsonfuncs.c | 8 ++++++-- src/pl/plpgsql/src/pl_exec.c | 5 ++++- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index 20949a5dec..c3754acca4 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -2840,12 +2840,25 @@ ExecEvalRow(ExprState *state, ExprEvalStep *op) { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < op->d.row.tupdesc->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(op->d.row.tupdesc, i); + + if (op->d.row.elemnulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.row.elemvalues[i]))) + continue; + + op->d.row.elemvalues[i] = + PointerGetDatum(PG_DETOAST_DATUM_PACKED(op->d.row.elemvalues[i])); + } + /* build tuple from evaluated field values */ tuple = heap_form_tuple(op->d.row.tupdesc, op->d.row.elemvalues, op->d.row.elemnulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } @@ -3085,12 +3098,24 @@ ExecEvalFieldStoreForm(ExprState *state, ExprEvalStep *op, ExprContext *econtext { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < (*op->d.fieldstore.argdesc)->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(*op->d.fieldstore.argdesc, i); + + if (op->d.fieldstore.nulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.fieldstore.values[i]))) + continue; + op->d.fieldstore.values[i] = PointerGetDatum( + PG_DETOAST_DATUM_PACKED(op->d.fieldstore.values[i])); + } + /* argdesc should already be valid from the DeForm step */ tuple = heap_form_tuple(*op->d.fieldstore.argdesc, op->d.fieldstore.values, op->d.fieldstore.nulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c index 511467280f..c3d464f42b 100644 --- a/src/backend/utils/adt/jsonfuncs.c +++ b/src/backend/utils/adt/jsonfuncs.c @@ -2968,7 +2968,7 @@ populate_composite(CompositeIOData *io, /* populate resulting record tuple */ tuple = populate_record(io->tupdesc, &io->record_io, defaultval, mcxt, &jso); - result = HeapTupleHeaderGetDatum(tuple); + result = HeapTupleHeaderGetRawDatum(tuple); JsObjectFree(&jso); } @@ -3387,6 +3387,10 @@ populate_record(TupleDesc tupdesc, nulls[i] ? (Datum) 0 : values[i], &field, &nulls[i]); + + if (!nulls[i] && att->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(values[i]))) + values[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(values[i])); } res = heap_form_tuple(tupdesc, values, nulls); @@ -3765,7 +3769,7 @@ populate_recordset_record(PopulateRecordsetState *state, JsObject *obj) /* if it's domain over composite, check domain constraints */ if (cache->c.typcat == TYPECAT_COMPOSITE_DOMAIN) - domain_check(HeapTupleHeaderGetDatum(tuphead), false, + domain_check(HeapTupleHeaderGetRawDatum(tuphead), false, cache->argtype, &cache->c.io.composite.domain_info, cache->fn_mcxt); diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index b4c70aaa7f..fd073767bc 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -5326,7 +5326,7 @@ exec_eval_datum(PLpgSQL_execstate *estate, elog(ERROR, "row not compatible with its own tupdesc"); *typeid = row->rowtupdesc->tdtypeid; *typetypmod = row->rowtupdesc->tdtypmod; - *value = HeapTupleGetDatum(tup); + *value = HeapTupleGetRawDatum(tup); *isnull = false; MemoryContextSwitchTo(oldcontext); break; @@ -7300,6 +7300,9 @@ make_tuple_from_row(PLpgSQL_execstate *estate, &dvalues[i], &nulls[i]); if (fieldtypeid != TupleDescAttr(tupdesc, i)->atttypid) return NULL; + if (!nulls[i] && TupleDescAttr(tupdesc, i)->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(dvalues[i]))) + dvalues[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(dvalues[i])); /* XXX should we insist on typmod match, too? */ } -- 2.17.0 --C94crkcyjafcjHxo Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-Disallow-compressed-data-inside-container-types.patch" ^ permalink raw reply [nested|flat] 49+ messages in thread
* [PATCH 2/8] Expand the external data before forming the tuple @ 2021-03-04 09:25 Dilip Kumar <[email protected]> 0 siblings, 0 replies; 49+ messages in thread From: Dilip Kumar @ 2021-03-04 09:25 UTC (permalink / raw) All the callers of HeapTupleGetDatum and HeapTupleHeaderGetDatum, who might contain the external varlena in their tuple, try to flatten the external varlena before forming the tuple wherever it is possible. Dilip Kumar based on idea by Robert Haas --- src/backend/executor/execExprInterp.c | 29 +++++++++++++++++++++++++-- src/backend/utils/adt/jsonfuncs.c | 8 ++++++-- src/pl/plpgsql/src/pl_exec.c | 5 ++++- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index 20949a5dec..c3754acca4 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -2840,12 +2840,25 @@ ExecEvalRow(ExprState *state, ExprEvalStep *op) { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < op->d.row.tupdesc->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(op->d.row.tupdesc, i); + + if (op->d.row.elemnulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.row.elemvalues[i]))) + continue; + + op->d.row.elemvalues[i] = + PointerGetDatum(PG_DETOAST_DATUM_PACKED(op->d.row.elemvalues[i])); + } + /* build tuple from evaluated field values */ tuple = heap_form_tuple(op->d.row.tupdesc, op->d.row.elemvalues, op->d.row.elemnulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } @@ -3085,12 +3098,24 @@ ExecEvalFieldStoreForm(ExprState *state, ExprEvalStep *op, ExprContext *econtext { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < (*op->d.fieldstore.argdesc)->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(*op->d.fieldstore.argdesc, i); + + if (op->d.fieldstore.nulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.fieldstore.values[i]))) + continue; + op->d.fieldstore.values[i] = PointerGetDatum( + PG_DETOAST_DATUM_PACKED(op->d.fieldstore.values[i])); + } + /* argdesc should already be valid from the DeForm step */ tuple = heap_form_tuple(*op->d.fieldstore.argdesc, op->d.fieldstore.values, op->d.fieldstore.nulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c index 511467280f..c3d464f42b 100644 --- a/src/backend/utils/adt/jsonfuncs.c +++ b/src/backend/utils/adt/jsonfuncs.c @@ -2968,7 +2968,7 @@ populate_composite(CompositeIOData *io, /* populate resulting record tuple */ tuple = populate_record(io->tupdesc, &io->record_io, defaultval, mcxt, &jso); - result = HeapTupleHeaderGetDatum(tuple); + result = HeapTupleHeaderGetRawDatum(tuple); JsObjectFree(&jso); } @@ -3387,6 +3387,10 @@ populate_record(TupleDesc tupdesc, nulls[i] ? (Datum) 0 : values[i], &field, &nulls[i]); + + if (!nulls[i] && att->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(values[i]))) + values[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(values[i])); } res = heap_form_tuple(tupdesc, values, nulls); @@ -3765,7 +3769,7 @@ populate_recordset_record(PopulateRecordsetState *state, JsObject *obj) /* if it's domain over composite, check domain constraints */ if (cache->c.typcat == TYPECAT_COMPOSITE_DOMAIN) - domain_check(HeapTupleHeaderGetDatum(tuphead), false, + domain_check(HeapTupleHeaderGetRawDatum(tuphead), false, cache->argtype, &cache->c.io.composite.domain_info, cache->fn_mcxt); diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index b4c70aaa7f..fd073767bc 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -5326,7 +5326,7 @@ exec_eval_datum(PLpgSQL_execstate *estate, elog(ERROR, "row not compatible with its own tupdesc"); *typeid = row->rowtupdesc->tdtypeid; *typetypmod = row->rowtupdesc->tdtypmod; - *value = HeapTupleGetDatum(tup); + *value = HeapTupleGetRawDatum(tup); *isnull = false; MemoryContextSwitchTo(oldcontext); break; @@ -7300,6 +7300,9 @@ make_tuple_from_row(PLpgSQL_execstate *estate, &dvalues[i], &nulls[i]); if (fieldtypeid != TupleDescAttr(tupdesc, i)->atttypid) return NULL; + if (!nulls[i] && TupleDescAttr(tupdesc, i)->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(dvalues[i]))) + dvalues[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(dvalues[i])); /* XXX should we insist on typmod match, too? */ } -- 2.17.0 --cvVnyQ+4j833TQvp Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-Disallow-compressed-data-inside-container-types.patch" ^ permalink raw reply [nested|flat] 49+ messages in thread
* [PATCH 2/8] Expand the external data before forming the tuple @ 2021-03-04 09:25 Dilip Kumar <[email protected]> 0 siblings, 0 replies; 49+ messages in thread From: Dilip Kumar @ 2021-03-04 09:25 UTC (permalink / raw) All the callers of HeapTupleGetDatum and HeapTupleHeaderGetDatum, who might contain the external varlena in their tuple, try to flatten the external varlena before forming the tuple wherever it is possible. Dilip Kumar based on idea by Robert Haas --- src/backend/executor/execExprInterp.c | 29 +++++++++++++++++++++++++-- src/backend/utils/adt/jsonfuncs.c | 8 ++++++-- src/pl/plpgsql/src/pl_exec.c | 5 ++++- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index 20949a5dec..c3754acca4 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -2840,12 +2840,25 @@ ExecEvalRow(ExprState *state, ExprEvalStep *op) { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < op->d.row.tupdesc->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(op->d.row.tupdesc, i); + + if (op->d.row.elemnulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.row.elemvalues[i]))) + continue; + + op->d.row.elemvalues[i] = + PointerGetDatum(PG_DETOAST_DATUM_PACKED(op->d.row.elemvalues[i])); + } + /* build tuple from evaluated field values */ tuple = heap_form_tuple(op->d.row.tupdesc, op->d.row.elemvalues, op->d.row.elemnulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } @@ -3085,12 +3098,24 @@ ExecEvalFieldStoreForm(ExprState *state, ExprEvalStep *op, ExprContext *econtext { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < (*op->d.fieldstore.argdesc)->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(*op->d.fieldstore.argdesc, i); + + if (op->d.fieldstore.nulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.fieldstore.values[i]))) + continue; + op->d.fieldstore.values[i] = PointerGetDatum( + PG_DETOAST_DATUM_PACKED(op->d.fieldstore.values[i])); + } + /* argdesc should already be valid from the DeForm step */ tuple = heap_form_tuple(*op->d.fieldstore.argdesc, op->d.fieldstore.values, op->d.fieldstore.nulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c index 511467280f..c3d464f42b 100644 --- a/src/backend/utils/adt/jsonfuncs.c +++ b/src/backend/utils/adt/jsonfuncs.c @@ -2968,7 +2968,7 @@ populate_composite(CompositeIOData *io, /* populate resulting record tuple */ tuple = populate_record(io->tupdesc, &io->record_io, defaultval, mcxt, &jso); - result = HeapTupleHeaderGetDatum(tuple); + result = HeapTupleHeaderGetRawDatum(tuple); JsObjectFree(&jso); } @@ -3387,6 +3387,10 @@ populate_record(TupleDesc tupdesc, nulls[i] ? (Datum) 0 : values[i], &field, &nulls[i]); + + if (!nulls[i] && att->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(values[i]))) + values[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(values[i])); } res = heap_form_tuple(tupdesc, values, nulls); @@ -3765,7 +3769,7 @@ populate_recordset_record(PopulateRecordsetState *state, JsObject *obj) /* if it's domain over composite, check domain constraints */ if (cache->c.typcat == TYPECAT_COMPOSITE_DOMAIN) - domain_check(HeapTupleHeaderGetDatum(tuphead), false, + domain_check(HeapTupleHeaderGetRawDatum(tuphead), false, cache->argtype, &cache->c.io.composite.domain_info, cache->fn_mcxt); diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index b4c70aaa7f..fd073767bc 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -5326,7 +5326,7 @@ exec_eval_datum(PLpgSQL_execstate *estate, elog(ERROR, "row not compatible with its own tupdesc"); *typeid = row->rowtupdesc->tdtypeid; *typetypmod = row->rowtupdesc->tdtypmod; - *value = HeapTupleGetDatum(tup); + *value = HeapTupleGetRawDatum(tup); *isnull = false; MemoryContextSwitchTo(oldcontext); break; @@ -7300,6 +7300,9 @@ make_tuple_from_row(PLpgSQL_execstate *estate, &dvalues[i], &nulls[i]); if (fieldtypeid != TupleDescAttr(tupdesc, i)->atttypid) return NULL; + if (!nulls[i] && TupleDescAttr(tupdesc, i)->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(dvalues[i]))) + dvalues[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(dvalues[i])); /* XXX should we insist on typmod match, too? */ } -- 2.17.0 --C94crkcyjafcjHxo Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-Disallow-compressed-data-inside-container-types.patch" ^ permalink raw reply [nested|flat] 49+ messages in thread
* [PATCH 2/8] Expand the external data before forming the tuple @ 2021-03-04 09:25 Dilip Kumar <[email protected]> 0 siblings, 0 replies; 49+ messages in thread From: Dilip Kumar @ 2021-03-04 09:25 UTC (permalink / raw) All the callers of HeapTupleGetDatum and HeapTupleHeaderGetDatum, who might contain the external varlena in their tuple, try to flatten the external varlena before forming the tuple wherever it is possible. Dilip Kumar based on idea by Robert Haas --- src/backend/executor/execExprInterp.c | 29 +++++++++++++++++++++++++-- src/backend/utils/adt/jsonfuncs.c | 8 ++++++-- src/pl/plpgsql/src/pl_exec.c | 5 ++++- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index 20949a5dec..c3754acca4 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -2840,12 +2840,25 @@ ExecEvalRow(ExprState *state, ExprEvalStep *op) { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < op->d.row.tupdesc->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(op->d.row.tupdesc, i); + + if (op->d.row.elemnulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.row.elemvalues[i]))) + continue; + + op->d.row.elemvalues[i] = + PointerGetDatum(PG_DETOAST_DATUM_PACKED(op->d.row.elemvalues[i])); + } + /* build tuple from evaluated field values */ tuple = heap_form_tuple(op->d.row.tupdesc, op->d.row.elemvalues, op->d.row.elemnulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } @@ -3085,12 +3098,24 @@ ExecEvalFieldStoreForm(ExprState *state, ExprEvalStep *op, ExprContext *econtext { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < (*op->d.fieldstore.argdesc)->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(*op->d.fieldstore.argdesc, i); + + if (op->d.fieldstore.nulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.fieldstore.values[i]))) + continue; + op->d.fieldstore.values[i] = PointerGetDatum( + PG_DETOAST_DATUM_PACKED(op->d.fieldstore.values[i])); + } + /* argdesc should already be valid from the DeForm step */ tuple = heap_form_tuple(*op->d.fieldstore.argdesc, op->d.fieldstore.values, op->d.fieldstore.nulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c index 511467280f..c3d464f42b 100644 --- a/src/backend/utils/adt/jsonfuncs.c +++ b/src/backend/utils/adt/jsonfuncs.c @@ -2968,7 +2968,7 @@ populate_composite(CompositeIOData *io, /* populate resulting record tuple */ tuple = populate_record(io->tupdesc, &io->record_io, defaultval, mcxt, &jso); - result = HeapTupleHeaderGetDatum(tuple); + result = HeapTupleHeaderGetRawDatum(tuple); JsObjectFree(&jso); } @@ -3387,6 +3387,10 @@ populate_record(TupleDesc tupdesc, nulls[i] ? (Datum) 0 : values[i], &field, &nulls[i]); + + if (!nulls[i] && att->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(values[i]))) + values[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(values[i])); } res = heap_form_tuple(tupdesc, values, nulls); @@ -3765,7 +3769,7 @@ populate_recordset_record(PopulateRecordsetState *state, JsObject *obj) /* if it's domain over composite, check domain constraints */ if (cache->c.typcat == TYPECAT_COMPOSITE_DOMAIN) - domain_check(HeapTupleHeaderGetDatum(tuphead), false, + domain_check(HeapTupleHeaderGetRawDatum(tuphead), false, cache->argtype, &cache->c.io.composite.domain_info, cache->fn_mcxt); diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index b4c70aaa7f..fd073767bc 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -5326,7 +5326,7 @@ exec_eval_datum(PLpgSQL_execstate *estate, elog(ERROR, "row not compatible with its own tupdesc"); *typeid = row->rowtupdesc->tdtypeid; *typetypmod = row->rowtupdesc->tdtypmod; - *value = HeapTupleGetDatum(tup); + *value = HeapTupleGetRawDatum(tup); *isnull = false; MemoryContextSwitchTo(oldcontext); break; @@ -7300,6 +7300,9 @@ make_tuple_from_row(PLpgSQL_execstate *estate, &dvalues[i], &nulls[i]); if (fieldtypeid != TupleDescAttr(tupdesc, i)->atttypid) return NULL; + if (!nulls[i] && TupleDescAttr(tupdesc, i)->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(dvalues[i]))) + dvalues[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(dvalues[i])); /* XXX should we insist on typmod match, too? */ } -- 2.17.0 --cvVnyQ+4j833TQvp Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-Disallow-compressed-data-inside-container-types.patch" ^ permalink raw reply [nested|flat] 49+ messages in thread
* [PATCH 2/8] Expand the external data before forming the tuple @ 2021-03-04 09:25 Dilip Kumar <[email protected]> 0 siblings, 0 replies; 49+ messages in thread From: Dilip Kumar @ 2021-03-04 09:25 UTC (permalink / raw) All the callers of HeapTupleGetDatum and HeapTupleHeaderGetDatum, who might contain the external varlena in their tuple, try to flatten the external varlena before forming the tuple wherever it is possible. Dilip Kumar based on idea by Robert Haas --- src/backend/executor/execExprInterp.c | 29 +++++++++++++++++++++++++-- src/backend/utils/adt/jsonfuncs.c | 8 ++++++-- src/pl/plpgsql/src/pl_exec.c | 5 ++++- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index 20949a5dec..c3754acca4 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -2840,12 +2840,25 @@ ExecEvalRow(ExprState *state, ExprEvalStep *op) { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < op->d.row.tupdesc->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(op->d.row.tupdesc, i); + + if (op->d.row.elemnulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.row.elemvalues[i]))) + continue; + + op->d.row.elemvalues[i] = + PointerGetDatum(PG_DETOAST_DATUM_PACKED(op->d.row.elemvalues[i])); + } + /* build tuple from evaluated field values */ tuple = heap_form_tuple(op->d.row.tupdesc, op->d.row.elemvalues, op->d.row.elemnulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } @@ -3085,12 +3098,24 @@ ExecEvalFieldStoreForm(ExprState *state, ExprEvalStep *op, ExprContext *econtext { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < (*op->d.fieldstore.argdesc)->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(*op->d.fieldstore.argdesc, i); + + if (op->d.fieldstore.nulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.fieldstore.values[i]))) + continue; + op->d.fieldstore.values[i] = PointerGetDatum( + PG_DETOAST_DATUM_PACKED(op->d.fieldstore.values[i])); + } + /* argdesc should already be valid from the DeForm step */ tuple = heap_form_tuple(*op->d.fieldstore.argdesc, op->d.fieldstore.values, op->d.fieldstore.nulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c index 511467280f..c3d464f42b 100644 --- a/src/backend/utils/adt/jsonfuncs.c +++ b/src/backend/utils/adt/jsonfuncs.c @@ -2968,7 +2968,7 @@ populate_composite(CompositeIOData *io, /* populate resulting record tuple */ tuple = populate_record(io->tupdesc, &io->record_io, defaultval, mcxt, &jso); - result = HeapTupleHeaderGetDatum(tuple); + result = HeapTupleHeaderGetRawDatum(tuple); JsObjectFree(&jso); } @@ -3387,6 +3387,10 @@ populate_record(TupleDesc tupdesc, nulls[i] ? (Datum) 0 : values[i], &field, &nulls[i]); + + if (!nulls[i] && att->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(values[i]))) + values[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(values[i])); } res = heap_form_tuple(tupdesc, values, nulls); @@ -3765,7 +3769,7 @@ populate_recordset_record(PopulateRecordsetState *state, JsObject *obj) /* if it's domain over composite, check domain constraints */ if (cache->c.typcat == TYPECAT_COMPOSITE_DOMAIN) - domain_check(HeapTupleHeaderGetDatum(tuphead), false, + domain_check(HeapTupleHeaderGetRawDatum(tuphead), false, cache->argtype, &cache->c.io.composite.domain_info, cache->fn_mcxt); diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index b4c70aaa7f..fd073767bc 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -5326,7 +5326,7 @@ exec_eval_datum(PLpgSQL_execstate *estate, elog(ERROR, "row not compatible with its own tupdesc"); *typeid = row->rowtupdesc->tdtypeid; *typetypmod = row->rowtupdesc->tdtypmod; - *value = HeapTupleGetDatum(tup); + *value = HeapTupleGetRawDatum(tup); *isnull = false; MemoryContextSwitchTo(oldcontext); break; @@ -7300,6 +7300,9 @@ make_tuple_from_row(PLpgSQL_execstate *estate, &dvalues[i], &nulls[i]); if (fieldtypeid != TupleDescAttr(tupdesc, i)->atttypid) return NULL; + if (!nulls[i] && TupleDescAttr(tupdesc, i)->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(dvalues[i]))) + dvalues[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(dvalues[i])); /* XXX should we insist on typmod match, too? */ } -- 2.17.0 --C94crkcyjafcjHxo Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-Disallow-compressed-data-inside-container-types.patch" ^ permalink raw reply [nested|flat] 49+ messages in thread
* [PATCH 2/8] Expand the external data before forming the tuple @ 2021-03-04 09:25 Dilip Kumar <[email protected]> 0 siblings, 0 replies; 49+ messages in thread From: Dilip Kumar @ 2021-03-04 09:25 UTC (permalink / raw) All the callers of HeapTupleGetDatum and HeapTupleHeaderGetDatum, who might contain the external varlena in their tuple, try to flatten the external varlena before forming the tuple wherever it is possible. Dilip Kumar based on idea by Robert Haas --- src/backend/executor/execExprInterp.c | 29 +++++++++++++++++++++++++-- src/backend/utils/adt/jsonfuncs.c | 8 ++++++-- src/pl/plpgsql/src/pl_exec.c | 5 ++++- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index 20949a5dec..c3754acca4 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -2840,12 +2840,25 @@ ExecEvalRow(ExprState *state, ExprEvalStep *op) { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < op->d.row.tupdesc->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(op->d.row.tupdesc, i); + + if (op->d.row.elemnulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.row.elemvalues[i]))) + continue; + + op->d.row.elemvalues[i] = + PointerGetDatum(PG_DETOAST_DATUM_PACKED(op->d.row.elemvalues[i])); + } + /* build tuple from evaluated field values */ tuple = heap_form_tuple(op->d.row.tupdesc, op->d.row.elemvalues, op->d.row.elemnulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } @@ -3085,12 +3098,24 @@ ExecEvalFieldStoreForm(ExprState *state, ExprEvalStep *op, ExprContext *econtext { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < (*op->d.fieldstore.argdesc)->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(*op->d.fieldstore.argdesc, i); + + if (op->d.fieldstore.nulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.fieldstore.values[i]))) + continue; + op->d.fieldstore.values[i] = PointerGetDatum( + PG_DETOAST_DATUM_PACKED(op->d.fieldstore.values[i])); + } + /* argdesc should already be valid from the DeForm step */ tuple = heap_form_tuple(*op->d.fieldstore.argdesc, op->d.fieldstore.values, op->d.fieldstore.nulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c index 511467280f..c3d464f42b 100644 --- a/src/backend/utils/adt/jsonfuncs.c +++ b/src/backend/utils/adt/jsonfuncs.c @@ -2968,7 +2968,7 @@ populate_composite(CompositeIOData *io, /* populate resulting record tuple */ tuple = populate_record(io->tupdesc, &io->record_io, defaultval, mcxt, &jso); - result = HeapTupleHeaderGetDatum(tuple); + result = HeapTupleHeaderGetRawDatum(tuple); JsObjectFree(&jso); } @@ -3387,6 +3387,10 @@ populate_record(TupleDesc tupdesc, nulls[i] ? (Datum) 0 : values[i], &field, &nulls[i]); + + if (!nulls[i] && att->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(values[i]))) + values[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(values[i])); } res = heap_form_tuple(tupdesc, values, nulls); @@ -3765,7 +3769,7 @@ populate_recordset_record(PopulateRecordsetState *state, JsObject *obj) /* if it's domain over composite, check domain constraints */ if (cache->c.typcat == TYPECAT_COMPOSITE_DOMAIN) - domain_check(HeapTupleHeaderGetDatum(tuphead), false, + domain_check(HeapTupleHeaderGetRawDatum(tuphead), false, cache->argtype, &cache->c.io.composite.domain_info, cache->fn_mcxt); diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index b4c70aaa7f..fd073767bc 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -5326,7 +5326,7 @@ exec_eval_datum(PLpgSQL_execstate *estate, elog(ERROR, "row not compatible with its own tupdesc"); *typeid = row->rowtupdesc->tdtypeid; *typetypmod = row->rowtupdesc->tdtypmod; - *value = HeapTupleGetDatum(tup); + *value = HeapTupleGetRawDatum(tup); *isnull = false; MemoryContextSwitchTo(oldcontext); break; @@ -7300,6 +7300,9 @@ make_tuple_from_row(PLpgSQL_execstate *estate, &dvalues[i], &nulls[i]); if (fieldtypeid != TupleDescAttr(tupdesc, i)->atttypid) return NULL; + if (!nulls[i] && TupleDescAttr(tupdesc, i)->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(dvalues[i]))) + dvalues[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(dvalues[i])); /* XXX should we insist on typmod match, too? */ } -- 2.17.0 --cvVnyQ+4j833TQvp Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-Disallow-compressed-data-inside-container-types.patch" ^ permalink raw reply [nested|flat] 49+ messages in thread
* [PATCH 2/8] Expand the external data before forming the tuple @ 2021-03-04 09:25 Dilip Kumar <[email protected]> 0 siblings, 0 replies; 49+ messages in thread From: Dilip Kumar @ 2021-03-04 09:25 UTC (permalink / raw) All the callers of HeapTupleGetDatum and HeapTupleHeaderGetDatum, who might contain the external varlena in their tuple, try to flatten the external varlena before forming the tuple wherever it is possible. Dilip Kumar based on idea by Robert Haas --- src/backend/executor/execExprInterp.c | 29 +++++++++++++++++++++++++-- src/backend/utils/adt/jsonfuncs.c | 8 ++++++-- src/pl/plpgsql/src/pl_exec.c | 5 ++++- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index 20949a5dec..c3754acca4 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -2840,12 +2840,25 @@ ExecEvalRow(ExprState *state, ExprEvalStep *op) { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < op->d.row.tupdesc->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(op->d.row.tupdesc, i); + + if (op->d.row.elemnulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.row.elemvalues[i]))) + continue; + + op->d.row.elemvalues[i] = + PointerGetDatum(PG_DETOAST_DATUM_PACKED(op->d.row.elemvalues[i])); + } + /* build tuple from evaluated field values */ tuple = heap_form_tuple(op->d.row.tupdesc, op->d.row.elemvalues, op->d.row.elemnulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } @@ -3085,12 +3098,24 @@ ExecEvalFieldStoreForm(ExprState *state, ExprEvalStep *op, ExprContext *econtext { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < (*op->d.fieldstore.argdesc)->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(*op->d.fieldstore.argdesc, i); + + if (op->d.fieldstore.nulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.fieldstore.values[i]))) + continue; + op->d.fieldstore.values[i] = PointerGetDatum( + PG_DETOAST_DATUM_PACKED(op->d.fieldstore.values[i])); + } + /* argdesc should already be valid from the DeForm step */ tuple = heap_form_tuple(*op->d.fieldstore.argdesc, op->d.fieldstore.values, op->d.fieldstore.nulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c index 511467280f..c3d464f42b 100644 --- a/src/backend/utils/adt/jsonfuncs.c +++ b/src/backend/utils/adt/jsonfuncs.c @@ -2968,7 +2968,7 @@ populate_composite(CompositeIOData *io, /* populate resulting record tuple */ tuple = populate_record(io->tupdesc, &io->record_io, defaultval, mcxt, &jso); - result = HeapTupleHeaderGetDatum(tuple); + result = HeapTupleHeaderGetRawDatum(tuple); JsObjectFree(&jso); } @@ -3387,6 +3387,10 @@ populate_record(TupleDesc tupdesc, nulls[i] ? (Datum) 0 : values[i], &field, &nulls[i]); + + if (!nulls[i] && att->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(values[i]))) + values[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(values[i])); } res = heap_form_tuple(tupdesc, values, nulls); @@ -3765,7 +3769,7 @@ populate_recordset_record(PopulateRecordsetState *state, JsObject *obj) /* if it's domain over composite, check domain constraints */ if (cache->c.typcat == TYPECAT_COMPOSITE_DOMAIN) - domain_check(HeapTupleHeaderGetDatum(tuphead), false, + domain_check(HeapTupleHeaderGetRawDatum(tuphead), false, cache->argtype, &cache->c.io.composite.domain_info, cache->fn_mcxt); diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index b4c70aaa7f..fd073767bc 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -5326,7 +5326,7 @@ exec_eval_datum(PLpgSQL_execstate *estate, elog(ERROR, "row not compatible with its own tupdesc"); *typeid = row->rowtupdesc->tdtypeid; *typetypmod = row->rowtupdesc->tdtypmod; - *value = HeapTupleGetDatum(tup); + *value = HeapTupleGetRawDatum(tup); *isnull = false; MemoryContextSwitchTo(oldcontext); break; @@ -7300,6 +7300,9 @@ make_tuple_from_row(PLpgSQL_execstate *estate, &dvalues[i], &nulls[i]); if (fieldtypeid != TupleDescAttr(tupdesc, i)->atttypid) return NULL; + if (!nulls[i] && TupleDescAttr(tupdesc, i)->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(dvalues[i]))) + dvalues[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(dvalues[i])); /* XXX should we insist on typmod match, too? */ } -- 2.17.0 --C94crkcyjafcjHxo Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-Disallow-compressed-data-inside-container-types.patch" ^ permalink raw reply [nested|flat] 49+ messages in thread
* [PATCH 2/8] Expand the external data before forming the tuple @ 2021-03-04 09:25 Dilip Kumar <[email protected]> 0 siblings, 0 replies; 49+ messages in thread From: Dilip Kumar @ 2021-03-04 09:25 UTC (permalink / raw) All the callers of HeapTupleGetDatum and HeapTupleHeaderGetDatum, who might contain the external varlena in their tuple, try to flatten the external varlena before forming the tuple wherever it is possible. Dilip Kumar based on idea by Robert Haas --- src/backend/executor/execExprInterp.c | 29 +++++++++++++++++++++++++-- src/backend/utils/adt/jsonfuncs.c | 8 ++++++-- src/pl/plpgsql/src/pl_exec.c | 5 ++++- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index 20949a5dec..c3754acca4 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -2840,12 +2840,25 @@ ExecEvalRow(ExprState *state, ExprEvalStep *op) { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < op->d.row.tupdesc->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(op->d.row.tupdesc, i); + + if (op->d.row.elemnulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.row.elemvalues[i]))) + continue; + + op->d.row.elemvalues[i] = + PointerGetDatum(PG_DETOAST_DATUM_PACKED(op->d.row.elemvalues[i])); + } + /* build tuple from evaluated field values */ tuple = heap_form_tuple(op->d.row.tupdesc, op->d.row.elemvalues, op->d.row.elemnulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } @@ -3085,12 +3098,24 @@ ExecEvalFieldStoreForm(ExprState *state, ExprEvalStep *op, ExprContext *econtext { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < (*op->d.fieldstore.argdesc)->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(*op->d.fieldstore.argdesc, i); + + if (op->d.fieldstore.nulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.fieldstore.values[i]))) + continue; + op->d.fieldstore.values[i] = PointerGetDatum( + PG_DETOAST_DATUM_PACKED(op->d.fieldstore.values[i])); + } + /* argdesc should already be valid from the DeForm step */ tuple = heap_form_tuple(*op->d.fieldstore.argdesc, op->d.fieldstore.values, op->d.fieldstore.nulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c index 511467280f..c3d464f42b 100644 --- a/src/backend/utils/adt/jsonfuncs.c +++ b/src/backend/utils/adt/jsonfuncs.c @@ -2968,7 +2968,7 @@ populate_composite(CompositeIOData *io, /* populate resulting record tuple */ tuple = populate_record(io->tupdesc, &io->record_io, defaultval, mcxt, &jso); - result = HeapTupleHeaderGetDatum(tuple); + result = HeapTupleHeaderGetRawDatum(tuple); JsObjectFree(&jso); } @@ -3387,6 +3387,10 @@ populate_record(TupleDesc tupdesc, nulls[i] ? (Datum) 0 : values[i], &field, &nulls[i]); + + if (!nulls[i] && att->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(values[i]))) + values[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(values[i])); } res = heap_form_tuple(tupdesc, values, nulls); @@ -3765,7 +3769,7 @@ populate_recordset_record(PopulateRecordsetState *state, JsObject *obj) /* if it's domain over composite, check domain constraints */ if (cache->c.typcat == TYPECAT_COMPOSITE_DOMAIN) - domain_check(HeapTupleHeaderGetDatum(tuphead), false, + domain_check(HeapTupleHeaderGetRawDatum(tuphead), false, cache->argtype, &cache->c.io.composite.domain_info, cache->fn_mcxt); diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index b4c70aaa7f..fd073767bc 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -5326,7 +5326,7 @@ exec_eval_datum(PLpgSQL_execstate *estate, elog(ERROR, "row not compatible with its own tupdesc"); *typeid = row->rowtupdesc->tdtypeid; *typetypmod = row->rowtupdesc->tdtypmod; - *value = HeapTupleGetDatum(tup); + *value = HeapTupleGetRawDatum(tup); *isnull = false; MemoryContextSwitchTo(oldcontext); break; @@ -7300,6 +7300,9 @@ make_tuple_from_row(PLpgSQL_execstate *estate, &dvalues[i], &nulls[i]); if (fieldtypeid != TupleDescAttr(tupdesc, i)->atttypid) return NULL; + if (!nulls[i] && TupleDescAttr(tupdesc, i)->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(dvalues[i]))) + dvalues[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(dvalues[i])); /* XXX should we insist on typmod match, too? */ } -- 2.17.0 --cvVnyQ+4j833TQvp Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-Disallow-compressed-data-inside-container-types.patch" ^ permalink raw reply [nested|flat] 49+ messages in thread
* [PATCH 2/8] Expand the external data before forming the tuple @ 2021-03-04 09:25 Dilip Kumar <[email protected]> 0 siblings, 0 replies; 49+ messages in thread From: Dilip Kumar @ 2021-03-04 09:25 UTC (permalink / raw) All the callers of HeapTupleGetDatum and HeapTupleHeaderGetDatum, who might contain the external varlena in their tuple, try to flatten the external varlena before forming the tuple wherever it is possible. Dilip Kumar based on idea by Robert Haas --- src/backend/executor/execExprInterp.c | 29 +++++++++++++++++++++++++-- src/backend/utils/adt/jsonfuncs.c | 8 ++++++-- src/pl/plpgsql/src/pl_exec.c | 5 ++++- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index 20949a5dec..c3754acca4 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -2840,12 +2840,25 @@ ExecEvalRow(ExprState *state, ExprEvalStep *op) { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < op->d.row.tupdesc->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(op->d.row.tupdesc, i); + + if (op->d.row.elemnulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.row.elemvalues[i]))) + continue; + + op->d.row.elemvalues[i] = + PointerGetDatum(PG_DETOAST_DATUM_PACKED(op->d.row.elemvalues[i])); + } + /* build tuple from evaluated field values */ tuple = heap_form_tuple(op->d.row.tupdesc, op->d.row.elemvalues, op->d.row.elemnulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } @@ -3085,12 +3098,24 @@ ExecEvalFieldStoreForm(ExprState *state, ExprEvalStep *op, ExprContext *econtext { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < (*op->d.fieldstore.argdesc)->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(*op->d.fieldstore.argdesc, i); + + if (op->d.fieldstore.nulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.fieldstore.values[i]))) + continue; + op->d.fieldstore.values[i] = PointerGetDatum( + PG_DETOAST_DATUM_PACKED(op->d.fieldstore.values[i])); + } + /* argdesc should already be valid from the DeForm step */ tuple = heap_form_tuple(*op->d.fieldstore.argdesc, op->d.fieldstore.values, op->d.fieldstore.nulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c index 511467280f..c3d464f42b 100644 --- a/src/backend/utils/adt/jsonfuncs.c +++ b/src/backend/utils/adt/jsonfuncs.c @@ -2968,7 +2968,7 @@ populate_composite(CompositeIOData *io, /* populate resulting record tuple */ tuple = populate_record(io->tupdesc, &io->record_io, defaultval, mcxt, &jso); - result = HeapTupleHeaderGetDatum(tuple); + result = HeapTupleHeaderGetRawDatum(tuple); JsObjectFree(&jso); } @@ -3387,6 +3387,10 @@ populate_record(TupleDesc tupdesc, nulls[i] ? (Datum) 0 : values[i], &field, &nulls[i]); + + if (!nulls[i] && att->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(values[i]))) + values[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(values[i])); } res = heap_form_tuple(tupdesc, values, nulls); @@ -3765,7 +3769,7 @@ populate_recordset_record(PopulateRecordsetState *state, JsObject *obj) /* if it's domain over composite, check domain constraints */ if (cache->c.typcat == TYPECAT_COMPOSITE_DOMAIN) - domain_check(HeapTupleHeaderGetDatum(tuphead), false, + domain_check(HeapTupleHeaderGetRawDatum(tuphead), false, cache->argtype, &cache->c.io.composite.domain_info, cache->fn_mcxt); diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index b4c70aaa7f..fd073767bc 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -5326,7 +5326,7 @@ exec_eval_datum(PLpgSQL_execstate *estate, elog(ERROR, "row not compatible with its own tupdesc"); *typeid = row->rowtupdesc->tdtypeid; *typetypmod = row->rowtupdesc->tdtypmod; - *value = HeapTupleGetDatum(tup); + *value = HeapTupleGetRawDatum(tup); *isnull = false; MemoryContextSwitchTo(oldcontext); break; @@ -7300,6 +7300,9 @@ make_tuple_from_row(PLpgSQL_execstate *estate, &dvalues[i], &nulls[i]); if (fieldtypeid != TupleDescAttr(tupdesc, i)->atttypid) return NULL; + if (!nulls[i] && TupleDescAttr(tupdesc, i)->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(dvalues[i]))) + dvalues[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(dvalues[i])); /* XXX should we insist on typmod match, too? */ } -- 2.17.0 --C94crkcyjafcjHxo Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-Disallow-compressed-data-inside-container-types.patch" ^ permalink raw reply [nested|flat] 49+ messages in thread
* [PATCH 2/8] Expand the external data before forming the tuple @ 2021-03-04 09:25 Dilip Kumar <[email protected]> 0 siblings, 0 replies; 49+ messages in thread From: Dilip Kumar @ 2021-03-04 09:25 UTC (permalink / raw) All the callers of HeapTupleGetDatum and HeapTupleHeaderGetDatum, who might contain the external varlena in their tuple, try to flatten the external varlena before forming the tuple wherever it is possible. Dilip Kumar based on idea by Robert Haas --- src/backend/executor/execExprInterp.c | 29 +++++++++++++++++++++++++-- src/backend/utils/adt/jsonfuncs.c | 8 ++++++-- src/pl/plpgsql/src/pl_exec.c | 5 ++++- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index 20949a5dec..c3754acca4 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -2840,12 +2840,25 @@ ExecEvalRow(ExprState *state, ExprEvalStep *op) { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < op->d.row.tupdesc->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(op->d.row.tupdesc, i); + + if (op->d.row.elemnulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.row.elemvalues[i]))) + continue; + + op->d.row.elemvalues[i] = + PointerGetDatum(PG_DETOAST_DATUM_PACKED(op->d.row.elemvalues[i])); + } + /* build tuple from evaluated field values */ tuple = heap_form_tuple(op->d.row.tupdesc, op->d.row.elemvalues, op->d.row.elemnulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } @@ -3085,12 +3098,24 @@ ExecEvalFieldStoreForm(ExprState *state, ExprEvalStep *op, ExprContext *econtext { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < (*op->d.fieldstore.argdesc)->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(*op->d.fieldstore.argdesc, i); + + if (op->d.fieldstore.nulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.fieldstore.values[i]))) + continue; + op->d.fieldstore.values[i] = PointerGetDatum( + PG_DETOAST_DATUM_PACKED(op->d.fieldstore.values[i])); + } + /* argdesc should already be valid from the DeForm step */ tuple = heap_form_tuple(*op->d.fieldstore.argdesc, op->d.fieldstore.values, op->d.fieldstore.nulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c index 511467280f..c3d464f42b 100644 --- a/src/backend/utils/adt/jsonfuncs.c +++ b/src/backend/utils/adt/jsonfuncs.c @@ -2968,7 +2968,7 @@ populate_composite(CompositeIOData *io, /* populate resulting record tuple */ tuple = populate_record(io->tupdesc, &io->record_io, defaultval, mcxt, &jso); - result = HeapTupleHeaderGetDatum(tuple); + result = HeapTupleHeaderGetRawDatum(tuple); JsObjectFree(&jso); } @@ -3387,6 +3387,10 @@ populate_record(TupleDesc tupdesc, nulls[i] ? (Datum) 0 : values[i], &field, &nulls[i]); + + if (!nulls[i] && att->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(values[i]))) + values[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(values[i])); } res = heap_form_tuple(tupdesc, values, nulls); @@ -3765,7 +3769,7 @@ populate_recordset_record(PopulateRecordsetState *state, JsObject *obj) /* if it's domain over composite, check domain constraints */ if (cache->c.typcat == TYPECAT_COMPOSITE_DOMAIN) - domain_check(HeapTupleHeaderGetDatum(tuphead), false, + domain_check(HeapTupleHeaderGetRawDatum(tuphead), false, cache->argtype, &cache->c.io.composite.domain_info, cache->fn_mcxt); diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index b4c70aaa7f..fd073767bc 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -5326,7 +5326,7 @@ exec_eval_datum(PLpgSQL_execstate *estate, elog(ERROR, "row not compatible with its own tupdesc"); *typeid = row->rowtupdesc->tdtypeid; *typetypmod = row->rowtupdesc->tdtypmod; - *value = HeapTupleGetDatum(tup); + *value = HeapTupleGetRawDatum(tup); *isnull = false; MemoryContextSwitchTo(oldcontext); break; @@ -7300,6 +7300,9 @@ make_tuple_from_row(PLpgSQL_execstate *estate, &dvalues[i], &nulls[i]); if (fieldtypeid != TupleDescAttr(tupdesc, i)->atttypid) return NULL; + if (!nulls[i] && TupleDescAttr(tupdesc, i)->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(dvalues[i]))) + dvalues[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(dvalues[i])); /* XXX should we insist on typmod match, too? */ } -- 2.17.0 --cvVnyQ+4j833TQvp Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-Disallow-compressed-data-inside-container-types.patch" ^ permalink raw reply [nested|flat] 49+ messages in thread
* [PATCH 2/8] Expand the external data before forming the tuple @ 2021-03-04 09:25 Dilip Kumar <[email protected]> 0 siblings, 0 replies; 49+ messages in thread From: Dilip Kumar @ 2021-03-04 09:25 UTC (permalink / raw) All the callers of HeapTupleGetDatum and HeapTupleHeaderGetDatum, who might contain the external varlena in their tuple, try to flatten the external varlena before forming the tuple wherever it is possible. Dilip Kumar based on idea by Robert Haas --- src/backend/executor/execExprInterp.c | 29 +++++++++++++++++++++++++-- src/backend/utils/adt/jsonfuncs.c | 8 ++++++-- src/pl/plpgsql/src/pl_exec.c | 5 ++++- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index 20949a5dec..c3754acca4 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -2840,12 +2840,25 @@ ExecEvalRow(ExprState *state, ExprEvalStep *op) { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < op->d.row.tupdesc->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(op->d.row.tupdesc, i); + + if (op->d.row.elemnulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.row.elemvalues[i]))) + continue; + + op->d.row.elemvalues[i] = + PointerGetDatum(PG_DETOAST_DATUM_PACKED(op->d.row.elemvalues[i])); + } + /* build tuple from evaluated field values */ tuple = heap_form_tuple(op->d.row.tupdesc, op->d.row.elemvalues, op->d.row.elemnulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } @@ -3085,12 +3098,24 @@ ExecEvalFieldStoreForm(ExprState *state, ExprEvalStep *op, ExprContext *econtext { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < (*op->d.fieldstore.argdesc)->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(*op->d.fieldstore.argdesc, i); + + if (op->d.fieldstore.nulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.fieldstore.values[i]))) + continue; + op->d.fieldstore.values[i] = PointerGetDatum( + PG_DETOAST_DATUM_PACKED(op->d.fieldstore.values[i])); + } + /* argdesc should already be valid from the DeForm step */ tuple = heap_form_tuple(*op->d.fieldstore.argdesc, op->d.fieldstore.values, op->d.fieldstore.nulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c index 511467280f..c3d464f42b 100644 --- a/src/backend/utils/adt/jsonfuncs.c +++ b/src/backend/utils/adt/jsonfuncs.c @@ -2968,7 +2968,7 @@ populate_composite(CompositeIOData *io, /* populate resulting record tuple */ tuple = populate_record(io->tupdesc, &io->record_io, defaultval, mcxt, &jso); - result = HeapTupleHeaderGetDatum(tuple); + result = HeapTupleHeaderGetRawDatum(tuple); JsObjectFree(&jso); } @@ -3387,6 +3387,10 @@ populate_record(TupleDesc tupdesc, nulls[i] ? (Datum) 0 : values[i], &field, &nulls[i]); + + if (!nulls[i] && att->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(values[i]))) + values[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(values[i])); } res = heap_form_tuple(tupdesc, values, nulls); @@ -3765,7 +3769,7 @@ populate_recordset_record(PopulateRecordsetState *state, JsObject *obj) /* if it's domain over composite, check domain constraints */ if (cache->c.typcat == TYPECAT_COMPOSITE_DOMAIN) - domain_check(HeapTupleHeaderGetDatum(tuphead), false, + domain_check(HeapTupleHeaderGetRawDatum(tuphead), false, cache->argtype, &cache->c.io.composite.domain_info, cache->fn_mcxt); diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index b4c70aaa7f..fd073767bc 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -5326,7 +5326,7 @@ exec_eval_datum(PLpgSQL_execstate *estate, elog(ERROR, "row not compatible with its own tupdesc"); *typeid = row->rowtupdesc->tdtypeid; *typetypmod = row->rowtupdesc->tdtypmod; - *value = HeapTupleGetDatum(tup); + *value = HeapTupleGetRawDatum(tup); *isnull = false; MemoryContextSwitchTo(oldcontext); break; @@ -7300,6 +7300,9 @@ make_tuple_from_row(PLpgSQL_execstate *estate, &dvalues[i], &nulls[i]); if (fieldtypeid != TupleDescAttr(tupdesc, i)->atttypid) return NULL; + if (!nulls[i] && TupleDescAttr(tupdesc, i)->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(dvalues[i]))) + dvalues[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(dvalues[i])); /* XXX should we insist on typmod match, too? */ } -- 2.17.0 --C94crkcyjafcjHxo Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-Disallow-compressed-data-inside-container-types.patch" ^ permalink raw reply [nested|flat] 49+ messages in thread
* [PATCH 2/8] Expand the external data before forming the tuple @ 2021-03-04 09:25 Dilip Kumar <[email protected]> 0 siblings, 0 replies; 49+ messages in thread From: Dilip Kumar @ 2021-03-04 09:25 UTC (permalink / raw) All the callers of HeapTupleGetDatum and HeapTupleHeaderGetDatum, who might contain the external varlena in their tuple, try to flatten the external varlena before forming the tuple wherever it is possible. Dilip Kumar based on idea by Robert Haas --- src/backend/executor/execExprInterp.c | 29 +++++++++++++++++++++++++-- src/backend/utils/adt/jsonfuncs.c | 8 ++++++-- src/pl/plpgsql/src/pl_exec.c | 5 ++++- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index 20949a5dec..c3754acca4 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -2840,12 +2840,25 @@ ExecEvalRow(ExprState *state, ExprEvalStep *op) { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < op->d.row.tupdesc->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(op->d.row.tupdesc, i); + + if (op->d.row.elemnulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.row.elemvalues[i]))) + continue; + + op->d.row.elemvalues[i] = + PointerGetDatum(PG_DETOAST_DATUM_PACKED(op->d.row.elemvalues[i])); + } + /* build tuple from evaluated field values */ tuple = heap_form_tuple(op->d.row.tupdesc, op->d.row.elemvalues, op->d.row.elemnulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } @@ -3085,12 +3098,24 @@ ExecEvalFieldStoreForm(ExprState *state, ExprEvalStep *op, ExprContext *econtext { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < (*op->d.fieldstore.argdesc)->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(*op->d.fieldstore.argdesc, i); + + if (op->d.fieldstore.nulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.fieldstore.values[i]))) + continue; + op->d.fieldstore.values[i] = PointerGetDatum( + PG_DETOAST_DATUM_PACKED(op->d.fieldstore.values[i])); + } + /* argdesc should already be valid from the DeForm step */ tuple = heap_form_tuple(*op->d.fieldstore.argdesc, op->d.fieldstore.values, op->d.fieldstore.nulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c index 511467280f..c3d464f42b 100644 --- a/src/backend/utils/adt/jsonfuncs.c +++ b/src/backend/utils/adt/jsonfuncs.c @@ -2968,7 +2968,7 @@ populate_composite(CompositeIOData *io, /* populate resulting record tuple */ tuple = populate_record(io->tupdesc, &io->record_io, defaultval, mcxt, &jso); - result = HeapTupleHeaderGetDatum(tuple); + result = HeapTupleHeaderGetRawDatum(tuple); JsObjectFree(&jso); } @@ -3387,6 +3387,10 @@ populate_record(TupleDesc tupdesc, nulls[i] ? (Datum) 0 : values[i], &field, &nulls[i]); + + if (!nulls[i] && att->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(values[i]))) + values[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(values[i])); } res = heap_form_tuple(tupdesc, values, nulls); @@ -3765,7 +3769,7 @@ populate_recordset_record(PopulateRecordsetState *state, JsObject *obj) /* if it's domain over composite, check domain constraints */ if (cache->c.typcat == TYPECAT_COMPOSITE_DOMAIN) - domain_check(HeapTupleHeaderGetDatum(tuphead), false, + domain_check(HeapTupleHeaderGetRawDatum(tuphead), false, cache->argtype, &cache->c.io.composite.domain_info, cache->fn_mcxt); diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index b4c70aaa7f..fd073767bc 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -5326,7 +5326,7 @@ exec_eval_datum(PLpgSQL_execstate *estate, elog(ERROR, "row not compatible with its own tupdesc"); *typeid = row->rowtupdesc->tdtypeid; *typetypmod = row->rowtupdesc->tdtypmod; - *value = HeapTupleGetDatum(tup); + *value = HeapTupleGetRawDatum(tup); *isnull = false; MemoryContextSwitchTo(oldcontext); break; @@ -7300,6 +7300,9 @@ make_tuple_from_row(PLpgSQL_execstate *estate, &dvalues[i], &nulls[i]); if (fieldtypeid != TupleDescAttr(tupdesc, i)->atttypid) return NULL; + if (!nulls[i] && TupleDescAttr(tupdesc, i)->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(dvalues[i]))) + dvalues[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(dvalues[i])); /* XXX should we insist on typmod match, too? */ } -- 2.17.0 --cvVnyQ+4j833TQvp Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-Disallow-compressed-data-inside-container-types.patch" ^ permalink raw reply [nested|flat] 49+ messages in thread
* [PATCH 2/8] Expand the external data before forming the tuple @ 2021-03-04 09:25 Dilip Kumar <[email protected]> 0 siblings, 0 replies; 49+ messages in thread From: Dilip Kumar @ 2021-03-04 09:25 UTC (permalink / raw) All the callers of HeapTupleGetDatum and HeapTupleHeaderGetDatum, who might contain the external varlena in their tuple, try to flatten the external varlena before forming the tuple wherever it is possible. Dilip Kumar based on idea by Robert Haas --- src/backend/executor/execExprInterp.c | 29 +++++++++++++++++++++++++-- src/backend/utils/adt/jsonfuncs.c | 8 ++++++-- src/pl/plpgsql/src/pl_exec.c | 5 ++++- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index 20949a5dec..c3754acca4 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -2840,12 +2840,25 @@ ExecEvalRow(ExprState *state, ExprEvalStep *op) { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < op->d.row.tupdesc->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(op->d.row.tupdesc, i); + + if (op->d.row.elemnulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.row.elemvalues[i]))) + continue; + + op->d.row.elemvalues[i] = + PointerGetDatum(PG_DETOAST_DATUM_PACKED(op->d.row.elemvalues[i])); + } + /* build tuple from evaluated field values */ tuple = heap_form_tuple(op->d.row.tupdesc, op->d.row.elemvalues, op->d.row.elemnulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } @@ -3085,12 +3098,24 @@ ExecEvalFieldStoreForm(ExprState *state, ExprEvalStep *op, ExprContext *econtext { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < (*op->d.fieldstore.argdesc)->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(*op->d.fieldstore.argdesc, i); + + if (op->d.fieldstore.nulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.fieldstore.values[i]))) + continue; + op->d.fieldstore.values[i] = PointerGetDatum( + PG_DETOAST_DATUM_PACKED(op->d.fieldstore.values[i])); + } + /* argdesc should already be valid from the DeForm step */ tuple = heap_form_tuple(*op->d.fieldstore.argdesc, op->d.fieldstore.values, op->d.fieldstore.nulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c index 511467280f..c3d464f42b 100644 --- a/src/backend/utils/adt/jsonfuncs.c +++ b/src/backend/utils/adt/jsonfuncs.c @@ -2968,7 +2968,7 @@ populate_composite(CompositeIOData *io, /* populate resulting record tuple */ tuple = populate_record(io->tupdesc, &io->record_io, defaultval, mcxt, &jso); - result = HeapTupleHeaderGetDatum(tuple); + result = HeapTupleHeaderGetRawDatum(tuple); JsObjectFree(&jso); } @@ -3387,6 +3387,10 @@ populate_record(TupleDesc tupdesc, nulls[i] ? (Datum) 0 : values[i], &field, &nulls[i]); + + if (!nulls[i] && att->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(values[i]))) + values[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(values[i])); } res = heap_form_tuple(tupdesc, values, nulls); @@ -3765,7 +3769,7 @@ populate_recordset_record(PopulateRecordsetState *state, JsObject *obj) /* if it's domain over composite, check domain constraints */ if (cache->c.typcat == TYPECAT_COMPOSITE_DOMAIN) - domain_check(HeapTupleHeaderGetDatum(tuphead), false, + domain_check(HeapTupleHeaderGetRawDatum(tuphead), false, cache->argtype, &cache->c.io.composite.domain_info, cache->fn_mcxt); diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index b4c70aaa7f..fd073767bc 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -5326,7 +5326,7 @@ exec_eval_datum(PLpgSQL_execstate *estate, elog(ERROR, "row not compatible with its own tupdesc"); *typeid = row->rowtupdesc->tdtypeid; *typetypmod = row->rowtupdesc->tdtypmod; - *value = HeapTupleGetDatum(tup); + *value = HeapTupleGetRawDatum(tup); *isnull = false; MemoryContextSwitchTo(oldcontext); break; @@ -7300,6 +7300,9 @@ make_tuple_from_row(PLpgSQL_execstate *estate, &dvalues[i], &nulls[i]); if (fieldtypeid != TupleDescAttr(tupdesc, i)->atttypid) return NULL; + if (!nulls[i] && TupleDescAttr(tupdesc, i)->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(dvalues[i]))) + dvalues[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(dvalues[i])); /* XXX should we insist on typmod match, too? */ } -- 2.17.0 --C94crkcyjafcjHxo Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-Disallow-compressed-data-inside-container-types.patch" ^ permalink raw reply [nested|flat] 49+ messages in thread
* [PATCH 2/8] Expand the external data before forming the tuple @ 2021-03-04 09:25 Dilip Kumar <[email protected]> 0 siblings, 0 replies; 49+ messages in thread From: Dilip Kumar @ 2021-03-04 09:25 UTC (permalink / raw) All the callers of HeapTupleGetDatum and HeapTupleHeaderGetDatum, who might contain the external varlena in their tuple, try to flatten the external varlena before forming the tuple wherever it is possible. Dilip Kumar based on idea by Robert Haas --- src/backend/executor/execExprInterp.c | 29 +++++++++++++++++++++++++-- src/backend/utils/adt/jsonfuncs.c | 8 ++++++-- src/pl/plpgsql/src/pl_exec.c | 5 ++++- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index 20949a5dec..c3754acca4 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -2840,12 +2840,25 @@ ExecEvalRow(ExprState *state, ExprEvalStep *op) { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < op->d.row.tupdesc->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(op->d.row.tupdesc, i); + + if (op->d.row.elemnulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.row.elemvalues[i]))) + continue; + + op->d.row.elemvalues[i] = + PointerGetDatum(PG_DETOAST_DATUM_PACKED(op->d.row.elemvalues[i])); + } + /* build tuple from evaluated field values */ tuple = heap_form_tuple(op->d.row.tupdesc, op->d.row.elemvalues, op->d.row.elemnulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } @@ -3085,12 +3098,24 @@ ExecEvalFieldStoreForm(ExprState *state, ExprEvalStep *op, ExprContext *econtext { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < (*op->d.fieldstore.argdesc)->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(*op->d.fieldstore.argdesc, i); + + if (op->d.fieldstore.nulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.fieldstore.values[i]))) + continue; + op->d.fieldstore.values[i] = PointerGetDatum( + PG_DETOAST_DATUM_PACKED(op->d.fieldstore.values[i])); + } + /* argdesc should already be valid from the DeForm step */ tuple = heap_form_tuple(*op->d.fieldstore.argdesc, op->d.fieldstore.values, op->d.fieldstore.nulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c index 511467280f..c3d464f42b 100644 --- a/src/backend/utils/adt/jsonfuncs.c +++ b/src/backend/utils/adt/jsonfuncs.c @@ -2968,7 +2968,7 @@ populate_composite(CompositeIOData *io, /* populate resulting record tuple */ tuple = populate_record(io->tupdesc, &io->record_io, defaultval, mcxt, &jso); - result = HeapTupleHeaderGetDatum(tuple); + result = HeapTupleHeaderGetRawDatum(tuple); JsObjectFree(&jso); } @@ -3387,6 +3387,10 @@ populate_record(TupleDesc tupdesc, nulls[i] ? (Datum) 0 : values[i], &field, &nulls[i]); + + if (!nulls[i] && att->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(values[i]))) + values[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(values[i])); } res = heap_form_tuple(tupdesc, values, nulls); @@ -3765,7 +3769,7 @@ populate_recordset_record(PopulateRecordsetState *state, JsObject *obj) /* if it's domain over composite, check domain constraints */ if (cache->c.typcat == TYPECAT_COMPOSITE_DOMAIN) - domain_check(HeapTupleHeaderGetDatum(tuphead), false, + domain_check(HeapTupleHeaderGetRawDatum(tuphead), false, cache->argtype, &cache->c.io.composite.domain_info, cache->fn_mcxt); diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index b4c70aaa7f..fd073767bc 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -5326,7 +5326,7 @@ exec_eval_datum(PLpgSQL_execstate *estate, elog(ERROR, "row not compatible with its own tupdesc"); *typeid = row->rowtupdesc->tdtypeid; *typetypmod = row->rowtupdesc->tdtypmod; - *value = HeapTupleGetDatum(tup); + *value = HeapTupleGetRawDatum(tup); *isnull = false; MemoryContextSwitchTo(oldcontext); break; @@ -7300,6 +7300,9 @@ make_tuple_from_row(PLpgSQL_execstate *estate, &dvalues[i], &nulls[i]); if (fieldtypeid != TupleDescAttr(tupdesc, i)->atttypid) return NULL; + if (!nulls[i] && TupleDescAttr(tupdesc, i)->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(dvalues[i]))) + dvalues[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(dvalues[i])); /* XXX should we insist on typmod match, too? */ } -- 2.17.0 --cvVnyQ+4j833TQvp Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-Disallow-compressed-data-inside-container-types.patch" ^ permalink raw reply [nested|flat] 49+ messages in thread
* [PATCH 2/8] Expand the external data before forming the tuple @ 2021-03-04 09:25 Dilip Kumar <[email protected]> 0 siblings, 0 replies; 49+ messages in thread From: Dilip Kumar @ 2021-03-04 09:25 UTC (permalink / raw) All the callers of HeapTupleGetDatum and HeapTupleHeaderGetDatum, who might contain the external varlena in their tuple, try to flatten the external varlena before forming the tuple wherever it is possible. Dilip Kumar based on idea by Robert Haas --- src/backend/executor/execExprInterp.c | 29 +++++++++++++++++++++++++-- src/backend/utils/adt/jsonfuncs.c | 8 ++++++-- src/pl/plpgsql/src/pl_exec.c | 5 ++++- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index 20949a5dec..c3754acca4 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -2840,12 +2840,25 @@ ExecEvalRow(ExprState *state, ExprEvalStep *op) { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < op->d.row.tupdesc->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(op->d.row.tupdesc, i); + + if (op->d.row.elemnulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.row.elemvalues[i]))) + continue; + + op->d.row.elemvalues[i] = + PointerGetDatum(PG_DETOAST_DATUM_PACKED(op->d.row.elemvalues[i])); + } + /* build tuple from evaluated field values */ tuple = heap_form_tuple(op->d.row.tupdesc, op->d.row.elemvalues, op->d.row.elemnulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } @@ -3085,12 +3098,24 @@ ExecEvalFieldStoreForm(ExprState *state, ExprEvalStep *op, ExprContext *econtext { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < (*op->d.fieldstore.argdesc)->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(*op->d.fieldstore.argdesc, i); + + if (op->d.fieldstore.nulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.fieldstore.values[i]))) + continue; + op->d.fieldstore.values[i] = PointerGetDatum( + PG_DETOAST_DATUM_PACKED(op->d.fieldstore.values[i])); + } + /* argdesc should already be valid from the DeForm step */ tuple = heap_form_tuple(*op->d.fieldstore.argdesc, op->d.fieldstore.values, op->d.fieldstore.nulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c index 511467280f..c3d464f42b 100644 --- a/src/backend/utils/adt/jsonfuncs.c +++ b/src/backend/utils/adt/jsonfuncs.c @@ -2968,7 +2968,7 @@ populate_composite(CompositeIOData *io, /* populate resulting record tuple */ tuple = populate_record(io->tupdesc, &io->record_io, defaultval, mcxt, &jso); - result = HeapTupleHeaderGetDatum(tuple); + result = HeapTupleHeaderGetRawDatum(tuple); JsObjectFree(&jso); } @@ -3387,6 +3387,10 @@ populate_record(TupleDesc tupdesc, nulls[i] ? (Datum) 0 : values[i], &field, &nulls[i]); + + if (!nulls[i] && att->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(values[i]))) + values[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(values[i])); } res = heap_form_tuple(tupdesc, values, nulls); @@ -3765,7 +3769,7 @@ populate_recordset_record(PopulateRecordsetState *state, JsObject *obj) /* if it's domain over composite, check domain constraints */ if (cache->c.typcat == TYPECAT_COMPOSITE_DOMAIN) - domain_check(HeapTupleHeaderGetDatum(tuphead), false, + domain_check(HeapTupleHeaderGetRawDatum(tuphead), false, cache->argtype, &cache->c.io.composite.domain_info, cache->fn_mcxt); diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index b4c70aaa7f..fd073767bc 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -5326,7 +5326,7 @@ exec_eval_datum(PLpgSQL_execstate *estate, elog(ERROR, "row not compatible with its own tupdesc"); *typeid = row->rowtupdesc->tdtypeid; *typetypmod = row->rowtupdesc->tdtypmod; - *value = HeapTupleGetDatum(tup); + *value = HeapTupleGetRawDatum(tup); *isnull = false; MemoryContextSwitchTo(oldcontext); break; @@ -7300,6 +7300,9 @@ make_tuple_from_row(PLpgSQL_execstate *estate, &dvalues[i], &nulls[i]); if (fieldtypeid != TupleDescAttr(tupdesc, i)->atttypid) return NULL; + if (!nulls[i] && TupleDescAttr(tupdesc, i)->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(dvalues[i]))) + dvalues[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(dvalues[i])); /* XXX should we insist on typmod match, too? */ } -- 2.17.0 --C94crkcyjafcjHxo Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-Disallow-compressed-data-inside-container-types.patch" ^ permalink raw reply [nested|flat] 49+ messages in thread
* [PATCH 2/8] Expand the external data before forming the tuple @ 2021-03-04 09:25 Dilip Kumar <[email protected]> 0 siblings, 0 replies; 49+ messages in thread From: Dilip Kumar @ 2021-03-04 09:25 UTC (permalink / raw) All the callers of HeapTupleGetDatum and HeapTupleHeaderGetDatum, who might contain the external varlena in their tuple, try to flatten the external varlena before forming the tuple wherever it is possible. Dilip Kumar based on idea by Robert Haas --- src/backend/executor/execExprInterp.c | 29 +++++++++++++++++++++++++-- src/backend/utils/adt/jsonfuncs.c | 8 ++++++-- src/pl/plpgsql/src/pl_exec.c | 5 ++++- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index 20949a5dec..c3754acca4 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -2840,12 +2840,25 @@ ExecEvalRow(ExprState *state, ExprEvalStep *op) { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < op->d.row.tupdesc->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(op->d.row.tupdesc, i); + + if (op->d.row.elemnulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.row.elemvalues[i]))) + continue; + + op->d.row.elemvalues[i] = + PointerGetDatum(PG_DETOAST_DATUM_PACKED(op->d.row.elemvalues[i])); + } + /* build tuple from evaluated field values */ tuple = heap_form_tuple(op->d.row.tupdesc, op->d.row.elemvalues, op->d.row.elemnulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } @@ -3085,12 +3098,24 @@ ExecEvalFieldStoreForm(ExprState *state, ExprEvalStep *op, ExprContext *econtext { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < (*op->d.fieldstore.argdesc)->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(*op->d.fieldstore.argdesc, i); + + if (op->d.fieldstore.nulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.fieldstore.values[i]))) + continue; + op->d.fieldstore.values[i] = PointerGetDatum( + PG_DETOAST_DATUM_PACKED(op->d.fieldstore.values[i])); + } + /* argdesc should already be valid from the DeForm step */ tuple = heap_form_tuple(*op->d.fieldstore.argdesc, op->d.fieldstore.values, op->d.fieldstore.nulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c index 511467280f..c3d464f42b 100644 --- a/src/backend/utils/adt/jsonfuncs.c +++ b/src/backend/utils/adt/jsonfuncs.c @@ -2968,7 +2968,7 @@ populate_composite(CompositeIOData *io, /* populate resulting record tuple */ tuple = populate_record(io->tupdesc, &io->record_io, defaultval, mcxt, &jso); - result = HeapTupleHeaderGetDatum(tuple); + result = HeapTupleHeaderGetRawDatum(tuple); JsObjectFree(&jso); } @@ -3387,6 +3387,10 @@ populate_record(TupleDesc tupdesc, nulls[i] ? (Datum) 0 : values[i], &field, &nulls[i]); + + if (!nulls[i] && att->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(values[i]))) + values[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(values[i])); } res = heap_form_tuple(tupdesc, values, nulls); @@ -3765,7 +3769,7 @@ populate_recordset_record(PopulateRecordsetState *state, JsObject *obj) /* if it's domain over composite, check domain constraints */ if (cache->c.typcat == TYPECAT_COMPOSITE_DOMAIN) - domain_check(HeapTupleHeaderGetDatum(tuphead), false, + domain_check(HeapTupleHeaderGetRawDatum(tuphead), false, cache->argtype, &cache->c.io.composite.domain_info, cache->fn_mcxt); diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index b4c70aaa7f..fd073767bc 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -5326,7 +5326,7 @@ exec_eval_datum(PLpgSQL_execstate *estate, elog(ERROR, "row not compatible with its own tupdesc"); *typeid = row->rowtupdesc->tdtypeid; *typetypmod = row->rowtupdesc->tdtypmod; - *value = HeapTupleGetDatum(tup); + *value = HeapTupleGetRawDatum(tup); *isnull = false; MemoryContextSwitchTo(oldcontext); break; @@ -7300,6 +7300,9 @@ make_tuple_from_row(PLpgSQL_execstate *estate, &dvalues[i], &nulls[i]); if (fieldtypeid != TupleDescAttr(tupdesc, i)->atttypid) return NULL; + if (!nulls[i] && TupleDescAttr(tupdesc, i)->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(dvalues[i]))) + dvalues[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(dvalues[i])); /* XXX should we insist on typmod match, too? */ } -- 2.17.0 --cvVnyQ+4j833TQvp Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-Disallow-compressed-data-inside-container-types.patch" ^ permalink raw reply [nested|flat] 49+ messages in thread
* [PATCH 2/8] Expand the external data before forming the tuple @ 2021-03-04 09:25 Dilip Kumar <[email protected]> 0 siblings, 0 replies; 49+ messages in thread From: Dilip Kumar @ 2021-03-04 09:25 UTC (permalink / raw) All the callers of HeapTupleGetDatum and HeapTupleHeaderGetDatum, who might contain the external varlena in their tuple, try to flatten the external varlena before forming the tuple wherever it is possible. Dilip Kumar based on idea by Robert Haas --- src/backend/executor/execExprInterp.c | 29 +++++++++++++++++++++++++-- src/backend/utils/adt/jsonfuncs.c | 8 ++++++-- src/pl/plpgsql/src/pl_exec.c | 5 ++++- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index 20949a5dec..c3754acca4 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -2840,12 +2840,25 @@ ExecEvalRow(ExprState *state, ExprEvalStep *op) { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < op->d.row.tupdesc->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(op->d.row.tupdesc, i); + + if (op->d.row.elemnulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.row.elemvalues[i]))) + continue; + + op->d.row.elemvalues[i] = + PointerGetDatum(PG_DETOAST_DATUM_PACKED(op->d.row.elemvalues[i])); + } + /* build tuple from evaluated field values */ tuple = heap_form_tuple(op->d.row.tupdesc, op->d.row.elemvalues, op->d.row.elemnulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } @@ -3085,12 +3098,24 @@ ExecEvalFieldStoreForm(ExprState *state, ExprEvalStep *op, ExprContext *econtext { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < (*op->d.fieldstore.argdesc)->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(*op->d.fieldstore.argdesc, i); + + if (op->d.fieldstore.nulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.fieldstore.values[i]))) + continue; + op->d.fieldstore.values[i] = PointerGetDatum( + PG_DETOAST_DATUM_PACKED(op->d.fieldstore.values[i])); + } + /* argdesc should already be valid from the DeForm step */ tuple = heap_form_tuple(*op->d.fieldstore.argdesc, op->d.fieldstore.values, op->d.fieldstore.nulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c index 511467280f..c3d464f42b 100644 --- a/src/backend/utils/adt/jsonfuncs.c +++ b/src/backend/utils/adt/jsonfuncs.c @@ -2968,7 +2968,7 @@ populate_composite(CompositeIOData *io, /* populate resulting record tuple */ tuple = populate_record(io->tupdesc, &io->record_io, defaultval, mcxt, &jso); - result = HeapTupleHeaderGetDatum(tuple); + result = HeapTupleHeaderGetRawDatum(tuple); JsObjectFree(&jso); } @@ -3387,6 +3387,10 @@ populate_record(TupleDesc tupdesc, nulls[i] ? (Datum) 0 : values[i], &field, &nulls[i]); + + if (!nulls[i] && att->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(values[i]))) + values[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(values[i])); } res = heap_form_tuple(tupdesc, values, nulls); @@ -3765,7 +3769,7 @@ populate_recordset_record(PopulateRecordsetState *state, JsObject *obj) /* if it's domain over composite, check domain constraints */ if (cache->c.typcat == TYPECAT_COMPOSITE_DOMAIN) - domain_check(HeapTupleHeaderGetDatum(tuphead), false, + domain_check(HeapTupleHeaderGetRawDatum(tuphead), false, cache->argtype, &cache->c.io.composite.domain_info, cache->fn_mcxt); diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index b4c70aaa7f..fd073767bc 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -5326,7 +5326,7 @@ exec_eval_datum(PLpgSQL_execstate *estate, elog(ERROR, "row not compatible with its own tupdesc"); *typeid = row->rowtupdesc->tdtypeid; *typetypmod = row->rowtupdesc->tdtypmod; - *value = HeapTupleGetDatum(tup); + *value = HeapTupleGetRawDatum(tup); *isnull = false; MemoryContextSwitchTo(oldcontext); break; @@ -7300,6 +7300,9 @@ make_tuple_from_row(PLpgSQL_execstate *estate, &dvalues[i], &nulls[i]); if (fieldtypeid != TupleDescAttr(tupdesc, i)->atttypid) return NULL; + if (!nulls[i] && TupleDescAttr(tupdesc, i)->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(dvalues[i]))) + dvalues[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(dvalues[i])); /* XXX should we insist on typmod match, too? */ } -- 2.17.0 --C94crkcyjafcjHxo Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-Disallow-compressed-data-inside-container-types.patch" ^ permalink raw reply [nested|flat] 49+ messages in thread
* [PATCH 2/8] Expand the external data before forming the tuple @ 2021-03-04 09:25 Dilip Kumar <[email protected]> 0 siblings, 0 replies; 49+ messages in thread From: Dilip Kumar @ 2021-03-04 09:25 UTC (permalink / raw) All the callers of HeapTupleGetDatum and HeapTupleHeaderGetDatum, who might contain the external varlena in their tuple, try to flatten the external varlena before forming the tuple wherever it is possible. Dilip Kumar based on idea by Robert Haas --- src/backend/executor/execExprInterp.c | 29 +++++++++++++++++++++++++-- src/backend/utils/adt/jsonfuncs.c | 8 ++++++-- src/pl/plpgsql/src/pl_exec.c | 5 ++++- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index 20949a5dec..c3754acca4 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -2840,12 +2840,25 @@ ExecEvalRow(ExprState *state, ExprEvalStep *op) { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < op->d.row.tupdesc->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(op->d.row.tupdesc, i); + + if (op->d.row.elemnulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.row.elemvalues[i]))) + continue; + + op->d.row.elemvalues[i] = + PointerGetDatum(PG_DETOAST_DATUM_PACKED(op->d.row.elemvalues[i])); + } + /* build tuple from evaluated field values */ tuple = heap_form_tuple(op->d.row.tupdesc, op->d.row.elemvalues, op->d.row.elemnulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } @@ -3085,12 +3098,24 @@ ExecEvalFieldStoreForm(ExprState *state, ExprEvalStep *op, ExprContext *econtext { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < (*op->d.fieldstore.argdesc)->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(*op->d.fieldstore.argdesc, i); + + if (op->d.fieldstore.nulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.fieldstore.values[i]))) + continue; + op->d.fieldstore.values[i] = PointerGetDatum( + PG_DETOAST_DATUM_PACKED(op->d.fieldstore.values[i])); + } + /* argdesc should already be valid from the DeForm step */ tuple = heap_form_tuple(*op->d.fieldstore.argdesc, op->d.fieldstore.values, op->d.fieldstore.nulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c index 511467280f..c3d464f42b 100644 --- a/src/backend/utils/adt/jsonfuncs.c +++ b/src/backend/utils/adt/jsonfuncs.c @@ -2968,7 +2968,7 @@ populate_composite(CompositeIOData *io, /* populate resulting record tuple */ tuple = populate_record(io->tupdesc, &io->record_io, defaultval, mcxt, &jso); - result = HeapTupleHeaderGetDatum(tuple); + result = HeapTupleHeaderGetRawDatum(tuple); JsObjectFree(&jso); } @@ -3387,6 +3387,10 @@ populate_record(TupleDesc tupdesc, nulls[i] ? (Datum) 0 : values[i], &field, &nulls[i]); + + if (!nulls[i] && att->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(values[i]))) + values[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(values[i])); } res = heap_form_tuple(tupdesc, values, nulls); @@ -3765,7 +3769,7 @@ populate_recordset_record(PopulateRecordsetState *state, JsObject *obj) /* if it's domain over composite, check domain constraints */ if (cache->c.typcat == TYPECAT_COMPOSITE_DOMAIN) - domain_check(HeapTupleHeaderGetDatum(tuphead), false, + domain_check(HeapTupleHeaderGetRawDatum(tuphead), false, cache->argtype, &cache->c.io.composite.domain_info, cache->fn_mcxt); diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index b4c70aaa7f..fd073767bc 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -5326,7 +5326,7 @@ exec_eval_datum(PLpgSQL_execstate *estate, elog(ERROR, "row not compatible with its own tupdesc"); *typeid = row->rowtupdesc->tdtypeid; *typetypmod = row->rowtupdesc->tdtypmod; - *value = HeapTupleGetDatum(tup); + *value = HeapTupleGetRawDatum(tup); *isnull = false; MemoryContextSwitchTo(oldcontext); break; @@ -7300,6 +7300,9 @@ make_tuple_from_row(PLpgSQL_execstate *estate, &dvalues[i], &nulls[i]); if (fieldtypeid != TupleDescAttr(tupdesc, i)->atttypid) return NULL; + if (!nulls[i] && TupleDescAttr(tupdesc, i)->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(dvalues[i]))) + dvalues[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(dvalues[i])); /* XXX should we insist on typmod match, too? */ } -- 2.17.0 --cvVnyQ+4j833TQvp Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-Disallow-compressed-data-inside-container-types.patch" ^ permalink raw reply [nested|flat] 49+ messages in thread
* [PATCH 2/8] Expand the external data before forming the tuple @ 2021-03-04 09:25 Dilip Kumar <[email protected]> 0 siblings, 0 replies; 49+ messages in thread From: Dilip Kumar @ 2021-03-04 09:25 UTC (permalink / raw) All the callers of HeapTupleGetDatum and HeapTupleHeaderGetDatum, who might contain the external varlena in their tuple, try to flatten the external varlena before forming the tuple wherever it is possible. Dilip Kumar based on idea by Robert Haas --- src/backend/executor/execExprInterp.c | 29 +++++++++++++++++++++++++-- src/backend/utils/adt/jsonfuncs.c | 8 ++++++-- src/pl/plpgsql/src/pl_exec.c | 5 ++++- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index 20949a5dec..c3754acca4 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -2840,12 +2840,25 @@ ExecEvalRow(ExprState *state, ExprEvalStep *op) { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < op->d.row.tupdesc->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(op->d.row.tupdesc, i); + + if (op->d.row.elemnulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.row.elemvalues[i]))) + continue; + + op->d.row.elemvalues[i] = + PointerGetDatum(PG_DETOAST_DATUM_PACKED(op->d.row.elemvalues[i])); + } + /* build tuple from evaluated field values */ tuple = heap_form_tuple(op->d.row.tupdesc, op->d.row.elemvalues, op->d.row.elemnulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } @@ -3085,12 +3098,24 @@ ExecEvalFieldStoreForm(ExprState *state, ExprEvalStep *op, ExprContext *econtext { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < (*op->d.fieldstore.argdesc)->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(*op->d.fieldstore.argdesc, i); + + if (op->d.fieldstore.nulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.fieldstore.values[i]))) + continue; + op->d.fieldstore.values[i] = PointerGetDatum( + PG_DETOAST_DATUM_PACKED(op->d.fieldstore.values[i])); + } + /* argdesc should already be valid from the DeForm step */ tuple = heap_form_tuple(*op->d.fieldstore.argdesc, op->d.fieldstore.values, op->d.fieldstore.nulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c index 511467280f..c3d464f42b 100644 --- a/src/backend/utils/adt/jsonfuncs.c +++ b/src/backend/utils/adt/jsonfuncs.c @@ -2968,7 +2968,7 @@ populate_composite(CompositeIOData *io, /* populate resulting record tuple */ tuple = populate_record(io->tupdesc, &io->record_io, defaultval, mcxt, &jso); - result = HeapTupleHeaderGetDatum(tuple); + result = HeapTupleHeaderGetRawDatum(tuple); JsObjectFree(&jso); } @@ -3387,6 +3387,10 @@ populate_record(TupleDesc tupdesc, nulls[i] ? (Datum) 0 : values[i], &field, &nulls[i]); + + if (!nulls[i] && att->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(values[i]))) + values[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(values[i])); } res = heap_form_tuple(tupdesc, values, nulls); @@ -3765,7 +3769,7 @@ populate_recordset_record(PopulateRecordsetState *state, JsObject *obj) /* if it's domain over composite, check domain constraints */ if (cache->c.typcat == TYPECAT_COMPOSITE_DOMAIN) - domain_check(HeapTupleHeaderGetDatum(tuphead), false, + domain_check(HeapTupleHeaderGetRawDatum(tuphead), false, cache->argtype, &cache->c.io.composite.domain_info, cache->fn_mcxt); diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index b4c70aaa7f..fd073767bc 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -5326,7 +5326,7 @@ exec_eval_datum(PLpgSQL_execstate *estate, elog(ERROR, "row not compatible with its own tupdesc"); *typeid = row->rowtupdesc->tdtypeid; *typetypmod = row->rowtupdesc->tdtypmod; - *value = HeapTupleGetDatum(tup); + *value = HeapTupleGetRawDatum(tup); *isnull = false; MemoryContextSwitchTo(oldcontext); break; @@ -7300,6 +7300,9 @@ make_tuple_from_row(PLpgSQL_execstate *estate, &dvalues[i], &nulls[i]); if (fieldtypeid != TupleDescAttr(tupdesc, i)->atttypid) return NULL; + if (!nulls[i] && TupleDescAttr(tupdesc, i)->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(dvalues[i]))) + dvalues[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(dvalues[i])); /* XXX should we insist on typmod match, too? */ } -- 2.17.0 --C94crkcyjafcjHxo Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-Disallow-compressed-data-inside-container-types.patch" ^ permalink raw reply [nested|flat] 49+ messages in thread
* [PATCH 2/8] Expand the external data before forming the tuple @ 2021-03-04 09:25 Dilip Kumar <[email protected]> 0 siblings, 0 replies; 49+ messages in thread From: Dilip Kumar @ 2021-03-04 09:25 UTC (permalink / raw) All the callers of HeapTupleGetDatum and HeapTupleHeaderGetDatum, who might contain the external varlena in their tuple, try to flatten the external varlena before forming the tuple wherever it is possible. Dilip Kumar based on idea by Robert Haas --- src/backend/executor/execExprInterp.c | 29 +++++++++++++++++++++++++-- src/backend/utils/adt/jsonfuncs.c | 8 ++++++-- src/pl/plpgsql/src/pl_exec.c | 5 ++++- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index 20949a5dec..c3754acca4 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -2840,12 +2840,25 @@ ExecEvalRow(ExprState *state, ExprEvalStep *op) { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < op->d.row.tupdesc->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(op->d.row.tupdesc, i); + + if (op->d.row.elemnulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.row.elemvalues[i]))) + continue; + + op->d.row.elemvalues[i] = + PointerGetDatum(PG_DETOAST_DATUM_PACKED(op->d.row.elemvalues[i])); + } + /* build tuple from evaluated field values */ tuple = heap_form_tuple(op->d.row.tupdesc, op->d.row.elemvalues, op->d.row.elemnulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } @@ -3085,12 +3098,24 @@ ExecEvalFieldStoreForm(ExprState *state, ExprEvalStep *op, ExprContext *econtext { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < (*op->d.fieldstore.argdesc)->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(*op->d.fieldstore.argdesc, i); + + if (op->d.fieldstore.nulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.fieldstore.values[i]))) + continue; + op->d.fieldstore.values[i] = PointerGetDatum( + PG_DETOAST_DATUM_PACKED(op->d.fieldstore.values[i])); + } + /* argdesc should already be valid from the DeForm step */ tuple = heap_form_tuple(*op->d.fieldstore.argdesc, op->d.fieldstore.values, op->d.fieldstore.nulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c index 511467280f..c3d464f42b 100644 --- a/src/backend/utils/adt/jsonfuncs.c +++ b/src/backend/utils/adt/jsonfuncs.c @@ -2968,7 +2968,7 @@ populate_composite(CompositeIOData *io, /* populate resulting record tuple */ tuple = populate_record(io->tupdesc, &io->record_io, defaultval, mcxt, &jso); - result = HeapTupleHeaderGetDatum(tuple); + result = HeapTupleHeaderGetRawDatum(tuple); JsObjectFree(&jso); } @@ -3387,6 +3387,10 @@ populate_record(TupleDesc tupdesc, nulls[i] ? (Datum) 0 : values[i], &field, &nulls[i]); + + if (!nulls[i] && att->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(values[i]))) + values[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(values[i])); } res = heap_form_tuple(tupdesc, values, nulls); @@ -3765,7 +3769,7 @@ populate_recordset_record(PopulateRecordsetState *state, JsObject *obj) /* if it's domain over composite, check domain constraints */ if (cache->c.typcat == TYPECAT_COMPOSITE_DOMAIN) - domain_check(HeapTupleHeaderGetDatum(tuphead), false, + domain_check(HeapTupleHeaderGetRawDatum(tuphead), false, cache->argtype, &cache->c.io.composite.domain_info, cache->fn_mcxt); diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index b4c70aaa7f..fd073767bc 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -5326,7 +5326,7 @@ exec_eval_datum(PLpgSQL_execstate *estate, elog(ERROR, "row not compatible with its own tupdesc"); *typeid = row->rowtupdesc->tdtypeid; *typetypmod = row->rowtupdesc->tdtypmod; - *value = HeapTupleGetDatum(tup); + *value = HeapTupleGetRawDatum(tup); *isnull = false; MemoryContextSwitchTo(oldcontext); break; @@ -7300,6 +7300,9 @@ make_tuple_from_row(PLpgSQL_execstate *estate, &dvalues[i], &nulls[i]); if (fieldtypeid != TupleDescAttr(tupdesc, i)->atttypid) return NULL; + if (!nulls[i] && TupleDescAttr(tupdesc, i)->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(dvalues[i]))) + dvalues[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(dvalues[i])); /* XXX should we insist on typmod match, too? */ } -- 2.17.0 --cvVnyQ+4j833TQvp Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-Disallow-compressed-data-inside-container-types.patch" ^ permalink raw reply [nested|flat] 49+ messages in thread
* [PATCH 2/8] Expand the external data before forming the tuple @ 2021-03-04 09:25 Dilip Kumar <[email protected]> 0 siblings, 0 replies; 49+ messages in thread From: Dilip Kumar @ 2021-03-04 09:25 UTC (permalink / raw) All the callers of HeapTupleGetDatum and HeapTupleHeaderGetDatum, who might contain the external varlena in their tuple, try to flatten the external varlena before forming the tuple wherever it is possible. Dilip Kumar based on idea by Robert Haas --- src/backend/executor/execExprInterp.c | 29 +++++++++++++++++++++++++-- src/backend/utils/adt/jsonfuncs.c | 8 ++++++-- src/pl/plpgsql/src/pl_exec.c | 5 ++++- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index 20949a5dec..c3754acca4 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -2840,12 +2840,25 @@ ExecEvalRow(ExprState *state, ExprEvalStep *op) { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < op->d.row.tupdesc->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(op->d.row.tupdesc, i); + + if (op->d.row.elemnulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.row.elemvalues[i]))) + continue; + + op->d.row.elemvalues[i] = + PointerGetDatum(PG_DETOAST_DATUM_PACKED(op->d.row.elemvalues[i])); + } + /* build tuple from evaluated field values */ tuple = heap_form_tuple(op->d.row.tupdesc, op->d.row.elemvalues, op->d.row.elemnulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } @@ -3085,12 +3098,24 @@ ExecEvalFieldStoreForm(ExprState *state, ExprEvalStep *op, ExprContext *econtext { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < (*op->d.fieldstore.argdesc)->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(*op->d.fieldstore.argdesc, i); + + if (op->d.fieldstore.nulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.fieldstore.values[i]))) + continue; + op->d.fieldstore.values[i] = PointerGetDatum( + PG_DETOAST_DATUM_PACKED(op->d.fieldstore.values[i])); + } + /* argdesc should already be valid from the DeForm step */ tuple = heap_form_tuple(*op->d.fieldstore.argdesc, op->d.fieldstore.values, op->d.fieldstore.nulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c index 511467280f..c3d464f42b 100644 --- a/src/backend/utils/adt/jsonfuncs.c +++ b/src/backend/utils/adt/jsonfuncs.c @@ -2968,7 +2968,7 @@ populate_composite(CompositeIOData *io, /* populate resulting record tuple */ tuple = populate_record(io->tupdesc, &io->record_io, defaultval, mcxt, &jso); - result = HeapTupleHeaderGetDatum(tuple); + result = HeapTupleHeaderGetRawDatum(tuple); JsObjectFree(&jso); } @@ -3387,6 +3387,10 @@ populate_record(TupleDesc tupdesc, nulls[i] ? (Datum) 0 : values[i], &field, &nulls[i]); + + if (!nulls[i] && att->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(values[i]))) + values[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(values[i])); } res = heap_form_tuple(tupdesc, values, nulls); @@ -3765,7 +3769,7 @@ populate_recordset_record(PopulateRecordsetState *state, JsObject *obj) /* if it's domain over composite, check domain constraints */ if (cache->c.typcat == TYPECAT_COMPOSITE_DOMAIN) - domain_check(HeapTupleHeaderGetDatum(tuphead), false, + domain_check(HeapTupleHeaderGetRawDatum(tuphead), false, cache->argtype, &cache->c.io.composite.domain_info, cache->fn_mcxt); diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index b4c70aaa7f..fd073767bc 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -5326,7 +5326,7 @@ exec_eval_datum(PLpgSQL_execstate *estate, elog(ERROR, "row not compatible with its own tupdesc"); *typeid = row->rowtupdesc->tdtypeid; *typetypmod = row->rowtupdesc->tdtypmod; - *value = HeapTupleGetDatum(tup); + *value = HeapTupleGetRawDatum(tup); *isnull = false; MemoryContextSwitchTo(oldcontext); break; @@ -7300,6 +7300,9 @@ make_tuple_from_row(PLpgSQL_execstate *estate, &dvalues[i], &nulls[i]); if (fieldtypeid != TupleDescAttr(tupdesc, i)->atttypid) return NULL; + if (!nulls[i] && TupleDescAttr(tupdesc, i)->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(dvalues[i]))) + dvalues[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(dvalues[i])); /* XXX should we insist on typmod match, too? */ } -- 2.17.0 --C94crkcyjafcjHxo Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-Disallow-compressed-data-inside-container-types.patch" ^ permalink raw reply [nested|flat] 49+ messages in thread
* [PATCH 2/8] Expand the external data before forming the tuple @ 2021-03-04 09:25 Dilip Kumar <[email protected]> 0 siblings, 0 replies; 49+ messages in thread From: Dilip Kumar @ 2021-03-04 09:25 UTC (permalink / raw) All the callers of HeapTupleGetDatum and HeapTupleHeaderGetDatum, who might contain the external varlena in their tuple, try to flatten the external varlena before forming the tuple wherever it is possible. Dilip Kumar based on idea by Robert Haas --- src/backend/executor/execExprInterp.c | 29 +++++++++++++++++++++++++-- src/backend/utils/adt/jsonfuncs.c | 8 ++++++-- src/pl/plpgsql/src/pl_exec.c | 5 ++++- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index 20949a5dec..c3754acca4 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -2840,12 +2840,25 @@ ExecEvalRow(ExprState *state, ExprEvalStep *op) { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < op->d.row.tupdesc->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(op->d.row.tupdesc, i); + + if (op->d.row.elemnulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.row.elemvalues[i]))) + continue; + + op->d.row.elemvalues[i] = + PointerGetDatum(PG_DETOAST_DATUM_PACKED(op->d.row.elemvalues[i])); + } + /* build tuple from evaluated field values */ tuple = heap_form_tuple(op->d.row.tupdesc, op->d.row.elemvalues, op->d.row.elemnulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } @@ -3085,12 +3098,24 @@ ExecEvalFieldStoreForm(ExprState *state, ExprEvalStep *op, ExprContext *econtext { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < (*op->d.fieldstore.argdesc)->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(*op->d.fieldstore.argdesc, i); + + if (op->d.fieldstore.nulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.fieldstore.values[i]))) + continue; + op->d.fieldstore.values[i] = PointerGetDatum( + PG_DETOAST_DATUM_PACKED(op->d.fieldstore.values[i])); + } + /* argdesc should already be valid from the DeForm step */ tuple = heap_form_tuple(*op->d.fieldstore.argdesc, op->d.fieldstore.values, op->d.fieldstore.nulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c index 511467280f..c3d464f42b 100644 --- a/src/backend/utils/adt/jsonfuncs.c +++ b/src/backend/utils/adt/jsonfuncs.c @@ -2968,7 +2968,7 @@ populate_composite(CompositeIOData *io, /* populate resulting record tuple */ tuple = populate_record(io->tupdesc, &io->record_io, defaultval, mcxt, &jso); - result = HeapTupleHeaderGetDatum(tuple); + result = HeapTupleHeaderGetRawDatum(tuple); JsObjectFree(&jso); } @@ -3387,6 +3387,10 @@ populate_record(TupleDesc tupdesc, nulls[i] ? (Datum) 0 : values[i], &field, &nulls[i]); + + if (!nulls[i] && att->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(values[i]))) + values[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(values[i])); } res = heap_form_tuple(tupdesc, values, nulls); @@ -3765,7 +3769,7 @@ populate_recordset_record(PopulateRecordsetState *state, JsObject *obj) /* if it's domain over composite, check domain constraints */ if (cache->c.typcat == TYPECAT_COMPOSITE_DOMAIN) - domain_check(HeapTupleHeaderGetDatum(tuphead), false, + domain_check(HeapTupleHeaderGetRawDatum(tuphead), false, cache->argtype, &cache->c.io.composite.domain_info, cache->fn_mcxt); diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index b4c70aaa7f..fd073767bc 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -5326,7 +5326,7 @@ exec_eval_datum(PLpgSQL_execstate *estate, elog(ERROR, "row not compatible with its own tupdesc"); *typeid = row->rowtupdesc->tdtypeid; *typetypmod = row->rowtupdesc->tdtypmod; - *value = HeapTupleGetDatum(tup); + *value = HeapTupleGetRawDatum(tup); *isnull = false; MemoryContextSwitchTo(oldcontext); break; @@ -7300,6 +7300,9 @@ make_tuple_from_row(PLpgSQL_execstate *estate, &dvalues[i], &nulls[i]); if (fieldtypeid != TupleDescAttr(tupdesc, i)->atttypid) return NULL; + if (!nulls[i] && TupleDescAttr(tupdesc, i)->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(dvalues[i]))) + dvalues[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(dvalues[i])); /* XXX should we insist on typmod match, too? */ } -- 2.17.0 --cvVnyQ+4j833TQvp Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-Disallow-compressed-data-inside-container-types.patch" ^ permalink raw reply [nested|flat] 49+ messages in thread
* [PATCH 2/8] Expand the external data before forming the tuple @ 2021-03-04 09:25 Dilip Kumar <[email protected]> 0 siblings, 0 replies; 49+ messages in thread From: Dilip Kumar @ 2021-03-04 09:25 UTC (permalink / raw) All the callers of HeapTupleGetDatum and HeapTupleHeaderGetDatum, who might contain the external varlena in their tuple, try to flatten the external varlena before forming the tuple wherever it is possible. Dilip Kumar based on idea by Robert Haas --- src/backend/executor/execExprInterp.c | 29 +++++++++++++++++++++++++-- src/backend/utils/adt/jsonfuncs.c | 8 ++++++-- src/pl/plpgsql/src/pl_exec.c | 5 ++++- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index 20949a5dec..c3754acca4 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -2840,12 +2840,25 @@ ExecEvalRow(ExprState *state, ExprEvalStep *op) { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < op->d.row.tupdesc->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(op->d.row.tupdesc, i); + + if (op->d.row.elemnulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.row.elemvalues[i]))) + continue; + + op->d.row.elemvalues[i] = + PointerGetDatum(PG_DETOAST_DATUM_PACKED(op->d.row.elemvalues[i])); + } + /* build tuple from evaluated field values */ tuple = heap_form_tuple(op->d.row.tupdesc, op->d.row.elemvalues, op->d.row.elemnulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } @@ -3085,12 +3098,24 @@ ExecEvalFieldStoreForm(ExprState *state, ExprEvalStep *op, ExprContext *econtext { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < (*op->d.fieldstore.argdesc)->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(*op->d.fieldstore.argdesc, i); + + if (op->d.fieldstore.nulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.fieldstore.values[i]))) + continue; + op->d.fieldstore.values[i] = PointerGetDatum( + PG_DETOAST_DATUM_PACKED(op->d.fieldstore.values[i])); + } + /* argdesc should already be valid from the DeForm step */ tuple = heap_form_tuple(*op->d.fieldstore.argdesc, op->d.fieldstore.values, op->d.fieldstore.nulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c index 511467280f..c3d464f42b 100644 --- a/src/backend/utils/adt/jsonfuncs.c +++ b/src/backend/utils/adt/jsonfuncs.c @@ -2968,7 +2968,7 @@ populate_composite(CompositeIOData *io, /* populate resulting record tuple */ tuple = populate_record(io->tupdesc, &io->record_io, defaultval, mcxt, &jso); - result = HeapTupleHeaderGetDatum(tuple); + result = HeapTupleHeaderGetRawDatum(tuple); JsObjectFree(&jso); } @@ -3387,6 +3387,10 @@ populate_record(TupleDesc tupdesc, nulls[i] ? (Datum) 0 : values[i], &field, &nulls[i]); + + if (!nulls[i] && att->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(values[i]))) + values[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(values[i])); } res = heap_form_tuple(tupdesc, values, nulls); @@ -3765,7 +3769,7 @@ populate_recordset_record(PopulateRecordsetState *state, JsObject *obj) /* if it's domain over composite, check domain constraints */ if (cache->c.typcat == TYPECAT_COMPOSITE_DOMAIN) - domain_check(HeapTupleHeaderGetDatum(tuphead), false, + domain_check(HeapTupleHeaderGetRawDatum(tuphead), false, cache->argtype, &cache->c.io.composite.domain_info, cache->fn_mcxt); diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index b4c70aaa7f..fd073767bc 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -5326,7 +5326,7 @@ exec_eval_datum(PLpgSQL_execstate *estate, elog(ERROR, "row not compatible with its own tupdesc"); *typeid = row->rowtupdesc->tdtypeid; *typetypmod = row->rowtupdesc->tdtypmod; - *value = HeapTupleGetDatum(tup); + *value = HeapTupleGetRawDatum(tup); *isnull = false; MemoryContextSwitchTo(oldcontext); break; @@ -7300,6 +7300,9 @@ make_tuple_from_row(PLpgSQL_execstate *estate, &dvalues[i], &nulls[i]); if (fieldtypeid != TupleDescAttr(tupdesc, i)->atttypid) return NULL; + if (!nulls[i] && TupleDescAttr(tupdesc, i)->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(dvalues[i]))) + dvalues[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(dvalues[i])); /* XXX should we insist on typmod match, too? */ } -- 2.17.0 --C94crkcyjafcjHxo Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-Disallow-compressed-data-inside-container-types.patch" ^ permalink raw reply [nested|flat] 49+ messages in thread
* [PATCH 2/8] Expand the external data before forming the tuple @ 2021-03-04 09:25 Dilip Kumar <[email protected]> 0 siblings, 0 replies; 49+ messages in thread From: Dilip Kumar @ 2021-03-04 09:25 UTC (permalink / raw) All the callers of HeapTupleGetDatum and HeapTupleHeaderGetDatum, who might contain the external varlena in their tuple, try to flatten the external varlena before forming the tuple wherever it is possible. Dilip Kumar based on idea by Robert Haas --- src/backend/executor/execExprInterp.c | 29 +++++++++++++++++++++++++-- src/backend/utils/adt/jsonfuncs.c | 8 ++++++-- src/pl/plpgsql/src/pl_exec.c | 5 ++++- 3 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index 20949a5dec..c3754acca4 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -2840,12 +2840,25 @@ ExecEvalRow(ExprState *state, ExprEvalStep *op) { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < op->d.row.tupdesc->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(op->d.row.tupdesc, i); + + if (op->d.row.elemnulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.row.elemvalues[i]))) + continue; + + op->d.row.elemvalues[i] = + PointerGetDatum(PG_DETOAST_DATUM_PACKED(op->d.row.elemvalues[i])); + } + /* build tuple from evaluated field values */ tuple = heap_form_tuple(op->d.row.tupdesc, op->d.row.elemvalues, op->d.row.elemnulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } @@ -3085,12 +3098,24 @@ ExecEvalFieldStoreForm(ExprState *state, ExprEvalStep *op, ExprContext *econtext { HeapTuple tuple; + /* Retrieve externally stored values and decompress. */ + for (int i = 0; i < (*op->d.fieldstore.argdesc)->natts; i++) + { + Form_pg_attribute attr = TupleDescAttr(*op->d.fieldstore.argdesc, i); + + if (op->d.fieldstore.nulls[i] || attr->attlen != -1 || + !VARATT_IS_EXTERNAL(DatumGetPointer(op->d.fieldstore.values[i]))) + continue; + op->d.fieldstore.values[i] = PointerGetDatum( + PG_DETOAST_DATUM_PACKED(op->d.fieldstore.values[i])); + } + /* argdesc should already be valid from the DeForm step */ tuple = heap_form_tuple(*op->d.fieldstore.argdesc, op->d.fieldstore.values, op->d.fieldstore.nulls); - *op->resvalue = HeapTupleGetDatum(tuple); + *op->resvalue = HeapTupleGetRawDatum(tuple); *op->resnull = false; } diff --git a/src/backend/utils/adt/jsonfuncs.c b/src/backend/utils/adt/jsonfuncs.c index 511467280f..c3d464f42b 100644 --- a/src/backend/utils/adt/jsonfuncs.c +++ b/src/backend/utils/adt/jsonfuncs.c @@ -2968,7 +2968,7 @@ populate_composite(CompositeIOData *io, /* populate resulting record tuple */ tuple = populate_record(io->tupdesc, &io->record_io, defaultval, mcxt, &jso); - result = HeapTupleHeaderGetDatum(tuple); + result = HeapTupleHeaderGetRawDatum(tuple); JsObjectFree(&jso); } @@ -3387,6 +3387,10 @@ populate_record(TupleDesc tupdesc, nulls[i] ? (Datum) 0 : values[i], &field, &nulls[i]); + + if (!nulls[i] && att->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(values[i]))) + values[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(values[i])); } res = heap_form_tuple(tupdesc, values, nulls); @@ -3765,7 +3769,7 @@ populate_recordset_record(PopulateRecordsetState *state, JsObject *obj) /* if it's domain over composite, check domain constraints */ if (cache->c.typcat == TYPECAT_COMPOSITE_DOMAIN) - domain_check(HeapTupleHeaderGetDatum(tuphead), false, + domain_check(HeapTupleHeaderGetRawDatum(tuphead), false, cache->argtype, &cache->c.io.composite.domain_info, cache->fn_mcxt); diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index b4c70aaa7f..fd073767bc 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -5326,7 +5326,7 @@ exec_eval_datum(PLpgSQL_execstate *estate, elog(ERROR, "row not compatible with its own tupdesc"); *typeid = row->rowtupdesc->tdtypeid; *typetypmod = row->rowtupdesc->tdtypmod; - *value = HeapTupleGetDatum(tup); + *value = HeapTupleGetRawDatum(tup); *isnull = false; MemoryContextSwitchTo(oldcontext); break; @@ -7300,6 +7300,9 @@ make_tuple_from_row(PLpgSQL_execstate *estate, &dvalues[i], &nulls[i]); if (fieldtypeid != TupleDescAttr(tupdesc, i)->atttypid) return NULL; + if (!nulls[i] && TupleDescAttr(tupdesc, i)->attlen == -1 && + VARATT_IS_EXTERNAL(DatumGetPointer(dvalues[i]))) + dvalues[i] = PointerGetDatum(PG_DETOAST_DATUM_PACKED(dvalues[i])); /* XXX should we insist on typmod match, too? */ } -- 2.17.0 --cvVnyQ+4j833TQvp Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0003-Disallow-compressed-data-inside-container-types.patch" ^ permalink raw reply [nested|flat] 49+ messages in thread
* Re: [Proposal] Fully WAL logged CREATE DATABASE - No Checkpoints @ 2022-02-08 17:09 Robert Haas <[email protected]> 0 siblings, 0 replies; 49+ messages in thread From: Robert Haas @ 2022-02-08 17:09 UTC (permalink / raw) To: Ashutosh Sharma <[email protected]>; +Cc: Dilip Kumar <[email protected]>; Greg Nancarrow <[email protected]>; Andres Freund <[email protected]>; Heikki Linnakangas <[email protected]>; PostgreSQL Hackers <[email protected]> On Mon, Dec 6, 2021 at 12:45 PM Robert Haas <[email protected]> wrote: > So for example, imagine tests with 1GB of shard_buffers, 8GB, and > 64GB. And template databases with sizes of whatever the default is, > 1GB, 10GB, 100GB. Repeatedly make 75% of the pages dirty and then > create a new database from one of the templates. And then just measure > the performance. Maybe for large databases this approach is just > really the pits -- and if your max_wal_size is too small, it > definitely will be. But, I don't know, maybe with reasonable settings > it's not that bad. Writing everything to disk twice - once to WAL and > once to the target directory - has to be more expensive than doing it > once. But on the other hand, it's all sequential I/O and the data > pages don't need to be fsync'd, so perhaps the overhead is relatively > mild. I don't know. I have been tied up with other things for a bit now and have not had time to look at this thread; sorry about that. I have a little more time available now so I thought I would take a look at this again and see where things stand. Sadly, it doesn't appear to me that anyone has done any performance testing of this patch, along the lines suggested above or otherwise, and I think it's a crucial question for the patch. My reading of this thread is that nobody really likes the idea of maintaining two methods for performing CREATE DATABASE, but nobody wants to hose people who are using it to clone large databases, either. To some extent those things are inexorably in conflict. If we postulate that the 10TB template database is on a local RAID array with 40 spindles, while pg_wal is on an iSCSI volume that we access via a 128kB ISDN link, then the new system is going to be infinitely worse. But real situations aren't likely to be that bad, and it would be useful in my opinion to have an idea how bad they actually are. I'm somewhat inclined to propose that we keep the existing method around along with the new method. Even though nobody really likes that, we don't necessarily have to maintain both methods forever. If, say, we use the new method by default in all cases, but add an option to get the old method back if you need it, we could leave it that way for a few years and then propose removing the old method (and the switch to activate it) and see if anyone complains. That way, if the new method turns out to suck in certain cases, users have a way out. However, I still think doing some performance testing would be a really good idea. It's not a great plan to make decisions about this kind of thing in an information vacuum. -- Robert Haas EDB: http://www.enterprisedb.com ^ permalink raw reply [nested|flat] 49+ messages in thread
end of thread, other threads:[~2022-02-08 17:09 UTC | newest] Thread overview: 49+ messages (download: mbox mbox.gz follow: Atom feed) -- links below jump to the message on this page -- 2021-03-04 09:25 [PATCH 2/8] Expand the external data before forming the tuple Dilip Kumar <[email protected]> 2021-03-04 09:25 [PATCH 2/8] Expand the external data before forming the tuple Dilip Kumar <[email protected]> 2021-03-04 09:25 [PATCH 2/8] Expand the external data before forming the tuple Dilip Kumar <[email protected]> 2021-03-04 09:25 [PATCH 2/8] Expand the external data before forming the tuple Dilip Kumar <[email protected]> 2021-03-04 09:25 [PATCH 2/8] Expand the external data before forming the tuple Dilip Kumar <[email protected]> 2021-03-04 09:25 [PATCH 2/8] Expand the external data before forming the tuple Dilip Kumar <[email protected]> 2021-03-04 09:25 [PATCH 2/8] Expand the external data before forming the tuple Dilip Kumar <[email protected]> 2021-03-04 09:25 [PATCH 2/8] Expand the external data before forming the tuple Dilip Kumar <[email protected]> 2021-03-04 09:25 [PATCH 2/8] Expand the external data before forming the tuple Dilip Kumar <[email protected]> 2021-03-04 09:25 [PATCH 2/8] Expand the external data before forming the tuple Dilip Kumar <[email protected]> 2021-03-04 09:25 [PATCH 2/8] Expand the external data before forming the tuple Dilip Kumar <[email protected]> 2021-03-04 09:25 [PATCH 2/8] Expand the external data before forming the tuple Dilip Kumar <[email protected]> 2021-03-04 09:25 [PATCH 2/8] Expand the external data before forming the tuple Dilip Kumar <[email protected]> 2021-03-04 09:25 [PATCH 2/8] Expand the external data before forming the tuple Dilip Kumar <[email protected]> 2021-03-04 09:25 [PATCH 2/8] Expand the external data before forming the tuple Dilip Kumar <[email protected]> 2021-03-04 09:25 [PATCH 2/8] Expand the external data before forming the tuple Dilip Kumar <[email protected]> 2021-03-04 09:25 [PATCH 2/8] Expand the external data before forming the tuple Dilip Kumar <[email protected]> 2021-03-04 09:25 [PATCH 2/8] Expand the external data before forming the tuple Dilip Kumar <[email protected]> 2021-03-04 09:25 [PATCH 2/8] Expand the external data before forming the tuple Dilip Kumar <[email protected]> 2021-03-04 09:25 [PATCH 2/8] Expand the external data before forming the tuple Dilip Kumar <[email protected]> 2021-03-04 09:25 [PATCH 2/8] Expand the external data before forming the tuple Dilip Kumar <[email protected]> 2021-03-04 09:25 [PATCH 2/8] Expand the external data before forming the tuple Dilip Kumar <[email protected]> 2021-03-04 09:25 [PATCH 2/8] Expand the external data before forming the tuple Dilip Kumar <[email protected]> 2021-03-04 09:25 [PATCH 2/8] Expand the external data before forming the tuple Dilip Kumar <[email protected]> 2021-03-04 09:25 [PATCH 2/8] Expand the external data before forming the tuple Dilip Kumar <[email protected]> 2021-03-04 09:25 [PATCH 2/8] Expand the external data before forming the tuple Dilip Kumar <[email protected]> 2021-03-04 09:25 [PATCH 2/8] Expand the external data before forming the tuple Dilip Kumar <[email protected]> 2021-03-04 09:25 [PATCH 2/8] Expand the external data before forming the tuple Dilip Kumar <[email protected]> 2021-03-04 09:25 [PATCH 2/8] Expand the external data before forming the tuple Dilip Kumar <[email protected]> 2021-03-04 09:25 [PATCH 2/8] Expand the external data before forming the tuple Dilip Kumar <[email protected]> 2021-03-04 09:25 [PATCH 2/8] Expand the external data before forming the tuple Dilip Kumar <[email protected]> 2021-03-04 09:25 [PATCH 2/8] Expand the external data before forming the tuple Dilip Kumar <[email protected]> 2021-03-04 09:25 [PATCH 2/8] Expand the external data before forming the tuple Dilip Kumar <[email protected]> 2021-03-04 09:25 [PATCH 2/8] Expand the external data before forming the tuple Dilip Kumar <[email protected]> 2021-03-04 09:25 [PATCH 2/8] Expand the external data before forming the tuple Dilip Kumar <[email protected]> 2021-03-04 09:25 [PATCH 2/8] Expand the external data before forming the tuple Dilip Kumar <[email protected]> 2021-03-04 09:25 [PATCH 2/8] Expand the external data before forming the tuple Dilip Kumar <[email protected]> 2021-03-04 09:25 [PATCH 2/8] Expand the external data before forming the tuple Dilip Kumar <[email protected]> 2021-03-04 09:25 [PATCH 2/8] Expand the external data before forming the tuple Dilip Kumar <[email protected]> 2021-03-04 09:25 [PATCH 2/8] Expand the external data before forming the tuple Dilip Kumar <[email protected]> 2021-03-04 09:25 [PATCH 2/8] Expand the external data before forming the tuple Dilip Kumar <[email protected]> 2021-03-04 09:25 [PATCH 2/8] Expand the external data before forming the tuple Dilip Kumar <[email protected]> 2021-03-04 09:25 [PATCH 2/8] Expand the external data before forming the tuple Dilip Kumar <[email protected]> 2021-03-04 09:25 [PATCH 2/8] Expand the external data before forming the tuple Dilip Kumar <[email protected]> 2021-03-04 09:25 [PATCH 2/8] Expand the external data before forming the tuple Dilip Kumar <[email protected]> 2021-03-04 09:25 [PATCH 2/8] Expand the external data before forming the tuple Dilip Kumar <[email protected]> 2021-03-04 09:25 [PATCH 2/8] Expand the external data before forming the tuple Dilip Kumar <[email protected]> 2021-03-04 09:25 [PATCH 2/8] Expand the external data before forming the tuple Dilip Kumar <[email protected]> 2022-02-08 17:09 Re: [Proposal] Fully WAL logged CREATE DATABASE - No Checkpoints Robert Haas <[email protected]>
This inbox is served by agora; see mirroring instructions for how to clone and mirror all data and code used for this inbox