Composite types as parameters

2021-06-26 Thread Elijah Stone

Hello all,

I am trying to add support for composite types to my ORM, which uses libpq 
and the binary format.


Given a schema like this one:

create type composite as (...);
create table sometable (field composite, ...);

I want to execute a query like this:

PQexecParams("insert into sometable values($1, ...);", paramValues[0] = 
serialize some record, ...)

However this fails in coerce_record_to_complex(), because it receives a 
node of type Param, but it can only handle RowExpr and Var.  There is a 
comment suggesting that this is not a fundamental limitation, but (not 
being familiar with postgres codebase) I'm not sure how to go about fixing 
it.  I assume there is a mapping somewhere from param ids to objects, but 
am unable to find it.


Does anyone have any pointers or suggestions?  Am I going about this in 
entirely the wrong way?


 -E




Re: seawasp failing, maybe in glibc allocator

2021-06-26 Thread Fabien COELHO




Seawasp should turn green on its next run.


It did!

--
Fabien.




Re: [PATCH] Make jsonapi usable from libpq

2021-06-26 Thread Daniel Gustafsson
> On 26 Jun 2021, at 02:36, Michael Paquier  wrote:

> The service file parsing is the only piece in libpq using StringInfoData.
> @Tom, @Daniel, you got involved in c0cb87f.  It looks like this piece about 
> the
> limitations with service file parsing needs a rework.  This code is new in 14,
> which means a new open item.


Reworking it at this point to use a pqexpbuffer would be too invasive for 14
IMO, so reverting this part seems like the best option, and then redo it with
a pqexpbuffer for 15.

--
Daniel Gustafsson   https://vmware.com/





Failover messages in Timeline History

2021-06-26 Thread Michael Banck
Hi,

if a failover (or probably a switchover, at least in the way Patroni
does it) occurs, the timeline history (e.g. via "patronictl history"[1])
seems to read "no recovery target specified". That's correct, of course,
from a PITR perspective, but for the (possibly more common?) promotion-
of-a-standby-due-to-failover/switchover case rather misleading.

I wonder whether it could be made more informative; like "no recovery
target or failover" or "(standby) promotion witout recovery target"?


Michael

[1]

root@pg1:~# patronictl -c /etc/patroni/13-main.yml history | head
++--+--+--+
| TL |  LSN | Reason   | Timestamp  
  |
++--+--+--+
|  1 | 83886296 | no recovery target specified | 
2021-06-18T20:04:11.645437+00:00 |
|  2 | 83886928 | no recovery target specified | 
2021-06-18T20:08:45.820304+00:00 |
|  3 | 83887384 | no recovery target specified | 
2021-06-19T05:57:50.431980+00:00 |
|  4 | 83887840 | no recovery target specified | 
2021-06-19T08:32:55.527975+00:00 |
|  5 | 84017040 | no recovery target specified | 
2021-06-19T12:05:40.495982+00:00 |
|  6 | 84019264 | no recovery target specified | 
2021-06-19T15:51:49.983987+00:00 |
|  7 | 84135720 | no recovery target specified | 
2021-06-20T03:46:22.775851+00:00 |

-- 
Michael Banck
Projektleiter / Senior Berater
Tel.: +49 2166 9901-171
Fax:  +49 2166 9901-100
Email: 
michael.ba...@credativ.de
credativ GmbH, HRB Mönchengladbach 12080
USt-ID-Nummer: DE204566209
Trompeterallee 108, 41189 Mönchengladbach
Geschäftsführung: Dr. Michael Meskes, Sascha Heuer

Unser Umgang mit personenbezogenen Daten unterliegt
folgenden Bestimmungen: 
https://www.credativ.de/datenschutz





Re: [HACKERS] WIP aPatch: Pgbench Serialization and deadlock errors

2021-06-26 Thread Fabien COELHO


Hello Yugo-san,


I'm wondering whether we could use "vars" instead of "variables" as a
struct field name and function parameter name, so that is is shorter and
more distinct from the type name "Variables". What do you think?


The struct "Variables" has a field named "vars" which is an array of
"Variable" type. I guess this is a reason why "variables" is used instead
of "vars" as a name of "Variables" type variable so that we could know
a variable's type is Variable or Variables.  Also, in order to refer to
the field, we would use

vars->vars[vars->nvars]

and there are nested "vars". Could this make a codereader confused?


Hmmm… Probably. Let's keep "variables" then.

--
Fabien.

Re: Doc chapter for Hash Indexes

2021-06-26 Thread Amit Kapila
On Fri, Jun 25, 2021 at 3:11 PM Simon Riggs
 wrote:
>
> On Fri, Jun 25, 2021 at 4:17 AM Amit Kapila  wrote:
> >
> > On Fri, Jun 25, 2021 at 1:29 AM Bruce Momjian  wrote:
> > >
> > > aOn Wed, Jun 23, 2021 at 12:56:51PM +0100, Simon Riggs wrote:
> > > > On Wed, Jun 23, 2021 at 5:12 AM Amit Kapila  
> > > > wrote:
> > > > >
> > > > > On Tue, Jun 22, 2021 at 2:31 PM Simon Riggs
> > > > >  wrote:
> > > > > >
> > > > > > I attach both clean and compare versions.
> > > > > >
> > > > >
> > > > > Do we want to hold this work for PG15 or commit in PG14 and backpatch
> > > > > it till v10 where we have made hash indexes crash-safe? I would vote
> > > > > for committing in PG14 and backpatch it till v10, however, I am fine
> > > > > if we want to commit just to PG14 or PG15.
> > > >
> > > > Backpatch makes sense to me, but since not everyone will be reading
> > > > this thread, I would look towards PG15 only first. We may yet pick up
> > > > additional corrections or additions before a backpatch, if that is
> > > > agreed.
> > >
> > > Yeah, I think backpatching makes sense.
> > >
> >
> > I checked and found that there are two commits (7c75ef5715 and
> > 22c5e73562) in the hash index code in PG-11 which might have impacted
> > what we write in the documentation. However, AFAICS, nothing proposed
> > in the patch would change due to those commits. Even, if we don't want
> > to back patch, is there any harm in committing this to PG-14?
>
> I've reviewed those commits and the related code, so I agree.
>

Do you agree to just commit this to PG-14 or to commit in PG-14 and
backpatch till PG-10?

> As a result, I've tweaked the wording around VACUUM slightly.
>

Thanks, the changes look good to me.

-- 
With Regards,
Amit Kapila.




Re: subscription/t/010_truncate.pl failure on desmoxytes in REL_13_STABLE

2021-06-26 Thread Amit Kapila
On Fri, Jun 25, 2021 at 8:16 PM Tom Lane  wrote:
>
> Amit Kapila  writes:
> > On Thu, Jun 24, 2021 at 11:25 PM Tom Lane  wrote:
> >> Checking the git history, this was fixed in f560209c6, which also
> >> included some other mostly-cosmetic cleanup.  I'm inclined to
> >> propose back-patching that whole commit, rather than allowing the
> >> code in exec_replication_command() to diverge in different branches.
> >> It looks like it applies cleanly as far back as v10.  Maybe something
> >> could be done for 9.6 as well, but since that branch is so close to
> >> EOL, I doubt it's worth spending extra effort on it.
>
> > +1.
>
> Done that way.
>

Thanks!

-- 
With Regards,
Amit Kapila.




Re: [HACKERS] WIP aPatch: Pgbench Serialization and deadlock errors

2021-06-26 Thread Fabien COELHO


Hello Yugo-san,

# About v12.2

## Compilation

Patch seems to apply cleanly with "git apply", but does not compile on my 
host: "undefined reference to `conditional_stack_reset'".


However it works better when using the "patch". I'm wondering why git 
apply fails silently…


When compiling there are warnings about "pg_log_fatal", which does not 
expect a FILE* on pgbench.c:4453. Remove the "stderr" argument.


Global and local checks ok.


number of transactions failed: 324 (3.240%)
...
number of transactions retried: 5629 (56.290%)
number of total retries: 103299


I'd suggest: "number of failed transactions". "total number of retries" or 
just "number of retries"?


## Feature

The overall code structure changes to implements the feature seems 
reasonable to me, as we are at the 12th iteration of the patch.


Comments below are somehow about details and asking questions
about choices, and commenting…

## Documentation

There is a lot of documentation, which is good. I'll review these
separatly. It looks good, but having a native English speaker/writer
would really help!

Some output examples do not correspond to actual output for
the current version. In particular, there is always one TPS figure
given now, instead of the confusing two shown before.

## Comments

transactinos -> transactions.

## Code

By default max_tries = 0. Should not the initialization be 1,
as the documentation argues that it is the default?

Counter comments, missing + in the formula on the skipped line.

Given that we manage errors, ISTM that we should not necessarily
stop on other not retried errors, but rather count/report them and
possibly proceed.  Eg with something like:

  -- server side random fail
  DO LANGUAGE plpgsql $$
  BEGIN
IF RANDOM() < 0.1 THEN
  RAISE EXCEPTION 'unlucky!';
END IF;
  END;
  $$;

Or:

  -- client side random fail
  BEGIN;
  \if random(1, 10) <= 1
  SELECT 1 +;
  \else
  SELECT 2;
  \endif
  COMMIT;

We could count the fail, rollback if necessary, and go on.  What do you think?
Maybe such behavior would deserve an option.

--report-latencies -> --report-per-command: should we keep supporting
the previous option?

--failures-detailed: if we bother to run with handling failures, should
it always be on?

--debug-errors: I'm not sure we should want a special debug mode for that,
I'd consider integrating it with the standard debug, or just for development.
Also, should it use pg_log_debug?

doRetry: I'd separate the 3 no retries options instead of mixing max_tries and
timer_exceeeded, for clarity.

Tries vs retries: I'm at odds with having tries & retries and + 1 here
and there to handle that, which is a little bit confusing. I'm wondering whether
we could only count "tries" and adjust to report what we want later?

advanceConnectionState: ISTM that ERROR should logically be before others which
lead to it.

Variables management: it looks expensive, with copying and freeing variable 
arrays.
I'm wondering whether we should think of something more clever. Well, that 
would be
for some other patch.

"Accumulate the retries" -> "Count (re)tries"?

Currently, ISTM that the retry on error mode is implicitely always on.
Do we want that? I'd say yes, but maybe people could disagree.

## Tests

There are tests, good!

I'm wondering whether something simpler could be devised to trigger
serialization or deadlock errors, eg with a SEQUENCE and an \if.

See the attached files for generating deadlocks reliably (start with 2 clients).
What do you think? The PL/pgSQL minimal, it is really client-code 
oriented.


Given that deadlocks are detected about every seconds, the test runs
would take some time. Let it be for now.

--
Fabien.

Re: Using each rel as both outer and inner for JOIN_ANTI

2021-06-26 Thread Richard Guo
On Thu, Jun 24, 2021 at 10:14 PM Tom Lane  wrote:

> Heikki Linnakangas  writes:
> > On 24/06/2021 12:50, Richard Guo wrote:
> >> I believe if we use the smaller table 'foo' as inner side for this
> >> query, we would have a cheaper plan.
>
> > How would that work?
>
> I think you could make it work for the hash-join case by extending
> the existing mechanism for right joins: emit nothing during the main
> scan, but mark hashtable entries when a match is found.  Then make
> a post-pass and emit hash entries that never found a match.  So
> basically just the inverse behavior of a right join, but with the
> same state info.
>
> Merge join could likely support "right anti join" too, though the
> benefit of swapping inputs tends to be small there, so it may not be
> worth doing.
>
> Obviously there's a pretty fair amount of code to write to make this
> happen.
>

Thanks for the explanation. Attached is a demo code for the hash-join
case, which is only for PoC to show how we can make it work. It's far
from complete, at least we need to adjust the cost calculation for this
'right anti join'.

Am I going in the right direction?

Thanks
Richard


0001-Using-each-rel-as-both-outer-and-inner-for-anti-join.patch
Description: Binary data


Re: Composite types as parameters

2021-06-26 Thread Tom Lane
Elijah Stone  writes:
> I want to execute a query like this:

> PQexecParams("insert into sometable values($1, ...);", paramValues[0] = 
> serialize some record, ...)

> However this fails in coerce_record_to_complex(), because it receives a 
> node of type Param, but it can only handle RowExpr and Var.

You probably would have better results from specifying the composite
type explicitly in the query:

PQexecParams("insert into sometable values($1::composite, ...);",

I gather from the complaint that you're currently doing something that
causes the Param to be typed as a generic "record", which is problematic
since the record's details are not available from anyplace.  But if you
cast it directly to a named composite type, that should work.

If it still doesn't work, please provide a more concrete example.

regards, tom lane




Re: PATCH: generate fractional cheapest paths in generate_orderedappend_path

2021-06-26 Thread Arne Roland
Hi Tomas,

I don't think there is much work left to do here.

Did you have a look at the test case? Did it make sense to you?

And I am sorry. I had another look at this and it seems I was confused (again).

From: Arne Roland
Sent: Monday, April 26, 2021 13:00
To: Tomas Vondra; pgsql-hackers
Subject: Re: PATCH: generate fractional cheapest paths in 
generate_orderedappend_path

> I think it should. We have a ParallelAppend node after all.
> I'm not really familiar with the way 
> get_cheapest_fractional_path_for_pathkeys is used, but a quick search 
> suggests to
> me, that build_minmax_path was thus far the only one using it. And minmax 
> paths are never parallel safe anyway. I think that is the reason it doesn't 
> do that already.

The whole segment were are talking about obviously assumes 
require_parallel_safe is not needed. I wasn't aware that in 
set_append_rel_size. And I just realized there is a great comment explaining 
why it rightfully does so:
 /*
 * If any live child is not parallel-safe, treat the whole appendrel
 * as not parallel-safe.  In future we might be able to generate plans
 * in which some children are farmed out to workers while others are
 * not; but we don't have that today, so it's a waste to consider
 * partial paths anywhere in the appendrel unless it's all safe.
 * (Child rels visited before this one will be unmarked in
 * set_append_rel_pathlist().)
 */
So afaik we don't need to think further about this.


From: Tomas Vondra 
Sent: Thursday, June 3, 2021 22:57
To: Zhihong Yu
Cc: Arne Roland; pgsql-hackers
Subject: Re: PATCH: generate fractional cheapest paths in 
generate_orderedappend_path
> Actually, there are two comments
>
>/* XXX maybe we should have startup_new_fractional? */
>
> in the patch I posted - I completely forgot about that. But I think
> that's a typo, I think - it should be
>
> /* XXX maybe we should have startup_neq_fractional? */
>
> and the new flag would work similarly to startup_neq_total, i.e. it's
> pointless to add paths where startup == fractional cost.
>
> At least I think that was the idea when I wrote the patch, it way too
> long ago.

> Sorry, I almost forgot about this myself. I only got reminded upon seeing 
> that again with different queries/tables.
> Just to be sure I get this correctly: You mean startup_gt_fractional (cost) 
> as an additional condition, right?

Could you clarify that for me?

Regards
Arne



Re: Rename of triggers for partitioned tables

2021-06-26 Thread Arne Roland
Hello Álvaro Herrera,

I am sorry to bother, but I am still annoyed by this. So I wonder if you had a 
look.

Regards
Arne




From: Arne Roland 
Sent: Friday, April 2, 2021 7:55:16 PM
To: Alvaro Herrera
Cc: David Steele; Pg Hackers
Subject: Re: Rename of triggers for partitioned tables


Hi,


attached a patch with some cleanup and a couple of test cases. The lookup is 
now done with the parentid and the renaming affects detached partitions as well.


The test cases are not perfectly concise, but only add about 0.4 % to the total 
runtime of regression tests at my machine. So I didn't bother to much. They 
only consist of basic sql tests.


Further feedback appreciated! Thank you!


Regards

Arne



From: Arne Roland 
Sent: Thursday, April 1, 2021 4:38:59 PM
To: Alvaro Herrera
Cc: David Steele; Pg Hackers
Subject: Re: Rename of triggers for partitioned tables

Alvaro Herrera wrote:
> I think the child cannot not have a corresponding trigger.  If you try
> to drop the trigger on child, it should say that it cannot be dropped
> because the trigger on parent requires it.  So I don't think there's any
> case where altering name of trigger in parent would raise an user-facing
> error.  If you can't find the trigger in child, that's a case of catalog
> corruption [...]

Ah, I didn't know that. That changes my reasoning about that. I only knew, that 
the alter table ... detach partition ... doesn't detach the child trigger from 
the partitioned trigger, but the the attach partition seem to add one. Maybe we 
should be able to make sure that there is a one to one correspondence for child 
triggers and child partitions.

Currently upon detaching we keep the trigger within the partitioned trigger of 
the parent relation. (So the trigger remains in place and can only be dropped 
with the parent one.) Only we try to attach the partition again any partitioned 
triggers are simply removed.

One idea would be to detach partitioned triggers there in a similar manner we 
detach partitioned indexes. That could give above guarantee. (At least if one 
would be willing to write a migration for that.) But then we can't tell anymore 
where the trigger stems from. That hence would break our attach/detach workflow.

I was annoyed by the inability to drop partitioned triggers from detached 
partitions, but it seems I just got a workaround. Ugh.

This is a bit of a sidetrack discussion, but it is related.

> Consider this.  You have table p and partition p1.  Add trigger t to p,
> and do
> ALTER TRIGGER t ON p1 RENAME TO q;

> What I'm saying is that if you later do
> ALTER TRIGGER t ON ONLY p RENAME TO r;
> then the trigger on parent is changed, and the trigger on child stays q.
> If you later do
> ALTER TRIGGER r ON p RENAME TO s;
> then triggers on both tables end up with name s.

If we get into the mindset of expecting one trigger on the child, we have the 
following edge case:

- The trigger is renamed. You seem to favor the silent rename in that case over 
raising a notice (or even an error). I am not convinced a notice wouldn't the 
better in that case.
- The trigger is outside of partitioned table. That still means that the 
trigger might still be in the inheritance tree, but likely isn't. Should we 
rename it anyways, or skip that? Should be raise a notice about what we are 
doing here? I think that would be helpful to the end user.

> Hmm, ok, maybe this is sufficient, I didn't actually test it.  I think
> you do need to add a few test cases to ensure everything is sane.  Make
> sure to verify what happens if you have multi-level partitioning
> (grandparent, parent, child) and you ALTER the one in the middle.  Also
> things like if parent has two children and one child has multiple
> children.

The test I had somewhere upwards this thread, already tested that.

I am not sure how to add a test for pg_dump though. Can you point me to the 
location in pg_regress for pg_dump?

> Also, please make sure that it works correctly with INHERITS (legacy
> inheritance).  We probably don't want to cause recursion in that case.

That works, but I will add a test to make sure it stays that way. Thank you for 
your input!

Regards
Arne


Re: Rename of triggers for partitioned tables

2021-06-26 Thread Alvaro Herrera
On 2021-Jun-26, Arne Roland wrote:

> Hello Álvaro Herrera,
> 
> I am sorry to bother, but I am still annoyed by this. So I wonder if you had 
> a look.

I'll have a look during the commitfest which starts late next week.

(However, I'm fairly sure that it won't be in released versions ...
it'll only be fixed in the version to be released next year, postgres
15.  Things that are clear bug fixes can be applied
in released versions, but this patch probably changes behavior in ways
that are not acceptable in released versions.  Sorry about that.)

-- 
Álvaro Herrera39°49'30"S 73°17'W
Al principio era UNIX, y UNIX habló y dijo: "Hello world\n".
No dijo "Hello New Jersey\n", ni "Hello USA\n".




Re: Rename of triggers for partitioned tables

2021-06-26 Thread Arne Roland
From: Alvaro Herrera 
Sent: Saturday, June 26, 2021 18:36
Subject: Re: Rename of triggers for partitioned tables

> I'll have a look during the commitfest which starts late next week.

Thank you!

> (However, I'm fairly sure that it won't be in released versions ...
> it'll only be fixed in the version to be released next year, postgres
> 15.  Things that are clear bug fixes can be applied
> in released versions, but this patch probably changes behavior in ways
> that are not acceptable in released versions.  Sorry about that.)

I never expected any backports. Albeit I don't know anyone, who would mind, I 
agree with you on that assessment. This is very annoying, but not really 
breaking the product.

Sure, I was hoping for pg14 initially. But I will survive another year of gexec.
I am grateful you agreed to have a look!

Regards
Arne



Re: [PATCH] Make jsonapi usable from libpq

2021-06-26 Thread Tom Lane
Michael Paquier  writes:
> On Fri, Jun 25, 2021 at 08:58:46PM +, Jacob Champion wrote:
>> That surprised me. So there's currently no compiler-enforced
>> prohibition, just a policy? It looks like the bar was lowered a little
>> bit in commit c0cb87fbb6, as libpq currently has a symbol dependency on
>> pg_get_line_buf() and pfree() on my machine.

> Good point.  That's worse than just pfree() which is just a plain call
> to free() in the frontend.  We could have more policies here, but my
> take is that we'd better move fe_memutils.o to OBJS_FRONTEND in
> src/common/Makefile so as shared libraries don't use those routines in
> the long term.

Ugh.  Not only is that bad, but your proposed fix doesn't fix it.
At least in psql, and probably in most/all of our other clients,
removing fe_memutils.o from libpq's link just causes it to start
relying on the copy in the psql executable :-(.  So I agree that
some sort of mechanical enforcement would be a really good thing,
but I'm not sure what it would look like.

> In parseServiceFile(), initStringInfo() does a palloc() which would
> simply exit() on OOM, in libpq.  That's not good.  The service file
> parsing is the only piece in libpq using StringInfoData.  @Tom,
> @Daniel, you got involved in c0cb87f.

I concur with Daniel that the easiest fix for v14 is to revert
c0cb87f.  Allowing unlimited-length lines in the service file seems
like a nice-to-have, but it's not worth a lot.  (Looking at the patch,
I'm inclined to keep much of the code rearrangement, just remove the
dependency on stringinfo.c.  Also I'm tempted to set the fixed buffer
size at 1024 not 256, after which we might never need to improve it.)

I spent some time looking for other undesirable symbol dependencies
in libpq, and soon found a couple.  PGTHREAD_ERROR potentially calls
abort(), which seems even worse than exit-on-OOM, although I don't
think we've ever heard a report of that being hit.  Also,
fe-print.c's handling of OOM isn't nice at all:

fprintf(stderr, libpq_gettext("out of memory\n"));
abort();

Although fe-print.c is semi-deprecated, it still seems like it'd
be a good idea to clean that up.

BTW, so far as the original topic of this thread is concerned,
it sounds like Jacob's ultimate goal is to put some functionality
into libpq that requires JSON parsing.  I'm going to say up front
that that sounds like a terrible idea.  As we've just seen, libpq
operates under very tight constraints, not all of which are
mechanically enforced.  I am really doubtful that anything that
would require a JSON parser has any business being in libpq.
Unless you can sell us on that point, I do not think it's worth
complicating the src/common JSON code to the point where it can
work under libpq's constraints.

regards, tom lane




Re: Rename of triggers for partitioned tables

2021-06-26 Thread Zhihong Yu
On Sat, Jun 26, 2021 at 10:08 AM Arne Roland  wrote:

> *From:* Alvaro Herrera 
> *Sent:* Saturday, June 26, 2021 18:36
> *Subject:* Re: Rename of triggers for partitioned tables
>
> > I'll have a look during the commitfest which starts late next week.
>
> Thank you!
>
> > (However, I'm fairly sure that it won't be in released versions ...
> > it'll only be fixed in the version to be released next year, postgres
> > 15.  Things that are clear bug fixes can be applied
> > in released versions, but this patch probably changes behavior in ways
> > that are not acceptable in released versions.  Sorry about that.)
>
> I never expected any backports. Albeit I don't know anyone, who would
> mind, I agree with you on that assessment. This is very annoying, but not
> really breaking the product.
>
> Sure, I was hoping for pg14 initially. But I will survive another year of
> gexec.
> I am grateful you agreed to have a look!
>
> Regards
> Arne
>
> Hi, Arne:
It seems the patch no longer applies cleanly on master branch.
Do you mind updating the patch ?

Thanks

1 out of 7 hunks FAILED -- saving rejects to file
src/backend/commands/trigger.c.rej
patching file src/backend/parser/gram.y
Hunk #1 succeeded at 8886 (offset 35 lines).
patching file src/backend/utils/adt/ri_triggers.c
Reversed (or previously applied) patch detected!  Assume -R? [n]
Apply anyway? [n]
Skipping patch.
1 out of 1 hunk ignored -- saving rejects to file
src/backend/utils/adt/ri_triggers.c.rej


Re: [PATCH] Make jsonapi usable from libpq

2021-06-26 Thread Tom Lane
I wrote:
> I spent some time looking for other undesirable symbol dependencies
> in libpq, and soon found a couple.  PGTHREAD_ERROR potentially calls
> abort(), which seems even worse than exit-on-OOM, although I don't
> think we've ever heard a report of that being hit.  Also,
> fe-print.c's handling of OOM isn't nice at all:
> fprintf(stderr, libpq_gettext("out of memory\n"));
> abort();
> Although fe-print.c is semi-deprecated, it still seems like it'd
> be a good idea to clean that up.

fe-print.c seems easy enough to clean up, as per attached.
Not real sure what to do about PGTHREAD_ERROR.

regards, tom lane

diff --git a/src/interfaces/libpq/fe-print.c b/src/interfaces/libpq/fe-print.c
index fc7d84844e..0831950b12 100644
--- a/src/interfaces/libpq/fe-print.c
+++ b/src/interfaces/libpq/fe-print.c
@@ -37,7 +37,7 @@
 #include "libpq-int.h"
 
 
-static void do_field(const PQprintOpt *po, const PGresult *res,
+static bool do_field(const PQprintOpt *po, const PGresult *res,
 	 const int i, const int j, const int fs_len,
 	 char **fields,
 	 const int nFields, const char **fieldNames,
@@ -80,12 +80,12 @@ PQprint(FILE *fout, const PGresult *res, const PQprintOpt *po)
 		unsigned char *fieldNotNum = NULL;
 		char	   *border = NULL;
 		char	  **fields = NULL;
-		const char **fieldNames;
+		const char **fieldNames = NULL;
 		int			fieldMaxLen = 0;
 		int			numFieldName;
 		int			fs_len = strlen(po->fieldSep);
 		int			total_line_length = 0;
-		int			usePipe = 0;
+		bool		usePipe = false;
 		char	   *pagerenv;
 
 #if defined(ENABLE_THREAD_SAFETY) && !defined(WIN32)
@@ -111,17 +111,17 @@ PQprint(FILE *fout, const PGresult *res, const PQprintOpt *po)
 		if (!(fieldNames = (const char **) calloc(nFields, sizeof(char *
 		{
 			fprintf(stderr, libpq_gettext("out of memory\n"));
-			abort();
+			goto exit;
 		}
 		if (!(fieldNotNum = (unsigned char *) calloc(nFields, 1)))
 		{
 			fprintf(stderr, libpq_gettext("out of memory\n"));
-			abort();
+			goto exit;
 		}
 		if (!(fieldMax = (int *) calloc(nFields, sizeof(int
 		{
 			fprintf(stderr, libpq_gettext("out of memory\n"));
-			abort();
+			goto exit;
 		}
 		for (numFieldName = 0;
 			 po->fieldName && po->fieldName[numFieldName];
@@ -190,7 +190,7 @@ PQprint(FILE *fout, const PGresult *res, const PQprintOpt *po)
 fout = popen(pagerenv, "w");
 if (fout)
 {
-	usePipe = 1;
+	usePipe = true;
 #ifndef WIN32
 #ifdef ENABLE_THREAD_SAFETY
 	if (pq_block_sigpipe(&osigset, &sigpipe_pending) == 0)
@@ -207,10 +207,11 @@ PQprint(FILE *fout, const PGresult *res, const PQprintOpt *po)
 
 		if (!po->expanded && (po->align || po->html3))
 		{
-			if (!(fields = (char **) calloc(nFields * (nTups + 1), sizeof(char *
+			if (!(fields = (char **) calloc((size_t) nTups + 1,
+			nFields * sizeof(char *
 			{
 fprintf(stderr, libpq_gettext("out of memory\n"));
-abort();
+goto exit;
 			}
 		}
 		else if (po->header && !po->html3)
@@ -264,9 +265,12 @@ PQprint(FILE *fout, const PGresult *res, const PQprintOpt *po)
 	fprintf(fout, libpq_gettext("-- RECORD %d --\n"), i);
 			}
 			for (j = 0; j < nFields; j++)
-do_field(po, res, i, j, fs_len, fields, nFields,
-		 fieldNames, fieldNotNum,
-		 fieldMax, fieldMaxLen, fout);
+			{
+if (!do_field(po, res, i, j, fs_len, fields, nFields,
+			  fieldNames, fieldNotNum,
+			  fieldMax, fieldMaxLen, fout))
+	goto exit;
+			}
 			if (po->html3 && po->expanded)
 fputs("\n", fout);
 		}
@@ -297,18 +301,34 @@ PQprint(FILE *fout, const PGresult *res, const PQprintOpt *po)
 			for (i = 0; i < nTups; i++)
 output_row(fout, po, nFields, fields,
 		   fieldNotNum, fieldMax, border, i);
-			free(fields);
-			if (border)
-free(border);
 		}
 		if (po->header && !po->html3)
 			fprintf(fout, "(%d row%s)\n\n", PQntuples(res),
 	(PQntuples(res) == 1) ? "" : "s");
 		if (po->html3 && !po->expanded)
 			fputs("\n", fout);
-		free(fieldMax);
-		free(fieldNotNum);
-		free((void *) fieldNames);
+
+exit:
+		if (fieldMax)
+			free(fieldMax);
+		if (fieldNotNum)
+			free(fieldNotNum);
+		if (border)
+			free(border);
+		if (fields)
+		{
+			/* if calloc succeeded, this shouldn't overflow size_t */
+			size_t		numfields = ((size_t) nTups + 1) * (size_t) nFields;
+
+			while (numfields-- > 0)
+			{
+if (fields[numfields])
+	free(fields[numfields]);
+			}
+			free(fields);
+		}
+		if (fieldNames)
+			free((void *) fieldNames);
 		if (usePipe)
 		{
 #ifdef WIN32
@@ -329,7 +349,7 @@ PQprint(FILE *fout, const PGresult *res, const PQprintOpt *po)
 }
 
 
-static void
+static bool
 do_field(const PQprintOpt *po, const PGresult *res,
 		 const int i, const int j, const int fs_len,
 		 char **fields,
@@ -397,7 +417,7 @@ do_field(const PQprintOpt *po, const PGresult *res,
 			if (!(fields[i * nFields + j] = (char *) malloc(plen + 1)))
 			{
 fprintf(stderr, libpq_gettext("out of memory\n"));
-			

Preventing abort() and exit() calls in libpq

2021-06-26 Thread Tom Lane
[ starting a new thread so as not to confuse the cfbot ]

I wrote:
> Michael Paquier  writes:
>> Good point.  That's worse than just pfree() which is just a plain call
>> to free() in the frontend.  We could have more policies here, but my
>> take is that we'd better move fe_memutils.o to OBJS_FRONTEND in
>> src/common/Makefile so as shared libraries don't use those routines in
>> the long term.

> Ugh.  Not only is that bad, but your proposed fix doesn't fix it.
> At least in psql, and probably in most/all of our other clients,
> removing fe_memutils.o from libpq's link just causes it to start
> relying on the copy in the psql executable :-(.  So I agree that
> some sort of mechanical enforcement would be a really good thing,
> but I'm not sure what it would look like.

After some thought I propose that what we really want is to prevent
any calls of abort() or exit() from inside libpq.  Attached is a
draft patch to do that.  This can't be committed as-is, because
we still have some abort() calls in there in HEAD, but if we could
get that cleaned up it'd work.  Alternatively we could just disallow
exit(), which'd be enough to catch the problematic src/common files.

This relies on "nm" being able to work on shlibs, which it's not
required to by POSIX.  However, it seems to behave as desired even
on my oldest dinosaurs.  In any case, if "nm" doesn't work then
we'll just not detect such problems on that platform, which should
be OK as long as the test does work on common platforms.
Other than that point I think it's relying only on POSIX-spec
features.

I'll stick this into the CF list to see if the cfbot agrees that
it finds the abort() problems...

regards, tom lane

diff --git a/src/interfaces/libpq/Makefile b/src/interfaces/libpq/Makefile
index 0c4e55b6ad..3d992fdc78 100644
--- a/src/interfaces/libpq/Makefile
+++ b/src/interfaces/libpq/Makefile
@@ -96,12 +96,18 @@ SHLIB_EXPORTS = exports.txt
 
 PKG_CONFIG_REQUIRES_PRIVATE = libssl libcrypto
 
-all: all-lib
+all: all-lib check-libpq-refs
 
 # Shared library stuff
 include $(top_srcdir)/src/Makefile.shlib
 backend_src = $(top_srcdir)/src/backend
 
+# Check for functions that libpq must not call.
+# (If nm doesn't exist or doesn't work on shlibs, this test will silently
+# do nothing, which is fine.)
+.PHONY: check-libpq-refs
+check-libpq-refs: $(shlib)
+	@! nm -A -g -u $< 2>/dev/null | grep -e abort -e exit
 
 # Make dependencies on pg_config_paths.h visible in all builds.
 fe-connect.o: fe-connect.c $(top_builddir)/src/port/pg_config_paths.h


Re: Pipeline mode and PQpipelineSync()

2021-06-26 Thread Alvaro Herrera
It hadn't occurred to me that I should ask the release management team
about adding a new function to libpq this late in the cycle.

Please do note that the message type used in the new routine is currenly
unused and uncovered -- see line 4660 here:

https://coverage.postgresql.org/src/backend/tcop/postgres.c.gcov.html


-- 
Álvaro Herrera   Valdivia, Chile
"I'm impressed how quickly you are fixing this obscure issue. I came from 
MS SQL and it would be hard for me to put into words how much of a better job
you all are doing on [PostgreSQL]."
 Steve Midgley, http://archives.postgresql.org/pgsql-sql/2008-08/msg0.php




Re: [PATCH] Make jsonapi usable from libpq

2021-06-26 Thread Tom Lane
I wrote:
> Not real sure what to do about PGTHREAD_ERROR.

I wonder if we shouldn't simply nuke that macro and change the
call sites into "Assert(false)".  The only call sites are in
default_threadlock() (used in fe_auth.c) and pq_lockingcallback()
(for OpenSSL).  I suggest that

1. "fprintf(stderr)" in these locking functions doesn't seem
remarkably well-advised either.  Especially not on Windows;
but in general, we don't expect libpq to emit stuff on stderr
except under *very* limited circumstances.

2. In an assert-enabled build, Assert() ought to be about equivalent
to abort().

3. In a production build, if one of these mutex calls fails, ignoring
the failure might be the best thing to do anyway.  Certainly, dumping
core is the worst possible outcome, while not doing anything would
have no impact except in the rather-unlikely case that multiple libpq
connections try to use this code concurrently.

It's certainly possible to quibble about point 3, but unless you
have a better alternative to offer, I don't think you have a lot
of room to complain.

regards, tom lane




Re: Different compression methods for FPI

2021-06-26 Thread Justin Pryzby
On Tue, Jun 22, 2021 at 12:53:46PM +0900, Michael Paquier wrote:
> > So the patches that you say are unrelated still seem to me to be a
> > prerequisite .
> 
> I may be missing something, of course, but I still don't see why
> that's necessary?  We don't get any test failures on HEAD by switching
> wal_compression to on, no?  That's easy enough to test with a two-line
> change that changes the default.

Curious.  I found that before a4d75c86bf, there was an issue without the
"extra" patches.

|commit a4d75c86bf15220df22de0a92c819ecef9db3849
|Author: Tomas Vondra 
|Date:   Fri Mar 26 23:22:01 2021 +0100
|
|Extended statistics on expressions

I have no idea why that patch changes the behavior, but before a4d7, this patch
series failed like:

|$ time time make -C src/test/recovery check
...
|#   Failed test 'new xid after restart is greater'
|#   at t/011_crash_recovery.pl line 53.
|# '539'
|# >
|# '539'
|
|#   Failed test 'xid is aborted after crash'
|#   at t/011_crash_recovery.pl line 57.
|#  got: 'committed'
|# expected: 'aborted'
|# Looks like you failed 2 tests of 3.
|t/011_crash_recovery.pl .. Dubious, test returned 2 (wstat 512, 
0x200)
|Failed 2/3 subtests 

I checked that my most recent WAL compression patch applied on top of
a4d75c86bf works ok without the "extra" patches but fails when applied to
a4d75c86bf~1.

I think Andrey has been saying that since this already fails with PGLZ wal
compression, we could consider this to be a pre-existing problem.  I'm not
thrilled with that interpretation, but it's not wrong.

-- 
Justin




Re: unnesting multirange data types

2021-06-26 Thread Alexander Korotkov
On Mon, Jun 21, 2021 at 1:24 AM Alexander Korotkov  wrote:
> On Sun, Jun 20, 2021 at 11:09 AM Noah Misch  wrote:
> > On Sat, Jun 19, 2021 at 10:05:09PM -0400, Tom Lane wrote:
> > > Alexander Korotkov  writes:
> > > > I also don't feel comfortable hurrying with unnest part to beta2.
> > > > According to the open items wiki page, there should be beta3.  Does
> > > > unnest part have a chance for beta3?
> > >
> > > Hm.  I'd prefer to avoid another forced initdb after beta2.  On the
> > > other hand, it's entirely likely that there will be some other thing
> > > that forces that; in which case there'd be no reason not to push in
> > > the unnest feature as well.
> > >
> > > I'd say let's sit on the unnest code for a little bit and see what
> > > happens.
> >
> > I think $SUBJECT can't simultaneously offer too little to justify its own
> > catversion bump and also offer enough to bypass feature freeze.  If 
> > multirange
> > is good without $SUBJECT, then $SUBJECT should wait for v15.  Otherwise, the
> > matter of the catversion bump should not delay commit of $SUBJECT.
>
> FWIW, there is a patch implementing just unnest() function.

BTW, I found some small inconsistencies in the declaration of
multirange operators in the system catalog.  Nothing critical, but if
we decide to bump catversion in beta3, this patch is also nice to
push.

--
Regards,
Alexander Korotkov


0002-Fix-small-inconsistencies-in-catalog-definition-of--.patch
Description: Binary data


Re: Pipeline mode and PQpipelineSync()

2021-06-26 Thread Michael Paquier
On Sat, Jun 26, 2021 at 05:40:15PM -0400, Alvaro Herrera wrote:
> It hadn't occurred to me that I should ask the release management team
> about adding a new function to libpq this late in the cycle.

I have not followed the thread in details, but if you think that this
improves the feature in the long term even for 14, I have no
personally no objections to the addition of a new function, or even a 
change of behavior in one of the existing functions.  The beta cycle
is here for such adjustments.
--
Michael


signature.asc
Description: PGP signature


Re: [PATCH] Make jsonapi usable from libpq

2021-06-26 Thread Michael Paquier
On Sat, Jun 26, 2021 at 01:43:50PM -0400, Tom Lane wrote:
> BTW, so far as the original topic of this thread is concerned,
> it sounds like Jacob's ultimate goal is to put some functionality
> into libpq that requires JSON parsing.  I'm going to say up front
> that that sounds like a terrible idea.  As we've just seen, libpq
> operates under very tight constraints, not all of which are
> mechanically enforced.  I am really doubtful that anything that
> would require a JSON parser has any business being in libpq.
> Unless you can sell us on that point, I do not think it's worth
> complicating the src/common JSON code to the point where it can
> work under libpq's constraints.

AFAIK, the SASL mechanism OAUTHBEARER described in RFC 7628 would
require such facilities as failures are reported in this format:
https://datatracker.ietf.org/doc/html/rfc7628

Perhaps you are right and we have no need to do any json parsing in
libpq as long as we pass down the JSON blob, but I am not completely
sure if we can avoid that either.

Separate topic: I find disturbing the dependency of jsonapi.c to
the logging parts just to cope with dummy error values that are
originally part of JsonParseErrorType.
--
Michael


signature.asc
Description: PGP signature


Re: Composite types as parameters

2021-06-26 Thread Elijah Stone

On Sat, 26 Jun 2021, Tom Lane wrote:
You probably would have better results from specifying the composite 
type explicitly in the query:


PQexecParams("insert into sometable values($1::composite, ...);",

I gather from the complaint that you're currently doing something that 
causes the Param to be typed as a generic "record", which is problematic 
since the record's details are not available from anyplace.  But if you 
cast it directly to a named composite type, that should work.


If it still doesn't work, please provide a more concrete example.


Thanks, unfortunately adding the explicit cast doesn't help.  I've 
attached a minimal runnable example.


I am serializing as a generic record, so it occurs to me that another 
solution would be to use the actual type of the composite in question. 
(Though it also seems to me that my code should work as-is.)  Is there a 
way to discover the OID of a composite type?  And is the wire format the 
same as for a generic record?


 -E#include 
#include 
#include 
#include 

#define check(r) do { \
PGresult *res = r; \
if (PQresultStatus(res) == PGRES_NONFATAL_ERROR \
|| PQresultStatus(res) == PGRES_FATAL_ERROR) { \
puts(PQresultErrorMessage(res)); \
} \
} while (0)

int main() {
PGconn *c = PQconnectStart("postgresql://test:test@localhost/test"); 
assert(c);
for (int tries = 0; PQconnectPoll(c) != CONNECTION_MADE && tries < 10; 
tries++)
usleep(10);
assert(PQconnectPoll(c) == CONNECTION_MADE);
check(PQexec(c, "CREATE TYPE some_record AS (x int);"));
check(PQexec(c, "CREATE TABLE tab (rec some_record, bar int);"));

// ok:
check(PQexec(c, "INSERT INTO tab VALUES(ROW(7), 8);"));

char recbuf[4096], *rec = recbuf;
*(int*)rec = __builtin_bswap32(1), rec += 4; //# elements
*(int*)rec = __builtin_bswap32(INT4OID), rec += 4;
*(int*)rec = __builtin_bswap32(4), rec += 4; //n bytes in entry
*(int*)rec = __builtin_bswap32(7), rec += 4;

// error:
check(PQexecParams(c, "INSERT INTO tab VALUES($1, 8);",
1, &(Oid){RECORDOID}, &(const char*){recbuf},
&(int){rec - recbuf}, &(int){1/*binary*/},
1/*binary result*/));

// error as well:
check(PQexecParams(c, "INSERT INTO tab VALUES($1::some_record, 8);",
1, &(Oid){RECORDOID}, &(const char*){recbuf},
&(int){rec - recbuf}, &(int){1},
1));

PQfinish(c);
}


Re: [HACKERS] Preserving param location

2021-06-26 Thread Julien Rouhaud
On Sat, Mar 11, 2017 at 11:09:32PM +0100, Julien Rouhaud wrote:
> 
> When a query contains parameters, the original param node contains the token
> location.  However, this information is lost when the Const node is generated,
> this one will only contain position -1 (unknown).
>
> FWIW, we do have a use case for this (custom extension that tracks quals
> statistics, which among other thing is used to regenerate query string from a
> pgss normalized query, thus needing the original param location).

rebased v2.




Re: [HACKERS] Preserving param location

2021-06-26 Thread Julien Rouhaud
On Sun, Jun 27, 2021 at 11:31:53AM +0800, Julien Rouhaud wrote:
> On Sat, Mar 11, 2017 at 11:09:32PM +0100, Julien Rouhaud wrote:
> > 
> > When a query contains parameters, the original param node contains the token
> > location.  However, this information is lost when the Const node is 
> > generated,
> > this one will only contain position -1 (unknown).
> >
> > FWIW, we do have a use case for this (custom extension that tracks quals
> > statistics, which among other thing is used to regenerate query string from 
> > a
> > pgss normalized query, thus needing the original param location).
> 
> rebased v2.

This time with the patch.
>From 5c4831437e5b832d73dbab827d7f5e737bd1dfae Mon Sep 17 00:00:00 2001
From: Julien Rouhaud 
Date: Sat, 11 Mar 2017 22:48:00 +0100
Subject: [PATCH v2] Preserve param location when generating a const node.

Discussion: https://postgr.es/m/20170311220932.GJ15188@nol.local
---
 src/backend/optimizer/util/clauses.c | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index 059fa70254..084560acd8 100644
--- a/src/backend/optimizer/util/clauses.c
+++ b/src/backend/optimizer/util/clauses.c
@@ -2285,6 +2285,7 @@ eval_const_expressions_mutator(Node *node,
 			int16		typLen;
 			bool		typByVal;
 			Datum		pval;
+			Const	   *con;
 
 			get_typlenbyval(param->paramtype,
 			&typLen, &typByVal);
@@ -2292,13 +2293,17 @@ eval_const_expressions_mutator(Node *node,
 pval = prm->value;
 			else
 pval = datumCopy(prm->value, typByVal, typLen);
-			return (Node *) makeConst(param->paramtype,
+
+			con = makeConst(param->paramtype,
 	  param->paramtypmod,
 	  param->paramcollid,
 	  (int) typLen,
 	  pval,
 	  prm->isnull,
 	  typByVal);
+			con->location = param->location;
+
+			return (Node *) con;
 		}
 	}
 }
-- 
2.31.1



Deparsing rewritten query

2021-06-26 Thread Julien Rouhaud
Hi,

I sometimes have to deal with queries referencing multiple and/or complex
views.  In such cases, it's quite troublesome to figure out what is the query
really executed.  Debug_print_rewritten isn't really useful for non trivial
queries, and manually doing the view expansion isn't great either.

While not being ideal, I wouldn't mind using a custom extension for that but
this isn't an option as get_query_def() is private and isn't likely to change.

As an alternative, maybe we could expose a simple SRF that would take care of
rewriting the query and deparsing the resulting query tree(s)?

I'm attaching a POC patch for that, adding a new pg_get_query_def(text) SRF.

Usage example:

SELECT pg_get_query_def('SELECT * FROM shoe') as def;
  def

  SELECT shoename, +
 sh_avail, +
 slcolor,  +
 slminlen, +
 slminlen_cm,  +
 slmaxlen, +
 slmaxlen_cm,  +
 slunit+
FROM ( SELECT sh.shoename, +
 sh.sh_avail,  +
 sh.slcolor,   +
 sh.slminlen,  +
 (sh.slminlen * un.un_fact) AS slminlen_cm,+
 sh.slmaxlen,  +
 (sh.slmaxlen * un.un_fact) AS slmaxlen_cm,+
 sh.slunit +
FROM shoe_data sh, +
 unit un   +
   WHERE (sh.slunit = un.un_name)) shoe;   +

(1 row)
>From 5e726861fff28a276bb2e31972b278b833968ff4 Mon Sep 17 00:00:00 2001
From: Julien Rouhaud 
Date: Sun, 27 Jun 2021 11:39:47 +0800
Subject: [PATCH v1] Add pg_get_query_def() to deparse and print a rewritten
 SQL statement.

---
 src/backend/rewrite/rewriteHandler.c |  2 +
 src/backend/utils/adt/ruleutils.c| 70 
 src/include/catalog/pg_proc.dat  |  3 ++
 src/test/regress/expected/rules.out  | 26 +++
 src/test/regress/sql/rules.sql   |  3 ++
 5 files changed, 104 insertions(+)

diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c
index 88a9e95e33..f01b4531bf 100644
--- a/src/backend/rewrite/rewriteHandler.c
+++ b/src/backend/rewrite/rewriteHandler.c
@@ -1815,6 +1815,8 @@ ApplyRetrieveRule(Query *parsetree,
 	rte->rtekind = RTE_SUBQUERY;
 	rte->subquery = rule_action;
 	rte->security_barrier = RelationIsSecurityView(relation);
+	if (!rte->alias)
+		rte->alias = makeAlias(get_rel_name(rte->relid), NULL);
 	/* Clear fields that should not be set in a subquery RTE */
 	rte->relid = InvalidOid;
 	rte->relkind = 0;
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index 3719755a0d..cd39f4ce75 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -49,6 +49,8 @@
 #include "nodes/nodeFuncs.h"
 #include "nodes/pathnodes.h"
 #include "optimizer/optimizer.h"
+#include "parser/analyze.h"
+#include "parser/parse_node.h"
 #include "parser/parse_agg.h"
 #include "parser/parse_func.h"
 #include "parser/parse_node.h"
@@ -58,6 +60,7 @@
 #include "rewrite/rewriteHandler.h"
 #include "rewrite/rewriteManip.h"
 #include "rewrite/rewriteSupport.h"
+#include "tcop/tcopprot.h"
 #include "utils/array.h"
 #include "utils/builtins.h"
 #include "utils/fmgroids.h"
@@ -489,6 +492,73 @@ static void get_reloptions(StringInfo buf, Datum reloptions);
 
 #define only_marker(rte)  ((rte)->inh ? "" : "ONLY ")
 
+/* return the query as postgres will rewrite */
+Datum
+pg_get_query_def(PG_FUNCTION_ARGS)
+{
+	char	   *sql = TextDatumGetCString(PG_GETARG_TEXT_PP(0));
+	List	   *parsetree_list;
+	List	   *querytree_list;
+	RawStmt	   *parsetree;
+	Query	*query;
+	bool		snapshot_set = false;
+	StringInfoData	buf;
+	StringInfoData	res;
+	ListCell   *lc;
+
+	if (strcmp(sql, "") == 0)
+		ereport(ERROR,
+(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("empty statement now allowed")));
+
+	parsetree_list = pg_parse_query(sql);
+
+	/* only support one statement at a time */
+	if (list_length(parsetree_list) != 1)
+		ereport(ERROR,
+(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("a single statement should be provided")));
+
+	initStringInfo(&res);
+
+	parsetree = linitial_node(RawStmt, parsetree_list);
+
+	/*
+	 * Set up a snapshot if parse analysis/planning will need one.
+	 */
+	if (analyze_requires_snapshot(parsetree))
+	{
+		PushActiveSnapshot(GetTransactionSnapshot());
+		snapshot_set = true;
+	}
+
+	querytree_list = pg_analyze_and_rewrite(parsetree, sql,
+			NULL, 0, NULL);
+
+	/* Don

Re: Deparsing rewritten query

2021-06-26 Thread Pavel Stehule
ne 27. 6. 2021 v 6:11 odesílatel Julien Rouhaud  napsal:

> Hi,
>
> I sometimes have to deal with queries referencing multiple and/or complex
> views.  In such cases, it's quite troublesome to figure out what is the
> query
> really executed.  Debug_print_rewritten isn't really useful for non trivial
> queries, and manually doing the view expansion isn't great either.
>
> While not being ideal, I wouldn't mind using a custom extension for that
> but
> this isn't an option as get_query_def() is private and isn't likely to
> change.
>
> As an alternative, maybe we could expose a simple SRF that would take care
> of
> rewriting the query and deparsing the resulting query tree(s)?
>
> I'm attaching a POC patch for that, adding a new pg_get_query_def(text)
> SRF.
>
> Usage example:
>
> SELECT pg_get_query_def('SELECT * FROM shoe') as def;
>   def
> 
>   SELECT shoename, +
>  sh_avail, +
>  slcolor,  +
>  slminlen, +
>  slminlen_cm,  +
>  slmaxlen, +
>  slmaxlen_cm,  +
>  slunit+
> FROM ( SELECT sh.shoename, +
>  sh.sh_avail,  +
>  sh.slcolor,   +
>  sh.slminlen,  +
>  (sh.slminlen * un.un_fact) AS slminlen_cm,+
>  sh.slmaxlen,  +
>  (sh.slmaxlen * un.un_fact) AS slmaxlen_cm,+
>  sh.slunit +
> FROM shoe_data sh, +
>  unit un   +
>WHERE (sh.slunit = un.un_name)) shoe;   +
>
> (1 row)
>

+1

Pavel