diff options
author | Peter Eisentraut <peter@eisentraut.org> | 2019-03-30 08:13:09 +0100 |
---|---|---|
committer | Peter Eisentraut <peter@eisentraut.org> | 2019-03-30 08:15:57 +0100 |
commit | fc22b6623b6b3bab3cb057ccd282c2bfad1a0b30 (patch) | |
tree | cda5092955ece5d547d5517ed56a3d480f199d25 /src/pl/plperl/plperl.c | |
parent | 6b8b5364ddd0e4d882562615c6b6c28638ade9f2 (diff) |
Generated columns
This is an SQL-standard feature that allows creating columns that are
computed from expressions rather than assigned, similar to a view or
materialized view but on a column basis.
This implements one kind of generated column: stored (computed on
write). Another kind, virtual (computed on read), is planned for the
future, and some room is left for it.
Reviewed-by: Michael Paquier <michael@paquier.xyz>
Reviewed-by: Pavel Stehule <pavel.stehule@gmail.com>
Discussion: https://www.postgresql.org/message-id/flat/b151f851-4019-bdb1-699e-ebab07d2f40a@2ndquadrant.com
Diffstat (limited to 'src/pl/plperl/plperl.c')
-rw-r--r-- | src/pl/plperl/plperl.c | 40 |
1 files changed, 31 insertions, 9 deletions
diff --git a/src/pl/plperl/plperl.c b/src/pl/plperl/plperl.c index 35d5d121a08..31ba2f262f7 100644 --- a/src/pl/plperl/plperl.c +++ b/src/pl/plperl/plperl.c @@ -266,7 +266,7 @@ static plperl_proc_desc *compile_plperl_function(Oid fn_oid, bool is_trigger, bool is_event_trigger); -static SV *plperl_hash_from_tuple(HeapTuple tuple, TupleDesc tupdesc); +static SV *plperl_hash_from_tuple(HeapTuple tuple, TupleDesc tupdesc, bool include_generated); static SV *plperl_hash_from_datum(Datum attr); static SV *plperl_ref_from_pg_array(Datum arg, Oid typid); static SV *split_array(plperl_array_info *info, int first, int last, int nest); @@ -1644,13 +1644,19 @@ plperl_trigger_build_args(FunctionCallInfo fcinfo) hv_store_string(hv, "name", cstr2sv(tdata->tg_trigger->tgname)); hv_store_string(hv, "relid", cstr2sv(relid)); + /* + * Note: In BEFORE trigger, stored generated columns are not computed yet, + * so don't make them accessible in NEW row. + */ + if (TRIGGER_FIRED_BY_INSERT(tdata->tg_event)) { event = "INSERT"; if (TRIGGER_FIRED_FOR_ROW(tdata->tg_event)) hv_store_string(hv, "new", plperl_hash_from_tuple(tdata->tg_trigtuple, - tupdesc)); + tupdesc, + !TRIGGER_FIRED_BEFORE(tdata->tg_event))); } else if (TRIGGER_FIRED_BY_DELETE(tdata->tg_event)) { @@ -1658,7 +1664,8 @@ plperl_trigger_build_args(FunctionCallInfo fcinfo) if (TRIGGER_FIRED_FOR_ROW(tdata->tg_event)) hv_store_string(hv, "old", plperl_hash_from_tuple(tdata->tg_trigtuple, - tupdesc)); + tupdesc, + true)); } else if (TRIGGER_FIRED_BY_UPDATE(tdata->tg_event)) { @@ -1667,10 +1674,12 @@ plperl_trigger_build_args(FunctionCallInfo fcinfo) { hv_store_string(hv, "old", plperl_hash_from_tuple(tdata->tg_trigtuple, - tupdesc)); + tupdesc, + true)); hv_store_string(hv, "new", plperl_hash_from_tuple(tdata->tg_newtuple, - tupdesc)); + tupdesc, + !TRIGGER_FIRED_BEFORE(tdata->tg_event))); } } else if (TRIGGER_FIRED_BY_TRUNCATE(tdata->tg_event)) @@ -1791,6 +1800,11 @@ plperl_modify_tuple(HV *hvTD, TriggerData *tdata, HeapTuple otup) (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("cannot set system attribute \"%s\"", key))); + if (attr->attgenerated) + ereport(ERROR, + (errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED), + errmsg("cannot set generated column \"%s\"", + key))); modvalues[attn - 1] = plperl_sv_to_datum(val, attr->atttypid, @@ -3012,7 +3026,7 @@ plperl_hash_from_datum(Datum attr) tmptup.t_len = HeapTupleHeaderGetDatumLength(td); tmptup.t_data = td; - sv = plperl_hash_from_tuple(&tmptup, tupdesc); + sv = plperl_hash_from_tuple(&tmptup, tupdesc, true); ReleaseTupleDesc(tupdesc); return sv; @@ -3020,7 +3034,7 @@ plperl_hash_from_datum(Datum attr) /* Build a hash from all attributes of a given tuple. */ static SV * -plperl_hash_from_tuple(HeapTuple tuple, TupleDesc tupdesc) +plperl_hash_from_tuple(HeapTuple tuple, TupleDesc tupdesc, bool include_generated) { dTHX; HV *hv; @@ -3044,6 +3058,13 @@ plperl_hash_from_tuple(HeapTuple tuple, TupleDesc tupdesc) if (att->attisdropped) continue; + if (att->attgenerated) + { + /* don't include unless requested */ + if (!include_generated) + continue; + } + attname = NameStr(att->attname); attr = heap_getattr(tuple, i + 1, tupdesc, &isnull); @@ -3198,7 +3219,7 @@ plperl_spi_execute_fetch_result(SPITupleTable *tuptable, uint64 processed, av_extend(rows, processed); for (i = 0; i < processed; i++) { - row = plperl_hash_from_tuple(tuptable->vals[i], tuptable->tupdesc); + row = plperl_hash_from_tuple(tuptable->vals[i], tuptable->tupdesc, true); av_push(rows, row); } hv_store_string(result, "rows", @@ -3484,7 +3505,8 @@ plperl_spi_fetchrow(char *cursor) else { row = plperl_hash_from_tuple(SPI_tuptable->vals[0], - SPI_tuptable->tupdesc); + SPI_tuptable->tupdesc, + true); } SPI_freetuptable(SPI_tuptable); } |