Re: delta relations in AFTER triggers
От | Robert Haas |
---|---|
Тема | Re: delta relations in AFTER triggers |
Дата | |
Msg-id | CA+TgmobHV=TF_MOnrQJk+icZh6arWHDUSQaAG=pTU-HYyxGTJA@mail.gmail.com обсуждение исходный текст |
Ответ на | Re: delta relations in AFTER triggers (Robert Haas <robertmhaas@gmail.com>) |
Ответы |
Re: delta relations in AFTER triggers
(Kevin Grittner <kgrittn@ymail.com>)
|
Список | pgsql-hackers |
On Thu, Oct 23, 2014 at 11:19 AM, Robert Haas <robertmhaas@gmail.com> wrote: > So what I'm imagining now is: > > 1. During parse analysis, p_tableref_hook gets control and calls > addRangeTableEntryForTuplestore(), creating an RTE of type > RTE_TUPLESTORE. The RTE stores an integer parameter-index. > > 2. Path generation doesn't need to do anything very exciting; it just > generates a Path node of type T_TuplestoreScan. The RTE is still > available, so the path itself doesn't need to know which tuplestore > we're referencing, because that information is present in the RTE. > > 3. At plan generation time, we look up the RTE for the path and > extract the parameter index, which is what gets stored in the > TuplestoreScan node. > > 4. At executor initialization time, we use the parameter index in the > TuplestoreScan to index into the EState's es_param_list_info and > retrieve the tuplestore. I spent some time poking at this yesterday, based on commit 5060b9352b0d0301ffb002355f0572e93f8b05fe from https://github.com/kgrittn/postgres.git Here's where I got stuck: The plpgsql_parser_setup() callback sets pstate->p_ref_hook_state = (void *) expr, so if we add p_tableref_hook as an additional callback, that's what it has to work with to find the information needed to generate a RangeTblEntry. That is a PLpgSQL_expr, and it contains a pointer to the PLpgSQL_function, which is created when the function is compiled, which seems good, but the information we need is not there. Specifically, we need to know the names the user picked for the old and new tuplestores (tgoldtable and tgnewtable) and we need to know what the tuple descriptor should be, and the PLpgSQL_function hasn't got it. It does not seem impossible to fix that, but I'm not sure it's safe. do_compile() has the FunctionCallInfo, so from there it can get at the TriggerData and the Trigger. The trigger has got tgoldtable and tgnewtable, and the TriggerData has got tg_relation, so everything we need is there. We could add pointers to the relevant stuff to the PLpgSQL_function, and then the parser callbacks could get at it. However, I'm not sure that's really OK -- presumably, tg_relation is going to be valid only during the initial compile. If somebody came back and looked at that PLpgSQL_function again later, and tried to follow that pointer, bad things would happen. In practice maybe it would be OK because the only likely reason to come back and look at the PLpgSQL_function again is because we're recompiling, and at that point we'd have a new relation pointer to copy in there, and so it would probably be OK. But that feels mighty ugly. Another idea is to change what actually gets passed to the parser callback. Right now we just pass the PLpgSQL_expr. If we created a new structure that contained that plus the PLpgSQL_execstate, we'd be in fine shape. But this sort of gets at the root of the problem here: with variables, the parser callback doesn't return the actual *value*, it returns a Param node that will later, at execution time, be looked up to find the actual value. With relations, we're sort of doing the same thing - the tuplestore RTE doesn't need to contain the actual data, just the tuple descriptor. But the data structures from which we can get that information also contain the actual execution-time information, so passing them into parse-time callbacks seems like it might be, if nothing else, a recipe for future bugs. Any suggestions? -- Robert Haas EnterpriseDB: http://www.enterprisedb.com The Enterprise PostgreSQL Company
В списке pgsql-hackers по дате отправления: