Thread: Is querying SPITupleTable with SQL possible?
Dear Hackers I am using PostgreSQL's SPI to execute a simple SQL query (SELECT * FROM ...) via SPI_exec. As a a result, I get an SPITupleTable with the results of my query. Now that I have the SPITupleTable, I was wondering if it would be possible to later query over it further in my SQL statements using SPI, for example, something a bit similar to SPI_Exec ("Select * FROM :mySPITupleTable", 0); My motivation is to treat, and use the SPITupleTable as 'intermediate' or 'temporary' tables which I would discard early - I want to apply a series of manipulations to my SPITupleTable before I would finally store it in the tablespace. Therefore, minimization of any overheads is also very important. I understand that I could introduce a CREATE TABLE to my SQL query and reference a table in that way, but I am under the impression that it would incur unnecessary overheads? So, I would be grateful if anyone could help me understand how to manipulate the SPITupleTable further with SQL or indicate if it is at all possible. In the case that it is not possible, I would also be interested in alternatives and discussion on overheads. Thanks in advance. Best, Tom
Tom Mercha <mercha_t@hotmail.com> writes: > I am using PostgreSQL's SPI to execute a simple SQL query (SELECT * FROM > ...) via SPI_exec. As a a result, I get an SPITupleTable with the > results of my query. > Now that I have the SPITupleTable, I was wondering if it would be > possible to later query over it further in my SQL statements using SPI, > for example, something a bit similar to SPI_Exec ("Select * FROM > :mySPITupleTable", 0); It's possible you could use the "transition table" (aka EphemeralNamedRelation) infrastructure for this, though I'm not sure if it's really a close fit, or whether it's been built out enough to support this usage. From memory, it wants to work with tuplestores, which are a bit heavier-weight than SPITupleTables. regards, tom lane
On 02/10/2019 16:11, Tom Lane wrote: > Tom Mercha <mercha_t@hotmail.com> writes: >> I am using PostgreSQL's SPI to execute a simple SQL query (SELECT * FROM >> ...) via SPI_exec. As a a result, I get an SPITupleTable with the >> results of my query. >> Now that I have the SPITupleTable, I was wondering if it would be >> possible to later query over it further in my SQL statements using SPI, >> for example, something a bit similar to SPI_Exec ("Select * FROM >> :mySPITupleTable", 0); > > It's possible you could use the "transition table" (aka > EphemeralNamedRelation) infrastructure for this, though I'm not sure > if it's really a close fit, or whether it's been built out enough to > support this usage. From memory, it wants to work with tuplestores, > which are a bit heavier-weight than SPITupleTables. > > regards, tom lane > Thanks for this feedback! The EphemeralNamedRelation seems that it could be a good fit for what I'm looking for. However, I'm not quite so sure how I can query over the EphemeralNamedRelation using SQL? Could someone indicate where I can find an example? Regards Tom
On 10/2/19 2:53 PM, Tom Mercha wrote: > However, I'm not quite so sure how I can query over the > EphemeralNamedRelation using SQL? Could someone indicate where I can > find an example? You could look in the documentation for CREATE TRIGGER in PG 10 or later, specifically the clauses like REFERENCING NEW TABLE AS foo. https://www.postgresql.org/docs/10/sql-createtrigger.html While the trigger function is executing, it can do SPI SQL queries exactly as if there is a table named 'foo' sitting there, but it only "exists" for that function and only until it returns. Regards, -Chap
Hi, I have had see your discussion about node EphemeralNamedRelation with the Community. Now, I want to use this node in SQL(for test), I have saw the manual but could not understand, can you show me a example on how to use it in SQL? Thanks a lot~ Regards, wu fei -----Original Message----- From: Tom Mercha [mailto:mercha_t@hotmail.com] Sent: 2019年10月3日 2:53 To: Tom Lane <tgl@sss.pgh.pa.us> Cc: pgsql-hackers@postgresql.org Subject: Re: Is querying SPITupleTable with SQL possible? On 02/10/2019 16:11, Tom Lane wrote: > Tom Mercha <mercha_t@hotmail.com> writes: >> I am using PostgreSQL's SPI to execute a simple SQL query (SELECT * >> FROM >> ...) via SPI_exec. As a a result, I get an SPITupleTable with the >> results of my query. >> Now that I have the SPITupleTable, I was wondering if it would be >> possible to later query over it further in my SQL statements using >> SPI, for example, something a bit similar to SPI_Exec ("Select * FROM >> :mySPITupleTable", 0); > > It's possible you could use the "transition table" (aka > EphemeralNamedRelation) infrastructure for this, though I'm not sure > if it's really a close fit, or whether it's been built out enough to > support this usage. From memory, it wants to work with tuplestores, > which are a bit heavier-weight than SPITupleTables. > > regards, tom lane > Thanks for this feedback! The EphemeralNamedRelation seems that it could be a good fit for what I'm looking for. However, I'm not quite so sure how I can query over the EphemeralNamedRelation using SQL? Could someone indicate where Ican find an example? Regards Tom
[un-top-postifying] On Fri, Dec 20, 2019 at 2:53 PM Wu, Fei <wufei.fnst@cn.fujitsu.com> wrote: >> On 02/10/2019 16:11, Tom Lane wrote: >> > Tom Mercha <mercha_t@hotmail.com> writes: >> >> I am using PostgreSQL's SPI to execute a simple SQL query (SELECT * >> >> FROM >> >> ...) via SPI_exec. As a a result, I get an SPITupleTable with the >> >> results of my query. >> >> Now that I have the SPITupleTable, I was wondering if it would be >> >> possible to later query over it further in my SQL statements using >> >> SPI, for example, something a bit similar to SPI_Exec ("Select * FROM >> >> :mySPITupleTable", 0); >> > >> > It's possible you could use the "transition table" (aka >> > EphemeralNamedRelation) infrastructure for this, though I'm not sure >> > if it's really a close fit, or whether it's been built out enough to >> > support this usage. From memory, it wants to work with tuplestores, >> > which are a bit heavier-weight than SPITupleTables. >> >> Thanks for this feedback! The EphemeralNamedRelation seems that it could be a good fit for what I'm looking for. >> >> However, I'm not quite so sure how I can query over the EphemeralNamedRelation using SQL? Could someone indicate whereI can find an example? > > I have had see your discussion about node EphemeralNamedRelation with the Community. > Now, I want to use this node in SQL(for test), I have saw the manual but could not understand, > can you show me a example on how to use it in SQL? I missed this thread before. If you want to expose an ENR to SQL you'll need to write some C code for now (unless someone has added support for other languages?). Try something like this (not tested): EphemeralNamedRelation enr = palloc0(sizeof(*enr)); enr->md.name = "my_magic_table"; enr->md.reliddesc = InvalidOid; enr->md.tupdesc = my_magic_table_tuple_descriptor; enr->md.enrtype = ENR_NAMED_TUPLESTORE; enr->md.enrtuples = how_many_tuples_to_tell_the_planner_we_have; enr->reldata = my_tupestorestate; rc = SPI_register_relation(enr); if (rc != SPI_OK_REL_REGISTER) explode(); You will need to come up with a TupleDesc that describes the columns in your magic table, and a Tuplestorestate that holds the tuples. After that you should be able to plan and execute read-only SQL queries against that tuplestore using that name, via the usual SPI_xxx() interfaces. I'm not sure how you'd really do this though: you might need to make a function that takes a query as a string, then does the above setup in a new SPI connection, and then executes the query. This would probably be a lot more fun from a PL like Python. (If you wanted to create ENRs that are available to your top level connection, I haven't looked into it but I suspect that'd require more machinery than we have right now, and I'm not sure if it'd be a good idea.) In theory, there could be a new type ENR_SPI_TUPLE_TABLE that could work with SPITupleTable instead of Tuplestore. The idea was that we might be able to do more clever things like that in the future, which is why we tried to make it at least a little bit general. One thing that could be nice would be SQL Server style table variables; you could have a functions that receive them as parameters, return them, and be able to insert/update/delete. That's a bit far fetched, but gives some idea of the reason we invented QueryEnvironment and passed to all the right places in the planner and executor (or perhaps not enough yet, we do occasionally find places that we forgot to pass it...). So yeah, to use an SPITupleTable now you'd need to insert its contents into a Tuplestorestate. As mentioned, this is the mechanism that is used to support SQL standard "transition tables" in triggers. You can see that the function SPI_register_trigger_data() just does what I showed above to expose all the transition tables to your trigger's SQL statements. That part even works in Perl, Python, TCL triggers, but to make your own tables in higher level languages you'd need to expose more interfaces and figure out sane ways to get TupleDescriptor and interact with Tuplestore. If you want to see examples of SQL queries inside triggers that access transition tables, check out src/test/regress/expected/triggers.out and src/pl/plpython/expected/plpython_trigger.out.