Re: pg_replslotdata - a tool for displaying replication slot information

2023-04-13 Thread Gurjeet
On Mon Jan 17, 2022 at 5:11 AM PST, Julien Rouhaud wrote:
> On Mon, Jan 17, 2022 at 04:10:13PM +0530, Bharath Rupireddy wrote:
> > 
> > Thanks Juilen. I'm okay if the patch gets dropped.
>
> Ok, I will take care of that soon.

I find this utility interesting and useful, especially for the reason
that it can provide information about the replication slots without
consuming a connection. I would be willing to continue the work on it.

Just checking here if, a year later, anyone has seen any more, or
interesting use-cases that would make it a candidate for its inclusion
in Postgres.

Best regards,
Gurjeet, http://Gurje.et
Postgres Contributors Team, https://aws.amazon.com/opensource




Re: Auto explain after query timeout

2022-09-20 Thread Gurjeet
On Tue Sep 20, 2022 at 10:34 AM PDT, James Coleman wrote:
> Hopefully I'm not missing something obvious, but as far as I know
> there's no way to configure auto explain to work fire
> statement_timeout fires.

I believe you're correct.

> I'd like to look into this at some point, but I'm wondering if anyone
> has thought about it before, and, if so, is there any obvious
> impediment to doing so?

This would be a neat feature. Since the changes would be fairly
localized to the contrib module, this would be a great first patch for
someone new to contributing.

This can be exposed at a new GUC auto_explain.log_on_statement_timeout.
I wish our conventions allowed for creating hierarchies of GUC
parameters, e.g. auto_explain.when.statmeent_timeout.

For someone who would like to achieve this in the field today, I believe
they can set auto_explain.log_min_duration equal to, or less than,
statement_timeout.

Best regards,
Gurjeet
http://Gurje.et




Re: Auto explain after query timeout

2022-09-20 Thread Gurjeet
On Tue Sep 20, 2022 at 11:34 AM PDT, James Coleman wrote:
> On Tue, Sep 20, 2022 at 2:12 PM Gurjeet  wrote:
> >
> > For someone who would like to achieve this in the field today, I believe
> > they can set auto_explain.log_min_duration equal to, or less than,
> > statement_timeout.
>
> Either I'm missing something (and/or this was fixed in a later PG
> version), but I don't think this is how it works. We have this
> specific problem now: we set auto_explain.log_min_duration to 200 (ms)
> and statement_timeout set to 30s, but when a statement times out we do
> not get the plan logged with auto-explain.

My DBA skills are rusty, so I'll take your word for it.

If this is the current behaviour, I'm inclined to treat this as a bug,
or at least a desirable improvement, and see if auto_explain can be
improved to emit the plan on statment_timeout.

>From what I undestand, the behaviour of auto_explain is that it waits
for the query to finish before it emits the plan. This information is
very useful for diagnosing long-running queries that are still running.
Many a times, you encounter such queries in production workloads, and
reproducing such a scenario later on is either undesirable, expensive, or
even impossible. So being able to see the plan of a query that has
crossed auto_explain.log_min_duration as soon as possible, would be highly
desirable.

Best regards,
Gurjeet
http://Gurje.et




Patch: Code comments: why some text-handling functions are leakproof

2022-01-10 Thread Gurjeet Singh
Please see attached a small patch to document why some text-processing
functions are marked as leakproof, while some others are not.

This is more or less a verbatim copy of Tom's comment in email thread at
[1].

I could not find an appropriate spot to place these comments, so I placed
them on bttextcmp() function, The only other place that I could see we can
place these comments is in the file src/backend/optimizer/README, because
there is some consideration given to leakproof functions in optimizer docs.
But these comments seem quite out of place in optimizer docs.

[1]:
https://www.postgresql.org/message-id/flat/673096.1630006990%40sss.pgh.pa.us#cd378cba4b990fda070c6fa4b51a069c

Best regards,
--
Gurjeet Singh http://gurjeet.singh.im/


leakproof_comments.patch
Description: Binary data


Begin a transaction on a SAVEPOINT that is outside any transaction

2021-11-22 Thread Gurjeet Singh
Currently there's a test [1] in the regression suite that ensures that
a SAVEPOINT cannot be initialized outside a transaction.

Instead of throwing an error, if we allowed it such that a SAVEPOINT
outside a transaction implicitly started a transaction, and the
corresponding ROLLBACK TO or RELEASE command finished that
transaction, I believe it will provide a uniform behavior that will
let SAVEPOINT be used on its own, to the exclusion of BEGIN, and I
believe the users will find it very useful as well.

For example, I was looking at a SQL script that is self-contained
(creates objects that it later operates on), but did not leverage
Postgres' ability to perform DDL and other non-DML operations inside a
transaction. My first instinct was to enclose it in a BEGIN-COMMIT
pair. But doing that would not play well with the other SQL scripts
that include/wrap it (using, say, \include or \ir). So the next
thought that crossed my mind was to wrap the script in a
SAVEPOINT-RELEASE pair, but that would obviously fail when the script
is sourced on its own, because SAVEPOINT and RELEASE are not allowed
outside a transaction.

Another possibility is as follows, but clearly not acceptable because
of uncertainty of outcome.

BEGIN TRANSACTION; -- Cmd1. issues a WARNING if already in txn, not otherwise
SAVEPOINT AA;
-- Do work
RELEASE SAVEPOINT AA;
COMMIT; -- This will commit the transaction started before Cmd1, if any.

Is there any desire to implement the behavior described in $SUBJECT?
Arguably, Postgres would be straying slightly further away from the
SQL compatibility of this command, but not by much.

Here's a sample session describing what the behavior would look like.

SAVEPOINT AA ; -- currently an error if outside a transaction;
-- but starts a transaction after implementation

-- Do work with other SQL commands

COMMIT ; -- Commits transaction AA started with savepoint. Transaction started
-- before that, if any, is not affected until its corresponding COMMIT/ROLLBACK.
-- Other commands that end this transaction:
-- -- ROLLBACK TO AA (rolls back txn; usual behavior)
-- -- RELEASE SAVEPOINT AA (commit/rollback depending on state of txn;
usual behavior)
-- -- ROLLBACK (rolls back the top-level transaction AA)

Looking at this example, we will also get the "named transactions"
feature for free! I don't know what the use of a named transaction
would be, though; identify it and use it in WAL and related features
somehow?!!

[1]:
commit cc813fc2b8d9293bbd4d0e0d6a6f3b9cf02fe32f
Author: Tom Lane 
Date:   Tue Jul 27 05:11:48 2004 +

Replace nested-BEGIN syntax for subtransactions with spec-compliant
SAVEPOINT/RELEASE/ROLLBACK-TO syntax.  (Alvaro)
Cause COMMIT of a failed transaction to report ROLLBACK instead of
COMMIT in its command tag.  (Tom)
Fix a few loose ends in the nested-transactions stuff.

-- only in a transaction block:
SAVEPOINT one;
ERROR:  SAVEPOINT can only be used in transaction blocks
ROLLBACK TO SAVEPOINT one;
ERROR:  ROLLBACK TO SAVEPOINT can only be used in transaction blocks
RELEASE SAVEPOINT one;
ERROR:  RELEASE SAVEPOINT can only be used in transaction blocks

Best regards,
--
Gurjeet Singh http://gurjeet.singh.im/




Fix comment in pgcrypto tests

2019-05-27 Thread Gurjeet Singh
Please see attached the patch that corrects the file-level SQL comment that
indicates which submodule of pgcrypto is being tested.

Best regards,
-- 
Gurjeet Singh http://gurjeet.singh.im/


pgcrypto-test-comments.patch
Description: Binary data


Re: Fix comment in pgcrypto tests

2019-05-28 Thread Gurjeet Singh
Thanks!

I have changed the patch status as follows in commitfest [1]
Reviewer: Michael Paquier
Committer: Michael Paquier
Status: committed

[1]: https://commitfest.postgresql.org/23/2132/

Best regards,

On Tue, May 28, 2019 at 3:38 AM Michael Paquier  wrote:

> On Mon, May 27, 2019 at 07:25:37PM -0700, Gurjeet Singh wrote:
> > Please see attached the patch that corrects the file-level SQL comment
> that
> > indicates which submodule of pgcrypto is being tested.
>
> Thanks, committed.  There was a second one in pgp-decrypt.sql.
> --
> Michael
>


-- 
Gurjeet Singh http://gurjeet.singh.im/


Re: Proposal: :SQL_EXEC_TIME (like :ROW_COUNT) Variable (psql)

2023-02-23 Thread Gurjeet Singh
On Thu, Feb 23, 2023 at 8:42 PM Kirk Wolak  wrote:
>   I love that my proposal for %T in the prompt, triggered some great 
> conversations.
>
>   This is not instead of that.  That lets me run a query and come back HOURS 
> later, and know it finished before 7PM like it was supposed to!

Neat! I have this info embedded in my Bash prompt [1], but many a
times this is not sufficient to reconstruct the time it took to run
the shell command.

>   This feature is simple.  We forget to set \timing on...
> We run a query, and we WONDER... how long did  that take.

And so I empathize with this need. I have set my Bash prompt to show
me this info [2].This info is very helpful in situations where you
fire a command, get tired of waiting for it and walk away for a few
minutes. Upon return it's very useful to see exactly how long did it
take for the command to finish.

>   I am not sure the name is right, but I would like to report it in the same 
> (ms) units as \timing, since there is an implicit relationship in what they 
> are doing.
>
>   I think like ROW_COUNT, it should not change because of internal commands.

+1

> So, you guys +1 this thing, give additional comments.  When the feedback 
> settles, I commit to making it happen.

This is definitely a useful feature. I agree with everything in the
proposed UI (reporting in milliseconds, don't track internal commands'
timing).

I think 'duration' or 'elapsed' would be a better words in this
context. So perhaps the name could be one of :sql_exec_duration (sql
prefix feels superfluous), :exec_duration, :command_duration, or
:elapsed_time.

By using \timing, the user is explicitly opting into any overhead
caused by time-keeping. With this feature, the timing info will be
collected all the time. So do consider evaluating the performance
impact this can cause on people's workloads. They may not care for the
impact in interactive mode, but in automated scripts, even a moderate
performance overhead would be a deal-breaker.

[1]: 
https://github.com/gurjeet/home/blob/08f1051fb854f4fc8fbc4f1326f393ed507a55ce/.bashrc#L278
[2]: 
https://github.com/gurjeet/home/blob/08f1051fb854f4fc8fbc4f1326f393ed507a55ce/.bashrc#L262

Best regards,
Gurjeet
http://Gurje.et




Named Operators

2023-01-12 Thread Gurjeet Singh
Technically correct name of this feature would be Readable Names for
Operators, or Pronounceable Names for Operators. But I'd like to call
it Named Operators.

With this patch in place, the users can name the operators as
:some_pronounceable_name: instead of having to choose from the special
characters like #^&@. For example, users will be able to create and
use operators like:

select
expr1 :distance: expr2,
expr3 :contains_all: expr4,
expr5 :contains_any: expr6
expr7 :contains_exactly_two_of: expr8
from mytable;

instead of being forced to use these:

select
expr1 <#> expr2,
expr3 ?&  expr4,
expr5 ?|  expr6
expr7 ??!! expr8 -- ¯\_(ツ)_/¯
from mytable;

I think Named Operators will significantly improve the readability
of queries.

After a little trial-an-error, it was easy to develop the scan.l
rules to implement this feature, without flex barfing. The hard part
has been convincing myself that this is a safe implementation, even
though there are no regressions in `make check`. I am unsure of this
implementation's compatibility with the SQL Spec, and I'm not able to
envision problems with its interaction with some current or potential
feature of Postgres. So I'd really appreciate feedback from someone
who is conversant with the SQL Spec.

If the colon character being used as a delimiter poses a
challenge, other good candidates for the delimiter seem to be one of
~^` Although I haven't tested any of these to see if they cause a
regression. The colon character is be preferable for the delimiter,
since it is already used in the typecast :: operator.

I tried to strip the delimiters/colons from the name right in the
scanner, primarily because that would allow the identifier part of the
name to be as long as NAMEDATALEN-1, just like other identifiers
Postgres allows. Added benefit of stripping delimiters was that the
rest of the code, and catalogs/storage won't have to see the
delimiters.  But stripping the delimiters made the code brittle; some
places in code now had to be taught different handling depending on
whether the operator name was coming from the user command, or from
the catalogs. I had to special-case code in pg_dump, as well. To share
code with frontends like pg_dump, I had to place code in src/common/.
I was still not able to address some obvious bugs.

By retaining the delimiters : in the name, the code became much
simpler; pg_dump support came for free! The bugs became a non-issue.
To see how much code and complexity was reduced, one can see this
commit [1]. The downside of retaining the delimiters is that the
identifier part of the name can be no more than NAMEDATALEN-3 in
length.

Because of the minimal changes to the scanner rules, and no
changes in the grammar, I don't think there's any impact on precedence
and associativity rules of the operators. I'd be happy to learn
otherwise.

Here's a rudimentary test case to demonstrate the feature:

create operator :add_point: (function = box_add, leftarg = box,
rightarg = point);
create table test(a box);
insert into test values('((0,0),(1,1))'), ('((0,0),(2,1))');
select a as original, a :add_point: '(1,1)' as modified from test;
drop operator :add_point:(box, point);

Feedback will be much appreciated!

[1]: Commit: Don't strip the delimiters
https://github.com/gurjeet/postgres/commit/62d11a578e5325c32109bb2a55a624d0d89d4b7e

[2]: Git branch named_operators
https://github.com/gurjeet/postgres/tree/named_operators

Best regards,
Gurjeet
http://Gurje.et


named_operators.patch
Description: Binary data


Re: Named Operators

2023-01-12 Thread Gurjeet Singh
Please see attached a slightly updated patch. There were some comment
changes sitting in uncommitted in Git worktree, that were missed.

Best regards,
Gurjeet
http://Gurje.et


named_operators_v1.patch
Description: Binary data


Re: Named Operators

2023-01-12 Thread Gurjeet Singh
On Thu, Jan 12, 2023 at 1:49 AM Matthias van de Meent
 wrote:
>
> On Thu, 12 Jan 2023 at 10:16, Gurjeet Singh  wrote:
> >
> > Technically correct name of this feature would be Readable Names for
> > Operators, or Pronounceable Names for Operators. But I'd like to call
> > it Named Operators.
> >
> > With this patch in place, the users can name the operators as
> > :some_pronounceable_name: instead of having to choose from the special
> > characters like #^&@.
> > [...]
> > I think Named Operators will significantly improve the readability
> > of queries.
>
> Couldn't the user better opt to call the functions that implement the
> operator directly if they want more legible operations? So, from your
> example, `SELECT box_add(a, b)` instead of `SELECT a :add_point: b`?

Matter of taste, I guess. But more importantly, defining an operator
gives you many additional features that the planner can use to
optimize your query differently, which it can't do with functions. See
the COMMUTATOR, HASHES, etc. clause in the CREATE OPERATOR command.

https://www.postgresql.org/docs/current/sql-createoperator.html

This proposal is primarily a replacement for the myriad of
hard-to-pronounce operators that users have to memorize. For example,
it'd be nice to have readable names for the PostGIS operators.

https://postgis.net/docs/reference.html#Operators

For someone who's reading/troubleshooting a PostGIS query, when they
encounter operator <<| — in the query for the first time, they'd have
to open up the docs. But if the query used the :strictly_below:
operator, there's no need to switch to docs and lose context.

> I'm -1 on the chosen syntax; :name: shadows common variable
> substitution patterns including those of psql.

Ah, thanks for reminding! Early on when I hadn't written code yet, I
remember discarding colon : as a delimiter choice, precisely because
it is used for using variables in psql, and perhaps in some drivers,
as well. But in the rush of implementing and wrangling code, I forgot
about that argument altogether.

I'll consider using one of the other special characters. Do you have
any suggestions?


Best regards,
Gurjeet
http://Gurje.et




Re: Named Operators

2023-01-14 Thread Gurjeet Singh
On Thu, Jan 12, 2023 at 5:55 AM Matthias van de Meent
 wrote:
> On Thu, 12 Jan 2023 at 11:59, Gurjeet Singh  wrote:
> > ... defining an operator
> > gives you many additional features that the planner can use to
> > optimize your query differently, which it can't do with functions. See
> > the COMMUTATOR, HASHES, etc. clause in the CREATE OPERATOR command.
>
> I see. Wouldn't it be better then to instead make it possible for the
> planner to detect the use of the functions used in operators and treat
> them as aliases of the operator? Or am I missing something w.r.t.
> differences between operator and function invocation?
>
> E.g. indexes on `int8pl(my_bigint, 1)` does not match queries for
> `my_bigint + 1` (and vice versa), while they should be able to support
> that, as OPERATOR(pg_catalog.+(int8, int8)) 's function is int8pl.

Such a feature would be immensely useful in its own right. But it's
also going to be at least 2 orders of magnitude (or more) effort to
implement, and to get accepted in the community. I'm thinking of
changes in planner, catalogs, etc.

On Thu, Jan 12, 2023 at 7:21 AM Tom Lane  wrote:
> Matthias van de Meent  writes:
> > I'm -1 on the chosen syntax; :name: shadows common variable
> > substitution patterns including those of psql.
>
> Yeah, this syntax is DOA because of that.  I think almost
> anything you might invent is going to have conflict risks.

I remember discussing this in a meeting with Joe Conway a few weeks
ago, when this was just a proposal in my head and I was just bouncing
it off him. And I remember pointing out that colons would be a bad
choice because of their use in psql; but for life of me I can't think
of a reason (except temporary memory loss) why I failed to consider
the psql conflict when implementing the feature. If only some test in
`make check` would have pointed out the mistake, I wouldn't have made
this obvious mistake.

> We could probably make it work by allowing the existing OPERATOR
> syntax to take things that look like names as well as operators,
> like
>
> expr3 OPERATOR(contains_all) expr4
>
> But that's bulky enough that nobody will care to use it.

+1. Although that'd be better for readers than the all-special-char
names, this format is bulky enough that you won't be able to convince
the query writers to bother using it. But if all other efforts fail,
I'll take this format over the cryptic ones any day.

> On the whole I don't see this proposal going anywhere.
> There's too much investment in the existing operator names,
> and too much risk of conflicts if you try to shorten the
> syntax.

I wouldn't give up on the idea, yet :-) See new proposal below.

On Thu, Jan 12, 2023 at 9:14 AM Tom Lane  wrote:
> Isaac Morland  writes:
> > What about backticks (`)?
>
> Since they're already allowed as operator characters, you can't
> use them for this purpose without breaking existing use-cases.
>
> Even if they were completely unused, I'd be pretty hesitant to
> adopt them for this purpose because of the potential confusion
> for users coming from mysql.

Since when have we started caring for the convenience of users of
other databases?!! /s

> Pretty much the only available syntax space is curly braces,
> and I don't really want to give those up for this either.
> (One has to assume that the SQL committee has their eyes
> on those too.)

On Thu, Jan 12, 2023 at 9:45 AM Vik Fearing  wrote:
> They are used in row pattern recognition.

I was very hopeful of using { }, and hoping that we'd beat the SQL
committee to it, so that they have to choose something else, if we
release this into the wild before them. But it seems that they beat us
to it long ago. (tangent: Reading some blog posts, I have to say I
loved the Row Pattern Recognition feature!)

Considering that there are almost no printable characters left in
1-255 ASCII range for us to choose from, I had to get creative; and I
believe I have found a way to make it work.

Unless the SQL committee has their eyes on a freestanding backslash \
character for something, I believe we can use it as a prefix for Named
Operators. Since the most common use of backslash is for escaping
characters, I believe it would feel natural for the users to use it as
described below.

New scheme for the named operators: \#foo That is, an identifier
prefixed with \# would serve as an operator name. psql considers \ to
be the start of its commands, but it wasn't hard to convince psql to
ignore \# and let it pass through to server.

I agree that an identifier _surrounded_ by the same token (e.g. #foo#)
or the pairing token (e.g. {foo}) looks better aesthetically, so I am
okay with any of the following variations of the scheme, as well:

\#foo\#  (tested; wor

Make message strings in fe-connect.c consistent

2023-04-20 Thread Gurjeet Singh
When reviewing a recently committed patch [1] I noticed the odd usage
of a format specifier:

+   libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
+   "load_balance_hosts",
+   conn->load_balance_hosts);

The oddity is that the first %s is unnecessary, since the value we
want there is a constant. Typically a format specifier used to get the
value stored in a variable.

Upon closer look, it looks like this is a common pattern in
fe-connect.c; there are many places where a %s format specifier is
being used in the format sting, where the name of the parameter would
have sufficed.

Upon some research, the only explanation I could come up with was that
this pattern of specifying error messages helps with message
translations. This way there's just one message to be translated. For
example:

.../libpq/po/es.po-#: fe-connect.c:1268 fe-connect.c:1294
fe-connect.c:1336 fe-connect.c:1345
.../libpq/po/es.po-#: fe-connect.c:1378 fe-connect.c:1422
.../libpq/po/es.po-#, c-format
.../libpq/po/es.po:msgid "invalid %s value: \"%s\"\n"

There's just one exception to this pattern, though.

> libpq_append_conn_error(conn, "invalid require_auth method: \"%s\"",
> method);

So, to make it consistent throughout the file, we should either
replace all such %s format specifiers with the respective strings, or
use the same pattern for the message string used for require_method,
as well. Attached patch [2] does the former, and patch [3] does the
latter.

Pick your favorite one.

[1]: Support connection load balancing in libpq
7f5b19817eaf38e70ad1153db4e644ee9456853e

[2]: Replace placeholders with known strings
v1-0001-Replace-placeholders-with-known-strings.patch

[3]: Make require_auth error message similar to surrounding messages
v1-0001-Make-require_auth-error-message-similar-to-surrou.patch

Best regards,
Gurjeet http://Gurje.et
Postgres Contributors Team, http://aws.amazon.com


v1-0001-Replace-placeholders-with-known-strings.patch
Description: Binary data


v1-0001-Make-require_auth-error-message-similar-to-surrou.patch
Description: Binary data


Re: Make message strings in fe-connect.c consistent

2023-04-20 Thread Gurjeet Singh
On Thu, Apr 20, 2023 at 9:31 PM Tom Lane  wrote:
>
> Gurjeet Singh  writes:
> > When reviewing a recently committed patch [1] I noticed the odd usage
> > of a format specifier:
>
> > +   libpq_append_conn_error(conn, "invalid %s value: \"%s\"",
> > +   "load_balance_hosts",
> > +   conn->load_balance_hosts);
>
> > The oddity is that the first %s is unnecessary, since the value we
> > want there is a constant. Typically a format specifier used to get the
> > value stored in a variable.
>
> This is actually intentional, on the grounds that it reduces the
> number of format strings that require translation.

That's the only reason I too could come up with.

> > There's just one exception to this pattern, though.
>
> >> libpq_append_conn_error(conn, "invalid require_auth method: \"%s\"",
> >> method);
>
> Yup, this one did not get the memo.

That explains why I could not find any translation for this error message.

Best regards,
Gurjeet http://Gurje.et
Postgres Contributors Team, http://aws.amazon.com




Minor code de-duplication in fe-connect.c

2023-04-20 Thread Gurjeet Singh
Commit [1] implements Fisher-Yates shuffling algorithm to shuffle
connection addresses, in two places.

The attached patch moves the duplicated code to a function, and calls
it in those 2 places.

[1]: Support connection load balancing in libpq
7f5b19817eaf38e70ad1153db4e644ee9456853e

Best regards,
Gurjeet https://Gurje.et
Postgres Contributors Team, http://aws.amazon.com


v0-0001-Reduce-code-duplication-in-fe-connect.c.patch
Description: Binary data


Reorder connection markers in libpq TAP tests

2023-04-20 Thread Gurjeet Singh
Commit 7f5b198 introduced TAP tests that use string literals to mark
the presence of a query in server logs. For no explicable reason, the
tests with the marker 'connect2' occur before the tests that use
'connect1' marker.

The attached patch swaps the connection marker strings so that a
reader doesn't have to spend extra deciphering why 'connect2' tests
appear before 'connect1' tests.

Best regards,
Gurjeet https://Gurje.et
Postgres Contributors Team, http://aws.amazon.com


v0-0001-Reorder-connection-markers-in-TAP-tests.patch
Description: Binary data


Re: Reorder connection markers in libpq TAP tests

2023-04-20 Thread Gurjeet Singh
On Thu, Apr 20, 2023 at 11:00 PM Gurjeet Singh  wrote:
>
> Commit 7f5b198 introduced TAP tests that use string literals to mark
> the presence of a query in server logs. For no explicable reason, the
> tests with the marker 'connect2' occur before the tests that use
> 'connect1' marker.
>
> The attached patch swaps the connection marker strings so that a
> reader doesn't have to spend extra deciphering why 'connect2' tests
> appear before 'connect1' tests.

Please see attached v2 of the patch. It now includes same fix in
another TAP tests file.


Best regards,
Gurjeet https://Gurje.et
Postgres Contributors Team, http://aws.amazon.com
From 8e785d5b440f17f7788c722582b2613e092ca18c Mon Sep 17 00:00:00 2001
From: Gurjeet Singh 
Date: Thu, 20 Apr 2023 22:49:00 -0700
Subject: [PATCH v2] Reorder connection markers in TAP tests

Commit 7f5b198 introduced TAP tests that use string literals to mark the
presence of a query in server logs. For no explicable reason, the tests
with the marker 'connect2' occur before the tests that use 'connect1'
marker.

So swap the connection marker strings so that a reader doesn't have to
spend extra effort deciphering why 'connect2' tests appear before
'connect1' tests.
---
 .../libpq/t/003_load_balance_host_list.pl  | 12 ++--
 src/interfaces/libpq/t/004_load_balance_dns.pl | 14 +++---
 2 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/src/interfaces/libpq/t/003_load_balance_host_list.pl b/src/interfaces/libpq/t/003_load_balance_host_list.pl
index 6963ef3849..7f1bb0c5bc 100644
--- a/src/interfaces/libpq/t/003_load_balance_host_list.pl
+++ b/src/interfaces/libpq/t/003_load_balance_host_list.pl
@@ -36,8 +36,8 @@ $node1->connect_fails(
 # load_balance_hosts=disable should always choose the first one.
 $node1->connect_ok("host=$hostlist port=$portlist load_balance_hosts=disable",
 	"load_balance_hosts=disable connects to the first node",
-	sql => "SELECT 'connect2'",
-	log_like => [qr/statement: SELECT 'connect2'/]);
+	sql => "SELECT 'connect1'",
+	log_like => [qr/statement: SELECT 'connect1'/]);
 
 # Statistically the following loop with load_balance_hosts=random will almost
 # certainly connect at least once to each of the nodes. The chance of that not
@@ -45,12 +45,12 @@ $node1->connect_ok("host=$hostlist port=$portlist load_balance_hosts=disable",
 foreach my $i (1 .. 50) {
 	$node1->connect_ok("host=$hostlist port=$portlist load_balance_hosts=random",
 		"repeated connections with random load balancing",
-		sql => "SELECT 'connect1'");
+		sql => "SELECT 'connect2'");
 }
 
-my $node1_occurences = () = $node1->log_content() =~ /statement: SELECT 'connect1'/g;
-my $node2_occurences = () = $node2->log_content() =~ /statement: SELECT 'connect1'/g;
-my $node3_occurences = () = $node3->log_content() =~ /statement: SELECT 'connect1'/g;
+my $node1_occurences = () = $node1->log_content() =~ /statement: SELECT 'connect2'/g;
+my $node2_occurences = () = $node2->log_content() =~ /statement: SELECT 'connect2'/g;
+my $node3_occurences = () = $node3->log_content() =~ /statement: SELECT 'connect2'/g;
 
 my $total_occurences = $node1_occurences + $node2_occurences + $node3_occurences;
 
diff --git a/src/interfaces/libpq/t/004_load_balance_dns.pl b/src/interfaces/libpq/t/004_load_balance_dns.pl
index d9b382dba9..b07bc9c074 100644
--- a/src/interfaces/libpq/t/004_load_balance_dns.pl
+++ b/src/interfaces/libpq/t/004_load_balance_dns.pl
@@ -9,7 +9,7 @@ use Test::More;
 if ($ENV{PG_TEST_EXTRA} !~ /\bload_balance\b/)
 {
 	plan skip_all =>
-	  'Potentially unsafe test load_balance not enabled in PG_TEST_EXTRA';
+	  'Potentially unsafe test; load_balance not enabled in PG_TEST_EXTRA';
 }
 
 # This tests loadbalancing based on a DNS entry that contains multiple records
@@ -78,8 +78,8 @@ $node3->start();
 # load_balance_hosts=disable should always choose the first one.
 $node1->connect_ok("host=pg-loadbalancetest port=$port load_balance_hosts=disable",
 	"load_balance_hosts=disable connects to the first node",
-	sql => "SELECT 'connect2'",
-	log_like => [qr/statement: SELECT 'connect2'/]);
+	sql => "SELECT 'connect1'",
+	log_like => [qr/statement: SELECT 'connect1'/]);
 
 
 # Statistically the following loop with load_balance_hosts=random will almost
@@ -88,12 +88,12 @@ $node1->connect_ok("host=pg-loadbalancetest port=$port load_balance_hosts=disabl
 foreach my $i (1 .. 50) {
 	$node1->connect_ok("host=pg-loadbalancetest port=$port load_balance_hosts=ran

Re: Minor code de-duplication in fe-connect.c

2023-04-21 Thread Gurjeet Singh
On Fri, Apr 21, 2023 at 7:47 AM Robert Haas  wrote:
>
> On Fri, Apr 21, 2023 at 8:25 AM Daniel Gustafsson  wrote:
> > The reason I left it like this when reviewing and committing is that I 
> > think it
> > makes for more readable code.  The amount of lines saved is pretty small, 
> > and
> > "shuffle" isn't an exact term so by reading the code it isn't immediate 
> > clear
> > what such a function would do.  By having the shuffle algorithm where it's 
> > used
> > it's clear what the code does and what the outcome is.  If others disagree I
> > can go ahead and refactor of course, but I personally would not deem it a 
> > net
> > win in code quality.
>
> I think we should avoid nitpicking stuff like this. I likely would
> have used a subroutine if I'd done it myself, but I definitely
> wouldn't have submitted a patch to change whatever the last person did
> without some tangible reason for so doing.

Code duplication, and the possibility that a change in one location
(bugfix or otherwise) does not get applied to the other locations, is
a good enough reason to submit a patch, IMHO.

> It's not a good use of
> reviewer and committer time to litigate things like this.

Postgres has a very high bar for code quality, and for documentation.
It is a major reason that attracts people to, and keeps them in the
Postgres ecosystem, as users and contributors. If anything, we should
encourage folks to point out such inconsistencies in code and docs
that keep the quality high.

This is not a attack on any one commit, or author/committer of the
commit; sorry if it appeared that way. I was merely reviewing the
commit that introduced a nice libpq feature. This patch is merely a
minor improvement to the code that I think deserves a consideration.
It's not a litigation, by any means.

Best regards,
Gurjeet https://Gurje.et
Postgres Contributors Team, http://aws.amazon.com




Re: Correct the documentation for work_mem

2023-04-21 Thread Gurjeet Singh
On Fri, Apr 21, 2023 at 10:15 AM Tom Lane  wrote:
>
> Peter Eisentraut  writes:
> > On 21.04.23 16:28, Imseih (AWS), Sami wrote:
> >> I suggest a small doc fix:
> >> “Note that for a complex query, several sort or hash operations might be
> >> running simultaneously;”
>
> > Here is a discussion of these terms:
> > https://takuti.me/note/parallel-vs-concurrent/
>
> > I think "concurrently" is the correct word here.
>
> Probably, but it'd do little to remove the confusion Sami is on about,

+1.

When discussing this internally, Sami's proposal was in fact to use
the word 'concurrently'. But given that when it comes to computers and
programming, it's common for someone to not understand the intricate
difference between the two terms, we thought it's best to not use any
of those, and instead use a word not usually associated with
programming and algorithms.

Aside: Another pair of words I see regularly used interchangeably,
when in fact they mean different things: precise vs. accurate.

> especially since the next sentence uses "concurrently" to describe the
> other case.  I think we need a more thorough rewording, perhaps like
>
> -   Note that for a complex query, several sort or hash operations might 
> be
> -   running in parallel; each operation will generally be allowed
> +   Note that a complex query may include several sort or hash
> +   operations; each such operation will generally be allowed

This wording doesn't seem to bring out the fact that there could be
more than one work_mem consumer running (in-progress) at the same
time. The reader to could mistake it to mean hashes and sorts in a
complex query may happen one after the other.

+ Note that a complex query may include several sort and hash operations, and
+ more than one of these operations may be in progress simultaneously at any
+ given time;  each such operation will generally be allowed

I believe the phrase "several sort _and_ hash" better describes the
possible composition of a complex query, than does "several sort _or_
hash".

> I also find this wording a bit further down to be poor:
>
> Hash-based operations are generally more sensitive to memory
> availability than equivalent sort-based operations.  The
> memory available for hash tables is computed by multiplying
> work_mem by
> hash_mem_multiplier.  This makes it
>
> I think "available" is not le mot juste, and it's also unclear from
> this whether we're speaking of the per-hash-table limit or some
> (nonexistent) overall limit.  How about
>
> -   memory available for hash tables is computed by multiplying
> +   memory limit for a hash table is computed by multiplying

+1

Best regards,
Gurjeet https://Gurje.et
Postgres Contributors Team, http://aws.amazon.com




Mark a transaction uncommittable

2023-04-22 Thread Gurjeet Singh
This is a proposal for a new transaction characteristic. I haven't
written any code, yet, and am interested in hearing if others may find
this feature useful.

Many a times we start a transaction that we never intend to commit;
for example, for testing, or for EXPLAIN ANALYZE, or after detecting
unexpected results but still interested in executing more commands
without risking commit,  etc.

A user would like to declare their intent to eventually abort the
transaction as soon as possible, so that the transaction does not
accidentally get committed.

This feature would allow the user to mark a transaction such that it
can never be committed. We must allow such marker to be placed when
the transaction is being started, or while it's in progress.

Once marked uncommittable, do not allow the marker to be removed.
Hence, once deemed uncommittable, the transaction cannot be committed,
even intentionally. This protects against cases where one script
includes another (e.g. psql's \i command), and the included script may
have statements that turn this marker back on.

Any command that ends a transaction (END, COMMIT, ROLLBACK) must
result in a rollback.

All of these properties seem useful for savepoints, too. But I want to
focus on just the top-level transactions, first.

I feel like the BEGIN and SET TRANSACTION commands would be the right
places to introduce this feature.

BEGIN [ work | transaction ] [ [ NOT ] COMMITTABLE ];
SET TRANSACTION [ [ NOT ] COMMITTABLE ];

I'm not yet sure if the COMMIT AND CHAIN command should carry this
characteristic to the next transaction.

Thoughts?

Best regards,
Gurjeet https://Gurje.et
http://aws.amazon.com




Re: [PATCH] Infinite loop while acquiring new TOAST Oid

2023-04-22 Thread Gurjeet Singh
On Thu, Dec 22, 2022 at 10:07 AM Nikita Malakhov  wrote:
> Any suggestions on the previous message (64-bit toast value ID with 
> individual counters)?

Was this patch ever added to CommitFest? I don't see it in the current
Open Commitfest.

https://commitfest.postgresql.org/43/

Best regards,
Gurjeet http://Gurje.et
http://aws.amazon.com




Re: Doc limitation update proposal: include out-of-line OID usage per TOAST-ed columns

2023-04-22 Thread Gurjeet Singh
On Fri, Apr 21, 2023 at 12:14 AM Nikita Malakhov  wrote:
> This limitation applies not only to wide tables - it also applies to tables 
> where TOASTed values
> are updated very often. You would soon be out of available TOAST value ID 
> because in case of
> high frequency updates autovacuum cleanup rate won't keep up with the 
> updates. It is discussed
> in [1].
>
> On Fri, Apr 21, 2023 at 9:39 AM Jakub Wartak  
> wrote:
>> I would like to ask if it wouldn't be good idea to copy the
>> https://wiki.postgresql.org/wiki/TOAST#Total_table_size_limit
>> discussion (out-of-line OID usage per TOAST-ed columns / potential
>> limitation) to the official "Appendix K. PostgreSQL Limits" with also
>> little bonus mentioning the "still searching for an unused OID in
>> relation" notice. Although it is pretty obvious information for some
>> and from commit 7fbcee1b2d5f1012c67942126881bd492e95077e and the
>> discussion in [1], I wonder if the information shouldn't be a little
>> more well known via the limitation (especially to steer people away
>> from designing very wide non-partitioned tables).
>>
>> [1] - 
>> https://www.postgresql.org/message-id/flat/16722-93043fb459a41073%40postgresql.org
>
> [1] 
> https://www.postgresql.org/message-id/CAN-LCVPRvRzxeUdYdDCZ7UwZQs1NmZpqBUCd%3D%2BRdMPFTyt-bRQ%40mail.gmail.com

These 2 discussions show that it's a painful experience to run into
this problem, and that the hackers have ideas on how to fix it, but
those fixes haven't materialized for years. So I would say that, yes,
this info belongs in the hard-limits section, because who knows how
long it'll take this to be fixed.

Please submit a patch.

I anticipate that edits to Appendix K Postgres Limits will prompt
improving the note in there about the maximum column limit, That note
is too wordy, and sometimes confusing, especially for the audience
that it's written for: newcomers to Postgres ecosystem.

Best regards,
Gurjeet https://Gurje.et
http://aws.amazon.com




Re: Minor code de-duplication in fe-connect.c

2023-04-24 Thread Gurjeet Singh
On Mon, Apr 24, 2023 at 5:14 AM Daniel Gustafsson  wrote:

> > On 21 Apr 2023, at 18:38, Gurjeet Singh  wrote:
> >
> > On Fri, Apr 21, 2023 at 7:47 AM Robert Haas 
> wrote:
> >>
> >> On Fri, Apr 21, 2023 at 8:25 AM Daniel Gustafsson 
> wrote:
> >>> The reason I left it like this when reviewing and committing is that I
> think it
> >>> makes for more readable code.  The amount of lines saved is pretty
> small, and
> >>> "shuffle" isn't an exact term so by reading the code it isn't
> immediate clear
> >>> what such a function would do.  By having the shuffle algorithm where
> it's used
> >>> it's clear what the code does and what the outcome is.  If others
> disagree I
> >>> can go ahead and refactor of course, but I personally would not deem
> it a net
> >>> win in code quality.
> >>
> >> I think we should avoid nitpicking stuff like this. I likely would
> >> have used a subroutine if I'd done it myself, but I definitely
> >> wouldn't have submitted a patch to change whatever the last person did
> >> without some tangible reason for so doing.
> >
> > Code duplication, and the possibility that a change in one location
> > (bugfix or otherwise) does not get applied to the other locations, is
> > a good enough reason to submit a patch, IMHO.
> >
> >> It's not a good use of
> >> reviewer and committer time to litigate things like this.
> >
> > Postgres has a very high bar for code quality, and for documentation.
> > It is a major reason that attracts people to, and keeps them in the
> > Postgres ecosystem, as users and contributors. If anything, we should
> > encourage folks to point out such inconsistencies in code and docs
> > that keep the quality high.
> >
> > This is not a attack on any one commit, or author/committer of the
> > commit; sorry if it appeared that way. I was merely reviewing the
> > commit that introduced a nice libpq feature. This patch is merely a
> > minor improvement to the code that I think deserves a consideration.
> > It's not a litigation, by any means.
>
> I didn't actually read the patch earlier, but since Robert gave a +1 to the
> idea of refactoring I had a look. I have a few comments:
>
> +static void
> +shuffleAddresses(PGConn *conn)
> This fails to compile since the struct is typedefed PGconn.
>
>
> -   /*
> -* This is the "inside-out" variant of the Fisher-Yates shuffle
> -* algorithm. Notionally, we append each new value to the array
> -* and then swap it with a randomly-chosen array element (possibly
> -* including itself, else we fail to generate permutations with
> -* the last integer last).  The swap step can be optimized by
> -* combining it with the insertion.
> -*
>  * We don't need to initialize conn->prng_state here, because that
>  * already happened in connectOptions2.
>  */
> This also fails to compile since it removes the starting /* marker of the
> comment resulting in a comment starting on *.
>
>
> -   for (i = 1; i < conn->nconnhost; i++)
> -   for (int i = 1; i < conn->naddr; i++)
> You are replacing these loops for shuffling an array with a function that
> does
> this:
> +   for (int i = 1; i < conn->naddr; i++)
> This is not the same thing, one is shuffling the hosts and the other is
> shuffling the addresses resolved for the hosts (which may be a n:m
> relationship).  If you had compiled and run the tests you would have seen
> that
> the libpq tests now fail with this applied, as would be expected.
>
>
> Shuffling the arrays can of course be made into a subroutine, but what to
> shuffle and where needs to be passed in to it and at that point I doubt the
> code readability is much improved over the current coding.
>
>
Sorry about the errors. This seems to be the older version of the patch
that I had generated before fixing these mistakes. I do remember
encountering the compiler errors and revising the code to fix these,
especially the upper vs. lower case and the partial removal of the coment.
Away from my keyboard, so please expect the newer patch some time later.

Best regards,
Gurjeet
http://Gurje.et


Postgres Index Advisor status and GSoC (was: Re: Returning to Postgres community work)

2023-05-11 Thread Gurjeet Singh
On Tue, Aug 31, 2021 at 10:02 AM Gurjeet Singh  wrote:
> On Tue, Aug 31, 2021 at 8:04 AM Alvaro Herrera  
> wrote:
>
> > You know what I've heard?  That your index advisor module languishes
> > unmaintained and that there's no shortage of people wishing to use it.
>
> Now there's a masterclass in making someone feel great and guilty in
> the same sentence ;-)
>
> > Heck, we spent a lot of back-and-forth in the spanish mailing list
> > with somebody building a super obsolete version of Postgres just so that
> > they could compile your index advisor.  I dunno, if you have some spare
> > time, maybe updating that one would be a valuable contribution from
> > users' perspective.
>
> Aye-aye Capn' :-)

As part of helping the GSoC contributor getting onboard (see below), I
went through a similar process and had to figure out the Postgres
version, system packages, etc. (all ancient) that were needed to build
and use it. It's no fun having to deal with software from over a
decade ago :-(

> EDB folks reached out to me a few months ago to assign a license to
> the project, which I did and it is now a Postgres-licensed project
> [1].
>
> Given the above, it is safe to assume that this tool is at least being
> maintained by EDB, at least internally for their customers. I would
> request them to contribute the changes back in the open.

After over a year of conversations and follow-ups, a couple of months
ago EnterpriseDB finally made it clear that they won't be contributing
their changes back to the open-source version of Index Advisor. With
that avenue now closed, we can now freely pursue

> Regardless of that, please rest assured that I will work on making it
> compatible with the current supported versions of Postgres. Lack of
> time is not an excuse anymore :-)

Oh, how wrong was I :-)

I have a few updates on the current state and plans around the Index
Adviser extension.

I proposed Index Adviser as a potential project for GSoC 2023 [1].
Ahmed (CCd) has signed up as the contributor. The project has now been
accepted/funded by GSoC. The primary goal of the project is to support
all the active versions of Postgres. The extended goal is to support
additional index types. The extension currently supports Postgres
version 8.3, and BTree index type.

[1]: 
https://wiki.postgresql.org/wiki/GSoC_2023#pg_adviser_.2F_index_adviser:_Recommend_Potentially_Useful_Indexes

Best regards,
Gurjeet
http://Gurje.et




Re: Remove extraneous break condition in logical slot advance function

2023-10-21 Thread Gurjeet Singh
On Fri, Oct 20, 2023 at 7:30 PM Bharath Rupireddy
 wrote:
>
> Hi,
>
> There exists an extraneous break condition in
> pg_logical_replication_slot_advance(). When the end of WAL or moveto
> LSN is reached, the main while condition helps to exit the loop, so no
> separate break condition is needed. Attached patch removes it.
>
> Thoughts?

+1 for the patch.

The only advantage I see of the code as it stands right now is that it
avoids one last call to CHECK_FOR_INTERRUPTS() by break'ing early. I
don't think we'd lose much in terms of performance by making one (very
cheap, in common case) extra call of this macro.

Best regards,
Gurjeet
http://Gurje.et




Replace references to malloc() in libpq documentation with generic language

2023-10-23 Thread Gurjeet Singh
The commit message in the attached patch provides the reasoning, as follows:

The user does not benefit from knowing that libpq allocates some/all memory
using malloc(). Mentioning malloc() here has a few downsides, and almost no
benefits.

All the relevant mentions of malloc() are followed by an explicit
instruction to use PQfreemem() to free the resulting objects. So the
docs perform the sufficient job of educating the user on how to properly
free the memory.  But these mentions of malloc() may still lead an
inexperienced or careless user to (wrongly) believe that they may use
free() to free the resulting memory. They will be in a lot of pain until
they learn that (when linked statically) libpq's malloc()/free() cannot
be mixed with malloc()/free() of whichever malloc() library the client
application is being linked with.

Another downside of explicitly mentioning that objects returned by libpq
functions are allocated with malloc(), is that it exposes the implementation
details of libpq to the users. Such details are best left unmentioned so that
these can be freely changed in the future without having to worry about its
effect on client applications.

Whenever necessary, it is sufficient to tell the user that the objects/memory
returned by libpq functions is allocated on the heap. That is just enough
detail for the user to realize that the relevant object/memory needs to be
freed; and the instructions that follow mention to use PQfreemem() to free such
memory.

One mention of malloc is left intact, because that mention is unrelated to how
the memory is allocated, or how to free it.

In passing, slightly improve the language of PQencryptPasswordConn()
documentation.

Best regards,
Gurjeet
http://Gurje.et


v1-0001-Replace-references-to-malloc-in-libpq-documentati.patch
Description: Binary data


Re: simplehash: preserve consistency in case of OOM

2023-11-17 Thread Gurjeet Singh
On Fri, Nov 17, 2023 at 12:13 PM Andres Freund  wrote:
>
> On 2023-11-17 10:42:54 -0800, Jeff Davis wrote:
> > Right now, if allocation fails while growing a hashtable, it's left in
> > an inconsistent state and can't be used again.

+1 to the patch.

> I'm not against allowing this - but I am curious, in which use cases is this
> useful?

I don't have an answer to that, but a guess would be when the server
is dealing with memory pressure. In my view the patch has merit purely
on the grounds of increasing robustness.

> > @@ -446,10 +459,11 @@ SH_CREATE(MemoryContext ctx, uint32 nelements, void 
> > *private_data)
> >   /* increase nelements by fillfactor, want to store nelements elements 
> > */
> >   size = Min((double) SH_MAX_SIZE, ((double) nelements) / 
> > SH_FILLFACTOR);
> >
> > - SH_COMPUTE_PARAMETERS(tb, size);
> > + size = SH_COMPUTE_SIZE(size);
> >
> > - tb->data = (SH_ELEMENT_TYPE *) SH_ALLOCATE(tb, 
> > sizeof(SH_ELEMENT_TYPE) * tb->size);
> > + tb->data = (SH_ELEMENT_TYPE *) SH_ALLOCATE(tb, 
> > sizeof(SH_ELEMENT_TYPE) * size);
> >
> > + SH_UPDATE_PARAMETERS(tb, size);
> >   return tb;
> >  }
>
> Maybe add a comment explaining why it's important to update parameters after
> allocating?

Perhaps something like this:

+ /*
+ * Update parameters _after_ allocation succeeds; prevent
+ * bogus/corrupted state.
+ */
+ SH_UPDATE_PARAMETERS(tb, size);

Best regards,
Gurjeet
http://Gurje.et




Re: Change GUC hashtable to use simplehash?

2023-11-17 Thread Gurjeet Singh
On Fri, Nov 17, 2023 at 11:02 AM Jeff Davis  wrote:
>
> I had briefly experimented changing the hash table in guc.c to use
> simplehash. It didn't offer any measurable speedup, but the API is
> slightly nicer.
>
> I thought I'd post the patch in case others thought this was a good
> direction or nice cleanup.

This is not a comment on the patch itself, but since GUC operations
are not typically considered performance or space sensitive, this
comment from simplehash.h makes a case against it.

 *  It's probably not worthwhile to generate such a specialized
implementation
 *  for hash tables that aren't performance or space sensitive.

But your argument of a nicer API might make a case for the patch. I

Best regards,
Gurjeet
http://Gurje.et




Re: Document that server will start even if it's unable to open some TCP/IP ports

2023-09-12 Thread Gurjeet Singh
On Fri, Sep 8, 2023 at 7:52 AM Bruce Momjian  wrote:
>
> On Thu, Sep  7, 2023 at 09:21:07PM -0700, Nathan Bossart wrote:
> > On Thu, Sep 07, 2023 at 07:13:44PM -0400, Bruce Momjian wrote:
> > > On Thu, Sep  7, 2023 at 02:54:13PM -0700, Nathan Bossart wrote:
> > >> IMO the phrase "open a port" is kind of nonstandard.  I think we should 
> > >> say
> > >> something along the lines of
> > >>
> > >>If listen_addresses is not empty, the server will start only if it can
> > >>listen on at least one of the specified addresses.  A warning will be
> > >>emitted for any addresses that the server cannot listen on.
> > >
> > > Good idea, updated patch attached.
> >
> > I still think we should say "listen on an address" instead of "open a
> > port," but otherwise it LGTM.
>
> Agreed, I never liked the "port" mention.  I couldn't figure how to get
> "open" out of the warning sentence though.  Updated patch attached.

LGTM.

Best regards,
Gurjeet
http://Gurje.et




Re: Document that server will start even if it's unable to open some TCP/IP ports

2023-10-01 Thread Gurjeet Singh
On Tue, Sep 26, 2023 at 4:02 PM Bruce Momjian  wrote:
>
> Patch applied back to PG 11.

+Peter E. since I received the following automated note:

> Closed in commitfest 2023-09 with status: Moved to next CF (petere)

Just a note that this patch has been committed (3fea854691), so I have
marked the CF item [1] as 'Committed', and specified Bruce as the
committer.

[1]: https://commitfest.postgresql.org/45/4333/


Best regards,
Gurjeet
http://Gurje.et




Re: [PoC/RFC] Multiple passwords, interval expirations

2023-10-04 Thread Gurjeet Singh
u1 VALID UNTIL '2022/01/01';
-- Note that currently I don't have a proposal for how to change the old
-- password's validity period, without deleting the latest/main password. See
-- PASSWORD NULL command below on how to delete the current password. It's very
-- likely that in a password rollover use case it's unnecessary, even
-- undesirable, to change the old password's validity period.

-- If, for some reason, the user wants to get rid of the latest password added.
-- Remove 'p2' (current password). The old password (p1), will be restored to
-- rolpassword, along with its valid-until value.
ALTER ROLE u1 PASSWORD NULL;
-- This may come as a surprise to some users, because currently they expect the
-- user to completely lose the ability to use passwords for login after this
-- command. To get the old behavior, the user must now use the ALL PASSWORD
-- NULL incantation; see below.
-- Issuing this command one more time will remove even the restored password,
-- hence leaving the user with no passwords.

-- Change the validity of the restored/current password (p1)
ALTER ROLE u1 VALID UNTIL '2022/01/01';

-- Add a new password (p3) without affecting old password's (p1) validity
ALTER ROLE u1 ADD PASSWORD 'p3' VALID UNTIL '2023/01/01';

-- Add a new password 'p4'. This will move 'p3' to rololdpassword, and hence
-- 'p1' will be forgotten completely.
-- After this command, user can use passwords 'p3' (old) and 'p4' (current) to
-- login.
ALTER ROLE u1 ADD PASSWORD 'p4' VALID UNTIL '2024/01/01';

-- Replace 'p4' (current) password with 'p5'. Note that this command is _not_
-- using the ADD keyword, hence 'p4' is _not_ moved to rololdpassword column.
-- After this command, user can use passwords 'p3' (old) and 'p5'
-- (current) to login.
ALTER ROLE u1 PASSWORD 'p5' VALID UNTIL '2025/01/01';

-- Using the old password to login will produce a warning, hopefully nudging
-- the user to start using the new password.
export PGPASSWORD=p3
psql -U u1
...
WARNING: Used old password to login

export PGPASSWORD=p5
psql -U u1
...
=> (no warning)

-- Remove all passwords from the role. Even old password, if any, is removed.
ALTER ROLE u1 ALL PASSWORD NULL;

In normal use, the users can simply keep ADDing new passwords, and the
database will promptly remember only one old password, and keep
forgetting any passwords older than that. But on the off chance
that someone needs to forget the latest password they added, and
restore the old password to be the "current" password, they can use
the PASSWORD NULL incantation. Note that this will result in
rol*old*password being set to NULL, because our password memory stack
cannot hold more than 2 elements.

Since this feature is targeted towards password rollovers, it's a legitimate
question to ask if we should enforce that the new password being added has a
valid-until greater than the valid-until of the existing/old password. I don't
think we should enforce this, at least not in this patch, because the
user/admin may have a use case where they want a short-lived new password that
they intend/want to change very soon; I'm thinking of cases where passwords are
being rolled over while they are also moving from older clients/libraries that
don't yet support scram-sha-256; keep using md5 and add passwords to honor
password rollover policy, but then as soon as all clients have been updated and
have the ability to use scram-sha-256, rollover the password again to utilize
the better mechanism.

I realize that allowing for a maximum of 2 passwords goes against the
zero-one-infinity rule [1], but I think in the case of password
rollovers it's perfectly acceptable to limit the number of active
passwords to just 2. If there are use cases, either related to password
rollovers, or in its vicinity, that can be better addressed by
allowing an arbitrarily many passwords, I would love to learn about
them and change this design to accommodate for those use cases, or
perhaps revert to pursuing the multiple-passwords feature.

[1]: https://en.wikipedia.org/wiki/Zero_one_infinity_rule

Best regards,
Gurjeet
http://Gurje.et




Re: Good News Everyone! + feature proposal

2023-10-05 Thread Gurjeet Singh
On Thu, Oct 5, 2023 at 1:52 AM Jon Erdman  wrote:
>
> So I have some good news! At long last I've found a company/manager that
> wants to actually factually pay me to do some work on PG!!

Congratulations!

> For the proposal (this one is a bit Apple specific): because my team
> offers managed postgres to our Apple-internal customers, many of whom
> are not database experts, or at least not postgres experts, we'd like to
> be able to toggle the availability of UNLOGGED tables in
> postgresql.conf, so our less clueful users have fewer footguns.
>
> So, my proposal is for a GUC to implement that, which would *OF COURSE*
> undefault to allowing UNLOGGED.

That was difficult to parse at first glance. I guess you mean the
GUC's default value will not change the current behaviour, as you
mention below.

> The reasoning here is we have autofailover set up for our standard
> cluster offering that we give to customers, using sync-rep to guarantee
> no data loss if we flop to the HA node. Any users not up to speed on
> what UNLOGGED really means could inadvertently lose data, so we'd like
> to be able to force it to be off, and turn it on upon request after
> educating the customer in question it's it's a valid use case.
>
> So to begin with: I'm sure some folks will hate this idea, but maybe a
> good many wont, and remember, this would default to UNLOGGED enabled, so
> no change to current behaviour. and no encouragement to disallow it, but
> just the ability to do so, which i think is useful in
> hosted/managed/multi-tenant environment where most things are taken care
> of for the customer.

I see the need to disable this feature and agree that some
installations may need it, where the users are not savvy enough to
realize its dangers and fall for its promise to increase INSERT/UPDATE
performance. Your specific example of an internal hosted/managed
service is a good example. Even in smaller installations the DBA might
want to disable this, so that unwary developers don't willy-nilly
create unlogged tables and end up losing data after a failover. I hope
others can provide more examples and situations where this may be
useful, to make it obvious that we need this feature.

My first reaction was to make it a GRANTable permission. But since one
can always do `ALTER USER savvy_user SET allow_unlogged_tables TO
true` and override the system-wide setting in postgresql.conf, for a
specific user, I feel a GUC would be the right way to implement it.

The complaint about too many GUCs is a valid one, but I'd worry more
about it if it were an optimizer/performance improvement being hidden
behind a GUC. This new GUC would be a on-off switch to override the
SQL/grammar feature provided by the UNLOGGED keyword, hence not really
a concern IMO.

> So I'd like to get a general idea how likely this would be to getting
> accepted if it did it, and did it right?

Like others said, there are no guarantees. A working patch may help
guide people's opinion one way or the other, so I'd work on submitting
a patch while (some) people are in agreement.

> Let the flame war begin!

Heh. I'm sure you already know this, but this community's flame wars
are way more timid compared to what members of other communities may
be used to :-) I consider it lucky if someone throws as much as a lit
match.

> PS: I'm SO happy that this phase of my postgres journey has finally
> started

I, too, am very happy for you! :-)

> Jon Erdman (aka StuckMojo on IRC)

TIL.

I wish there was a directory of IRC identities that pointed to real
identities (at least for folks who don't mind this mapping available
in the open), so that when we converse in IRC, we have a face to go
with the IRC handles. As a human I feel that necessity.

Best regards,
Gurjeet
http://Gurje.et




Re: [PoC/RFC] Multiple passwords, interval expirations

2023-10-05 Thread Gurjeet Singh
On Thu, Oct 5, 2023 at 12:04 PM Nathan Bossart  wrote:
>
> On Wed, Oct 04, 2023 at 10:41:15PM -0700, Gurjeet Singh wrote:
> > The patches posted in this thread so far attempt to add the ability to
> > allow the user to have an arbitrary number of passwords. I believe
> > that allowing arbitrary number of passwords is not only unnecessary,
> > but the need to name passwords, the need to store them in a shared
> > catalog, etc. may actually create problems in the field. The
> > users/admins will have to choose names for passwords, which they
> > didn't have to previously. The need to name them may also lead to
> > users storing password-hints in the password names (e.g. 'mom''s
> > birthday', 'ex''s phone number', 'third password'), rendering the
> > passwords weak.
> >
> > Moreover, allowing an arbitrarily many number of passwords will
> > require us to provide additional infrastructure to solve problems like
> > observability (which passwords are currently in use, and which ones
> > have been effectively forgotten by applications), or create a nuisance
> > for admins that can create more problems than it solves.
>
> IMHO neither of these problems seems insurmountable.

Agreed.

> Besides advising
> against using hints as names, we could also automatically generate safe
> names, or even disallow user-provided names entirely.

Somehow naming passwords doesn't feel palatable to me.

> And adding
> observability for passwords seems worthwhile anyway.

Agreed.

> > So I propose that the feature should allow no more than 2 passwords
> > for a role, each with their own validity periods. This eliminates the
> > need to name passwords, because at any given time there are no more
> > than 2 passwords; current one, and old one. This also eliminates the
> > need for a shared catalog to hold passwords, because with the limit of
> > 2 imposed, we can store the old password and its validity period in
> > additional columns in the pg_authid table.
>
> Another approach could be to allow an abritrary number of passwords but to
> also allow administrators to limit how many passwords can be associated to
> each role.  That way, we needn't restrict this feature to 2 passwords for
> everyone.  Perhaps 2 should be the default, but in any case, IMO we
> shouldn't design to only support 2.

I don't see a real use case to support more than 2 passwords. Allowing
an arbitrary number of passwords might look good and clean from
aesthetics and documentation perspective (no artificially enforced
limits, as in the zero-one-infinity rule), but in absence of real use
cases for that many passwords, I'm afraid we might end up with a
feature that creates more and worse problems for the users than it
solves.

> > In essence, we create a stack that can hold 2 passwords. Pushing an
> > element when it's full will make it forget the bottom element. Popping
> > the stack makes it forget the top element, and the only remaining
> > element, if any, becomes the top.
>
> I think this would be mighty confusing to users since it's not clear that
> adding a password will potentially invalidate a current password (which
> might be actively in use), but only if there are already 2 in the stack.

Fair point. We can aid the user by emitting a NOTICE (or a WARNING)
message whenever an old password is removed from the system because of
addition of a new password.

> I
> worry that such a desіgn might be too closely tailored to the
> implementation details.  If we proceed with this design, perhaps we should
> consider ERROR-ing if a user tries to add a third password.

I did not have a stack in mind when developing the use case and the
grammar, so implementation details did not drive this design. This new
design was more of a response to the manageability nightmare that I
could see the old approach may lead to. When writing the email I
thought mentioning the stack analogy may make it easier to develop a
mental model. I certainly won't suggest using it in the docs for
explanation :-)

> > -- If, for some reason, the user wants to get rid of the latest password 
> > added.
> > -- Remove 'p2' (current password). The old password (p1), will be restored 
> > to
> > -- rolpassword, along with its valid-until value.
> > ALTER ROLE u1 PASSWORD NULL;
> > -- This may come as a surprise to some users, because currently they expect 
> > the
> > -- user to completely lose the ability to use passwords for login after this
> > -- command. To get the old behavior, the user must now use the ALL PASSWORD
> > -- NULL incantation; see below.
> > -- Issuing this command one more

Re: [PoC/RFC] Multiple passwords, interval expirations

2023-10-05 Thread Gurjeet Singh
On Thu, Oct 5, 2023 at 1:09 PM Jeff Davis  wrote:
>
> >
> > I think this would be mighty confusing to users since it's not clear
> > that
> > adding a password will potentially invalidate a current password
> > (which
> > might be actively in use), but only if there are already 2 in the
> > stack.  I
> > worry that such a desіgn might be too closely tailored to the
> > implementation details.  If we proceed with this design, perhaps we
> > should
> > consider ERROR-ing if a user tries to add a third password.
>
> I agree that the proposed language is confusing, especially because ADD
> causes a password to be added and another one to be removed. But
> perhaps there are some non-confusing ways to expose a similar idea.

How about a language like the following (I haven't tried if this will
work in the grammar we have):

CREATE ROLE u1 PASSWORD 'p1';

ALTER ROLE u1ADD NEW PASSWORD 'p2';

ALTER ROLE u1 ADD NEW PASSOWRD 'p3';
ERROR: Cannot have more than 2 passwords at the same time.

ALTER ROLE u1 DROP OLD PASSWORD;

ALTER ROLE u1 ADD NEW PASSOWRD 'p3';
-- succeeds; forgets password 'p1'; p2 and p3 can be used to login

ALTER ROLE u1 DROP NEW PASSWORD;
-- forgets password 'p3'. Only 'p2' can be used to login

ALTER ROLE u1 ADD NEW PASSOWRD 'p4';
-- succeeds; 'p2' and 'p4' can be used to login

-- Set the valid-until of 'new' (p4) password
ALTER ROLE u1 VALID UNTIL '2024/01/01';

-- If we need the ability to change valid-until of both old and new,
we may allow something like the following.
ALTER ROLE u1 [_NEW_ | OLD] VALID UNTIL '2024/01/01';

This way there's a notion of a 'new' and 'old' passwords. User cannot
add a third password without explicitly dropping one of existing
passwords (either old or new). At any time the user can choose to drop
the old or the new password. Adding a new password will mark the
current password as 'old'; if there's only old password (because 'new'
was dropped) the 'old' password will remain intact and the new one
will be placed in 'current'/new spot.

So in normal course of operation, even for automated jobs, the
expected flow to roll over the passwords would be:

ALTER USER u1 DROP OLD PASSWORD;
-- success if there is an old password; otherwise NOTICE: no old password
ALTER USER u1 ADD NEW PASSWORD 'new-secret';

> The thing I like about Gurjeet's proposal is that it's well-targeted at
> a specific use case rather than trying to be too general. That makes it
> a little easier to avoid certain problems like having a process that
> adds passwords and never removes the old ones (leading to weird
> problems like 47000 passwords for one user).
>
> But it also feels strange to be limited to two -- perhaps the password
> rotation schedule or policy just doesn't work with a limit of two, or
> perhaps that introduces new kinds of mistakes.
>
> Another idea: what if we introduce the notion of deprecating a
> password?

I'll have to think more about it, but perhaps my above proposal
addresses the use case you describe.

> if we allow multiple deprecated passwords, we'd still have to come up
> with some way to address them (names, numbers, validity period,
> something). But by isolating the problem to deprecated passwords only,
> it feels like the system is still being restored to a clean state with
> at most one single current password. The awkwardness is contained to
> old passwords which will hopefully go away soon anyway and not
> represent permanent clutter.

+1

Best regards,
Gurjeet
http://Gurje.et




Re: [PoC/RFC] Multiple passwords, interval expirations

2023-10-08 Thread Gurjeet Singh
On Fri, Oct 6, 2023 at 1:46 PM Bruce Momjian  wrote:
>
> On Fri, Oct  6, 2023 at 01:20:03PM -0700, Jeff Davis wrote:
> > The basic problem, as I see it, is: how do we keep users from
> > accidentally dropping the wrong password? Generated unique names or
>
> I thought we could auto-remove old password if the valid-until date is
> in the past.

Autoremoving expired passwords will surprise users, and not in a good
way. Making a password, even an expired one, disappear from the system
will lead to astonishment. Among uses of an expired password are cases
of it acting like a tombstone, and the case where the user may want to
extend the validity of a password, instead of having to create a new
one and change application configuration(s) to specify the new
password.

Best regards,
Gurjeet
http://Gurje.et




Re: [PoC/RFC] Multiple passwords, interval expirations

2023-10-08 Thread Gurjeet Singh
On Sun, Oct 8, 2023 at 10:29 AM Bruce Momjian  wrote:
>
> I was speaking of autoremoving in cases where we are creating a new one,
> and taking the previous new one and making it the old one, if that was
> not clear.

Yes, I think I understood it differently. I understood it to mean that
this behaviour would apply to all passwords, those created by existing
commands, as well as to those created by new commands for rollover use
case. Whereas you meant this autoremove behaviour to apply only to
those passwords created by/for rollover related commands. I hope I've
understood your proposal correctly this time around :-)

I believe the passwords created by rollover feature should
behave by the same rules as the rules for passwords created by
existing CREATE/ALTER ROLE commands. If we implement the behaviour to
delete expired passwords, then I believe that behaviour should apply
to all passwords, irrespective of which command/feature was used to
create a password.


Best regards,
Gurjeet
http://Gurje.et




Re: [PoC/RFC] Multiple passwords, interval expirations

2023-10-08 Thread Gurjeet Singh
On Fri, Oct 6, 2023 at 1:29 PM Jeff Davis  wrote:
>
> On Thu, 2023-10-05 at 14:28 -0700, Gurjeet Singh wrote:
>
> > This way there's a notion of a 'new' and 'old' passwords.
>
> IIUC, you are proposing that there are exactly two slots, NEW and OLD.
> When adding a password, OLD must be unset and it moves NEW to OLD, and
> adds the new password in NEW. DROP only works on OLD. Is that right?

Yes, that's what I was proposing. But thinking a bit more about it,
the _implicit_ shuffling of labels 'new' and 'old' doesn't feel right
to me. The password that used to be referred to as 'new' now
automatically gets labeled 'old'.

> It's close to the idea of deprecation, except that adding a new
> password implicitly deprecates the existing one. I'm not sure about
> that -- it could be confusing.

+1

> We could also try using a verb like "expire" that could be coupled with
> a date, and that way all old passwords would always have some validity
> period.

Forcing the users to pick an expiry date for a password they intend to
rollover, when an expiry date did not exist before for that password,
feels like adding more burden to their password rollover decision
making. The dates and rules of password rollover may be a part of a
system external to their database, (wiki, docs, calendar, etc.) which
now they will be forced to translate into a timestamp to specify in
the rollover commands.

I believe we should fix the _names_ of the slots the 2 passwords are
stored in, and provide commands that manipulate those slots by
respective names; the commands should not implicitly move the
passwords between the slots. Additionally, we may provide functions
that provide observability info for these slots. I propose the slot
names FIRST and SECOND (I picked these because these keywords/tokens
already exist in the grammar, but not yet sure if the grammar rules
would allow their use; feel free to propose better names). FIRST
refers to the the existing slot, namely rolpassword. SECOND refers to
the new slot we'd add, that is, a pgauthid column named
rolsecondpassword. The existing commands, or when neither FIRST nor
SECOND are specified, the commands apply to the existing slot, a.k.a.
FIRST.

The user interface might look like the following:

-- Create a user, as usual
CREATE ROLE u1 PASSWORD 'p1' VALID UNTIL '2020/01/01';
-- This automatically occupies the 'first' slot

-- Add another password that the user can use for authentication.
ALTER ROLE u1 ADD SECOND PASSWORD 'p2' VALID UNTIL '2021/01/01';

-- Change both the passwords' validity independently; this solves the
-- problem with the previous '2-element stack' approach, where we
-- could not address the password at the bottom of the stack.
ALTER ROLE u1 SECOND PASSWORD VALID UNTIL '2022/01/01';

ALTER ROLE u1 [ [ FIRST ] PASSWORD ] VALID UNTIL '2022/01/01';

-- If, for some reason, the user wants to get rid of the latest password added.
ALTER ROLE u1 DROP SECOND PASSWORD;

-- Add a new password (p3) in 'second' slot
ALTER ROLE u1 ADD SECOND PASSWORD 'p3' VALID UNTIL '2023/01/01';

-- Attempting to add a password while the respective slot is occupied
-- results in error
ALTER ROLE u1 ADD [ [ FIRST ] PASSWORD ] 'p4' VALID UNTIL '2024/01/01';
ERROR: first password already exists

ALTER ROLE u1 ADD SECOND PASSWORD 'p4' VALID UNTIL '2024/01/01';
ERROR: second password already exists

-- Users can use this function to check whether a password slot is occupied
=> select password_exists('u1', 'first');
password_exists
-
t

=> select password_exists('u1', 'second');
password_exists
-
t

-- Remove all passwords from the role. Both, 'first' and 'second',
passwords are removed.
ALTER ROLE u1 DROP ALL PASSWORD;

Best regards,
Gurjeet
http://Gurje.et




Re: [PoC/RFC] Multiple passwords, interval expirations

2023-10-09 Thread Gurjeet Singh
On Sun, Oct 8, 2023 at 1:01 PM Gurjeet Singh  wrote:
>
> On Fri, Oct 6, 2023 at 1:29 PM Jeff Davis  wrote:
> >
> > On Thu, 2023-10-05 at 14:28 -0700, Gurjeet Singh wrote:
> >
> > > This way there's a notion of a 'new' and 'old' passwords.
> >
> > IIUC, you are proposing that there are exactly two slots, NEW and OLD.
> > When adding a password, OLD must be unset and it moves NEW to OLD, and
> > adds the new password in NEW. DROP only works on OLD. Is that right?
>
> Yes, that's what I was proposing. But thinking a bit more about it,
> the _implicit_ shuffling of labels 'new' and 'old' doesn't feel right
> to me. The password that used to be referred to as 'new' now
> automatically gets labeled 'old'.
>
> > It's close to the idea of deprecation, except that adding a new
> > password implicitly deprecates the existing one. I'm not sure about
> > that -- it could be confusing.
>
> +1

> I believe we should fix the _names_ of the slots the 2 passwords are
> stored in, and provide commands that manipulate those slots by
> respective names; the commands should not implicitly move the
> passwords between the slots. Additionally, we may provide functions
> that provide observability info for these slots. I propose the slot
> names FIRST and SECOND (I picked these because these keywords/tokens
> already exist in the grammar, but not yet sure if the grammar rules
> would allow their use; feel free to propose better names). FIRST
> refers to the the existing slot, namely rolpassword. SECOND refers to
> the new slot we'd add, that is, a pgauthid column named
> rolsecondpassword. The existing commands, or when neither FIRST nor
> SECOND are specified, the commands apply to the existing slot, a.k.a.
> FIRST.

Please see attached the patch that implements this proposal. The patch
is named password_rollover_v3.diff, breaking from the name
'multiple_passwords...', since this patch limits itself to address the
password-rollover feature.

The multiple_password* series of patches had removed a critical
functionality, which I believe is crucial from security perspective.
When a user does not exist, or has no passwords, or has passwords that
have expired, we must pretend to perform authentication (network
packet exchanges) as normally as possible, so that the absence of
user, or lack of (or expiration of) passwords is not revealed to an
attacker. I have restored the original behaviour in the
CheckPWChallengeAuth() function; see commit aba99df407 [2].

I looked for any existing keywords that may better fit the purpose of
naming the slots, better than FIRST and SECOND, but I could not find
any. Instead of DROP to remove the passwords, I tried DELETE and the
grammar/bison did not complain about it; so DELETE is an option, too,
but I feel DROP FIRST/SECOND/ALL PASSWORD is a better companion of ADD
FIRST/SECOND PASSWORD syntax, in the same vein as ADD/DROP COLUMN.

The doc changes are still missing, but the regression tests and the
comments therein should provide a good idea of the user interface of
this new feature. Documenting this behaviour in a succinct manner
feels difficult; so ideas welcome for how to inform the reader that
now a role is accompanied by two slots to store the passwords, and
that the old commands operate on the first slot, and to operate on the
second password slot one must use the new syntax. I guess it would be
best to start the relevant section with "To support gradual password
rollovers, Postgres provides the ability to store 2 active passwords
at the same time. The passwords are referred to as FIRST and SECOND
password. Each of these passwords can be changed independently, and
each of these can have an associated expiration time, if necessary."

Since these new commands are only available to ALTER ROLE (and not to
CREATE ROLE), the corresponding command doc page also needs to be
updated.

Next steps:
- Break the patch into a series of smaller patches.
- Add TAP tests (test the ability to actually login with these passwords)
- Add/update documentation
- Add more regression tests

The patch progress can be followed on the Git branch
password_rollover_v3 [1]. This branch begins uses
multiple_passwords_v4 as starting point, and removes unnecessary code
(commit 326f60225f [3])

The v1 (and tombstone of v2) patches of password_rollover never
finished as the consensus changed while they were in progress, but
they exist as sibling branches of the v3 branch.

[1]: https://github.com/gurjeet/postgres/commits/password_rollover_v3
[2]: 
https://github.com/gurjeet/postgres/commit/aba99df407a523357db2813f0eea0b45dbeb6006
[3]: 
https://github.com/gurjeet/postgres/commit/326f60225f0e660338fc9c276c8728dc10db435b


Best regards,
Gurjeet
http://Gurje.et


password_rollover_v3.diff
Description: Binary data


Re: [PoC/RFC] Multiple passwords, interval expirations

2023-10-09 Thread Gurjeet Singh
On Mon, Oct 9, 2023 at 2:31 AM Gurjeet Singh  wrote:
>
> Next steps:
> - Break the patch into a series of smaller patches.

Please see attached the same v3 patch, but now split into 3 separate
patches. Each patch in the series depends on the previous patch to
have been applied. I have made sure that each patch passes `make
check` individually.

First patch adds the two new columns, rolsecondpassword and
rolsecondvaliduntil to the pg_authid shared catalog. This patch also
updates the corresponding pg_authid.dat file to set these values to
null for the rows populated during bootstrap. Finally, it adds code to
CreateRole() to set these columns' values to NULL for a role being
created.

The second patch updates the password extraction, verification
functions as well as authentication functions to honor the second
password, if any. There is more detailed description in the commit
message/body of the patch.

The third patch adds the SQL support to the ALTER ROLE command which
allows manipulation of both, the rolpassword and rolsecondpassword,
columns and their respective expiration timestamps,
rol[second]validuntil. This patch also adds regression tests for the
new SQL command, demonstrating the use of the new grammar.

v3-0001-Add-new-columns-to-pg_authid.patch
v3-0002-Update-password-verification-infrastructure-to-ha.patch
v3-0003-Added-SQL-support-for-ALTER-ROLE-to-manage-two-pa.patch



Best regards,
Gurjeet
http://Gurje.et
From bc7c35e53e421157c9425c198bc2557ad118a650 Mon Sep 17 00:00:00 2001
From: Gurjeet Singh 
Date: Mon, 9 Oct 2023 11:36:05 -0700
Subject: [PATCH v3 1/3] Add new columns to pg_authid

Add two columns to pg_authid, namely rolsecondpassword and
rolsecondvaliduntil. These columns are added in preparation for the
password-rollover feature. These columns will store the hash and the
expiration time, repspectively, of a second password that the role can
use for login authentication.
---
 src/backend/commands/user.c   |  4 +++
 src/include/catalog/pg_authid.dat | 45 ---
 src/include/catalog/pg_authid.h   |  2 ++
 3 files changed, 36 insertions(+), 15 deletions(-)

diff --git a/src/backend/commands/user.c b/src/backend/commands/user.c
index ce77a055e5..0afaf74865 100644
--- a/src/backend/commands/user.c
+++ b/src/backend/commands/user.c
@@ -452,9 +452,13 @@ CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
 	else
 		new_record_nulls[Anum_pg_authid_rolpassword - 1] = true;
 
+	new_record_nulls[Anum_pg_authid_rolsecondpassword - 1] = true;
+
 	new_record[Anum_pg_authid_rolvaliduntil - 1] = validUntil_datum;
 	new_record_nulls[Anum_pg_authid_rolvaliduntil - 1] = validUntil_null;
 
+	new_record_nulls[Anum_pg_authid_rolsecondvaliduntil - 1] = true;
+
 	new_record[Anum_pg_authid_rolbypassrls - 1] = BoolGetDatum(bypassrls);
 
 	/*
diff --git a/src/include/catalog/pg_authid.dat b/src/include/catalog/pg_authid.dat
index 6b4a0d..b326e48376 100644
--- a/src/include/catalog/pg_authid.dat
+++ b/src/include/catalog/pg_authid.dat
@@ -23,76 +23,91 @@
   rolname => 'POSTGRES', rolsuper => 't', rolinherit => 't',
   rolcreaterole => 't', rolcreatedb => 't', rolcanlogin => 't',
   rolreplication => 't', rolbypassrls => 't', rolconnlimit => '-1',
-  rolpassword => '_null_', rolvaliduntil => '_null_' },
+  rolpassword => '_null_', rolvaliduntil => '_null_',
+  rolsecondpassword => '_null_', rolsecondvaliduntil => '_null_' },
 { oid => '6171', oid_symbol => 'ROLE_PG_DATABASE_OWNER',
   rolname => 'pg_database_owner', rolsuper => 'f', rolinherit => 't',
   rolcreaterole => 'f', rolcreatedb => 'f', rolcanlogin => 'f',
   rolreplication => 'f', rolbypassrls => 'f', rolconnlimit => '-1',
-  rolpassword => '_null_', rolvaliduntil => '_null_' },
+  rolpassword => '_null_', rolvaliduntil => '_null_',
+  rolsecondpassword => '_null_', rolsecondvaliduntil => '_null_' },
 { oid => '6181', oid_symbol => 'ROLE_PG_READ_ALL_DATA',
   rolname => 'pg_read_all_data', rolsuper => 'f', rolinherit => 't',
   rolcreaterole => 'f', rolcreatedb => 'f', rolcanlogin => 'f',
   rolreplication => 'f', rolbypassrls => 'f', rolconnlimit => '-1',
-  rolpassword => '_null_', rolvaliduntil => '_null_' },
+  rolpassword => '_null_', rolvaliduntil => '_null_',
+  rolsecondpassword => '_null_', rolsecondvaliduntil => '_null_' },
 { oid => '6182', oid_symb

Minor edit to src/bin/pg_upgrade/IMPLEMENTAION

2023-10-09 Thread Gurjeet Singh
The attached patch adds the word 'databases' to show that template0,
template1 and postgres are databases in a default installation.

Best regards,
Gurjeet
http://Gurje.et


pg_upgrade.implementation.diff
Description: Binary data


Re: pg_reload_conf() synchronously

2022-11-05 Thread Gurjeet Singh
On Sat, Nov 5, 2022 at 11:23 AM Andres Freund  wrote:
> > As far as I know, Gurjeet has been annoyed only with non-user-settable
> > GUCs for one connection (correct me of course), there was nothing
> > fancy with isolation tests, yet.  Not saying that this is useless for
> > isolation tests, this would have its cases for assumptions where
> > multiple GUCs need to be synced across multiple sessions, but it seems
> > to me that we have two different cases in need of two different
> > solutions.
>
> I didn't say we need to go for something more complete. Just that it's worth
> thinking about.

FWIW, I have considered a few different approaches, but all of them
were not only more work, they were fragile, and diffcult to prove
correctness of. For example, I thought of implementing DSM based
synchronisation between processes, so that the invoking backend can be
sure that _all_ children of Postmaster have processed the reload. But
that will run into problems as different backends get created, and as
they exit.

The invoking client may be interested in just client-facing backends
honoring the reload before moving on, so it would have to wait until
all the other backends finish their current command and return to the
main loop; but that may never happen, because one of the backends may
be processing a long-running query. Or, for some reason, the the
caller may be interested in only the autovacuum proccesses honoring
its reload request. So I thought about creating _classes_ of backends:
client-facing, other always-on children of Postmaster, BGWorkers, etc.
But that just makes the problem more difficult to solve.

I hadn't considered the possibilty of deadlocks that Tom raised, so
that's another downside of the other approaches.

The proposed patch solves a specific problem, that of a single backend
reloading conf before the next command, without adding any complexity
for any other cases. It sure is worth solving the case where a backend
waits for another backed(s) to process the conf files, but it will
have to be a separate solution, becuase it's much more difficult to
get it right.

Best regards,
Gurjeet
http://Gurje.et




Re: Named Operators

2023-01-20 Thread Gurjeet Singh
On Sat, Jan 14, 2023 at 6:14 AM Gurjeet Singh  wrote:
>
> I agree that an identifier _surrounded_ by the same token (e.g. #foo#)
> or the pairing token (e.g. {foo}) looks better aesthetically, so I am
> okay with any of the following variations of the scheme, as well:
>
> \#foo\#  (tested; works)
> \#foo#   (not tested; reduces ident length by 1)
>
> We can choose a different character, instead of #. Perhaps \{foo} !

Please find attached the patch that uses \{foo} styled Named
Operators. This is in line with Tom's reluctant hint at possibly using
curly braces as delimiter characters. Since the curly braces are used
by the SQL Specification for row pattern recognition, this patch
proposes escaping the first of the curly braces.

We can get rid of the leading backslash, if (a) we're confident that
SQL committee will not use curly braces anywhere else, and (b) if
we're confident that if/when Postgres supports Row Pattern Recognition
feature, we'll be able to treat curly braces inside the PATTERN clause
specially. Since both of those conditions are unlikely, I think we
must settle for the escaped-first-curly-brace style for the naming our
operators.

Keeping with the previous posts, here's a sample SQL script showing
what the proposed syntax will look like in action. Personally, I
prefer the \#foo style, since the \# prefix stands out among the text,
better than \{..} does, and because # character is a better signal of
an operator than {.

create operator \{add_point}
(function = box_add, leftarg = box, rightarg = point);
create table test(a box);
insert into test values('((0,0),(1,1))'), ('((0,0),(2,1))');
select a as original, a \{add_point} '(1,1)' as modified from test;
drop operator \{add_point}(box, point);

Best regards,
Gurjeet
http://Gurje.et
diff --git a/src/backend/catalog/pg_operator.c b/src/backend/catalog/pg_operator.c
index 1017f2eed1..c5b8562cb5 100644
--- a/src/backend/catalog/pg_operator.c
+++ b/src/backend/catalog/pg_operator.c
@@ -31,6 +31,7 @@
 #include "catalog/pg_type.h"
 #include "miscadmin.h"
 #include "parser/parse_oper.h"
+#include "parser/scansup.h"
 #include "utils/acl.h"
 #include "utils/builtins.h"
 #include "utils/lsyscache.h"
@@ -79,6 +80,10 @@ validOperatorName(const char *name)
 	if (len == 0 || len >= NAMEDATALEN)
 		return false;
 
+	/* Is this a Named Operator? */
+	if (validNamedOperator(name))
+		return true;
+
 	/* Can't contain any invalid characters */
 	/* Test string here should match op_chars in scan.l */
 	if (strspn(name, "~!@#^&|`?+-*/%<>=") != len)
diff --git a/src/backend/parser/scan.l b/src/backend/parser/scan.l
index db8b0fe8eb..8587b82c8d 100644
--- a/src/backend/parser/scan.l
+++ b/src/backend/parser/scan.l
@@ -379,6 +379,16 @@ self			[,()\[\].;\:\+\-\*\/\%\^\<\>\=]
 op_chars		[\~\!\@\#\^\&\|\`\?\+\-\*\/\%\<\>\=]
 operator		{op_chars}+
 
+/*
+ * Named Operators, e.g. \{foo}
+ *
+ * {namedopfailed*} are error rules to avoid scanner backup when
+ * {namedop} fails to match its trailing tokens.
+ */
+namedop			\\\{{identifier}\}
+namedopfailed1	\\\{{identifier}
+namedopfailed2	\\\{
+
 /*
  * Numbers
  *
@@ -768,6 +778,23 @@ other			.
 }
 <>	{ yyerror("unterminated dollar-quoted string"); }
 
+{namedop}		{
+	SET_YYLLOC();
+	if (yyleng >= NAMEDATALEN)
+		yyerror("operator name too long");
+	/* XXX Should we support double-quoted, case sensitive names? */
+	yylval->str = downcase_identifier(yytext, yyleng, false, false);
+	return Op;
+}
+
+{namedopfailed1}	{
+	yyerror("unexpected token");
+}
+
+{namedopfailed2}	{
+	yyerror("unexpected token");
+}
+
 {xdstart}		{
 	SET_YYLLOC();
 	BEGIN(xd);
diff --git a/src/backend/parser/scansup.c b/src/backend/parser/scansup.c
index 602108a40f..05c46ae09e 100644
--- a/src/backend/parser/scansup.c
+++ b/src/backend/parser/scansup.c
@@ -125,3 +125,70 @@ scanner_isspace(char ch)
 		return true;
 	return false;
 }
+
+/*
+ * validNamedOperator() -- return true if name adheres to the scanner rule
+ * {namedop}
+ */
+bool
+validNamedOperator(const char *name)
+{
+	size_t	len = strlen(name);
+	bool	valid_identifier;
+	char   *tmp;
+
+	if (len < 4 || len >= NAMEDATALEN)
+	   return false;
+
+	if (name[0] != '\\' || name[1] != '{' || name[len-1] != '}')
+		return false;
+
+	tmp = pstrdup(name);
+
+	// Disregard the delimiters
+	tmp[len-1] = '\0';
+	valid_identifier = validIdentifier(tmp + 2);
+	pfree(tmp);
+
+	return valid_identifier;
+}
+
+/*
+ * validIdentifier() -- return true if name adheres to the scanner rule
+ * {identifier}
+ *
+ * Note: this function does not check if the identifier length
+ * is less than NAMEDATALEN.
+ */
+bool
+validIdentifier(const char *name)
+{
+	uin

Re: Named Operators

2023-01-20 Thread Gurjeet Singh
On Fri, Jan 20, 2023 at 9:32 AM Ted Yu  wrote:
>
> Since `validIdentifier` doesn't modify the contents of `name` string, it 
> seems that there is no need to create `tmp` string in `validNamedOperator`.
> You can pass the start and end offsets into the string (name) as second and 
> third parameters to `validIdentifier`.

Thanks for reviewing the patch!

I was making a temporary copy of the string, since I had to modify it
before the validation, whereas the callee expects a `const char*`. I
agree that the same check can be done with more elegance, while
eliminating the temporary allocation. Please find the updated patch
attached.

Instead of passing the start and end of region I want to check, as
suggested, I'm now passing just the length of the string I want
validated. But I think that's for the better, since it now aligns with
the comment that validIdentifier() does not check if the passed string
is shorter than NAMEDATALEN.

Best regards,
Gurjeet
http://Gurje.et


named_operators_v4.patch
Description: Binary data


Re: generate_series for timestamptz and time zone problem

2023-01-29 Thread Gurjeet Singh
On Sat, Nov 12, 2022 at 10:44 AM Tom Lane  wrote:
> However, what it shouldn't be is part of this patch.  It's worth
> pushing it separately to have a record of that decision.  I've
> now done that, so you'll need to rebase to remove that delta.
>
> I looked over the v5 patch very briefly, and have two main
> complaints:
>
> * There's no documentation additions.  You can't add a user-visible
> function without adding an appropriate entry to func.sgml.
>
> * I'm pretty unimpressed with the whole truncate-to-interval thing
> and would recommend you drop it.  I don't think it's adding much
> useful functionality beyond what we can already do with the existing
> date_trunc variants; and the definition seems excessively messy
> (too many restrictions and special cases).

Please see attached v6 of the patch.

The changes since v5 are:
.) Rebased and resolved conflicts caused by commit 533e02e92.
.) Removed code and tests related to new date_trunc() functions, as
suggested by Tom.
.) Added 3 more variants to accompany with date_add(tstz, interval, zone).
date_add(tstz, interval)
date_subtract(tstz, interval)
date_subtract(tstz, interval, zone)

.) Eliminate duplication of code; use common function to implement
generate_series_timestamptz[_at_zone]() functions.
.) Fixed bug where in one of the new code paths,
generate_series_timestamptz_with_zone(),  did not perform
TIMESTAMP_NOT_FINITE() check.
.) Replaced some DirectFunctionCall?() with direct calls to the
relevant *_internal() function; should be better for performance.
.) Added documentation all 5 functions (2 date_add(), 2
date_subtract(), 1 overloaded version of generate_series()).

I'm not sure of the convention around authorship. But since this was
not an insignificant amount of work, would this patch be considered as
co-authored by Przemyslaw and myself? Should I add myself to Authors
field in the Commitfest app?

Hi Przemyslaw,

I started working on this patch based on Tom's review a few days
ago, since you hadn't responded in a while, and I presumed you're not
working on this anymore. I should've consulted with/notified you of my
intent before starting to work on it, to avoid duplication of work.
Sorry if this submission obviates any work you have in progress.
Please feel free to provide your feedback on the v6 of the patch.

Best regards,
Gurjeet
http://Gurje.et


generate_series_with_timezone.v6.patch
Description: Binary data


Re: generate_series for timestamptz and time zone problem

2023-01-30 Thread Gurjeet Singh
On Mon, Jan 30, 2023 at 4:07 PM Tom Lane  wrote:
> Gurjeet Singh  writes:
> > [ generate_series_with_timezone.v6.patch ]
>
> The cfbot isn't terribly happy with this.  It looks like UBSan
> is detecting some undefined behavior.  Possibly an uninitialized
> variable?

It was the classical case of out-of-bounds access. I was trying to
access 4th argument, even in the case where the 3-argument variant of
generate_series() was called.

Please see attached v7 of the patch. It now checks PG_NARGS() before
accessing the optional parameter.

This mistake would've been caught early if there were assertions
preventing access beyond the number of arguments passed to the
function. I'll send the assert_enough_args.patch, that adds these
checks, in a separate thread to avoid potentially confusing cfbot.

Best regards,
Gurjeet
http://Gurje.et
diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index e09e289a43..aa15407936 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -9231,6 +9231,22 @@ SELECT regexp_match('abc01234xyz', '(?:(.*?)(\d+)(.*)){1,1}');
 

 
+   
+
+ date_add ( timestamp with time zone, interval , text  )
+ timestamp with time zone
+
+
+ Add interval to a timestamp with time zone value,
+ at the time zone specified by the third parameter. The time zone value
+ defaults to current  setting.
+
+
+ date_add('2021-10-31 00:00:00+02'::timestamptz, '1 day'::interval, 'Europe/Warsaw')
+ 2021-10-31 23:00:00
+
+   
+

 
  date_bin ( interval, timestamp, timestamp )
@@ -9278,6 +9294,22 @@ SELECT regexp_match('abc01234xyz', '(?:(.*?)(\d+)(.*)){1,1}');
 

 
+   
+
+ date_subtract ( timestamp with time zone, interval , text  )
+ timestamp with time zone
+
+
+ Subtract interval from a timestamp with time zone value,
+ at the time zone specified by the third parameter. The time zone value
+ defaults to the current  setting.
+
+
+ date_subtract('2021-10-31 00:00:00+02'::timestamptz, '1 day'::interval, 'Europe/Warsaw')
+ 2021-10-29 22:00:00
+
+   
+

 
  
@@ -21968,13 +22000,14 @@ AND
 setof timestamp


-generate_series ( start timestamp with time zone, stop timestamp with time zone, step interval )
+generate_series ( start timestamp with time zone, stop timestamp with time zone, step interval , timezone text  )
 setof timestamp with time zone


 Generates a series of values from start
 to stop, with a step size
-of step.
+of step. timezone
+defaults to the current  setting.

   
  
diff --git a/src/backend/utils/adt/timestamp.c b/src/backend/utils/adt/timestamp.c
index 47e059a409..bd85f6421e 100644
--- a/src/backend/utils/adt/timestamp.c
+++ b/src/backend/utils/adt/timestamp.c
@@ -69,6 +69,7 @@ typedef struct
 	TimestampTz finish;
 	Interval	step;
 	int			step_sign;
+	pg_tz	   *attimezone;
 } generate_series_timestamptz_fctx;
 
 
@@ -78,6 +79,8 @@ static bool AdjustIntervalForTypmod(Interval *interval, int32 typmod,
 	Node *escontext);
 static TimestampTz timestamp2timestamptz(Timestamp timestamp);
 static Timestamp timestamptz2timestamp(TimestampTz timestamp);
+static pg_tz* lookup_timezone(text *zone);
+static Datum generate_series_timestamptz_internal(FunctionCallInfo fcinfo);
 
 
 /* common code for timestamptypmodin and timestamptztypmodin */
@@ -550,6 +553,54 @@ parse_sane_timezone(struct pg_tm *tm, text *zone)
 	return tz;
 }
 
+/*
+ * Look up the requested timezone (see notes in timestamptz_zone()).
+ */
+static pg_tz *
+lookup_timezone(text *zone)
+{
+	char		tzname[TZ_STRLEN_MAX + 1];
+	char	   *lowzone;
+	int			type,
+dterr,
+val;
+	pg_tz	   *tzp;
+
+	DateTimeErrorExtra extra;
+
+	text_to_cstring_buffer(zone, tzname, sizeof(tzname));
+
+	/* DecodeTimezoneAbbrev requires lowercase input */
+	lowzone = downcase_truncate_identifier(tzname,
+		   strlen(tzname),
+		   false);
+
+	dterr = DecodeTimezoneAbbrev(0, lowzone, &type, &val, &tzp, &extra);
+	if (dterr)
+		DateTimeParseError(dterr, &extra, NULL, NULL, NULL);
+
+	if (type == TZ || type == DTZ)
+	{
+		/* fixed-offset abbreviation, get a pg_tz descriptor for that */
+		tzp = pg_tzset_offset(-val);
+	}
+	else if (type == DYNTZ)
+	{
+		/* dynamic-offset abbreviation, use its referenced timezone */
+	}
+	else
+	{
+		/* try it as a full zone name */
+		tzp = pg_tzset(tzname);
+		if (!tzp)
+			ereport(ERROR,
+	(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+	 errmsg("time zone \"%s\" not recognized", tzname)));

Assert fcinfo has enough args before allowing parameter access (was: Re: generate_series for timestamptz and time zone problem)

2023-01-30 Thread Gurjeet Singh
On Mon, Jan 30, 2023 at 11:50 PM Gurjeet Singh  wrote:
> It was the classical case of out-of-bounds access.

> This mistake would've been caught early if there were assertions
> preventing access beyond the number of arguments passed to the
> function. I'll send the assert_enough_args.patch, that adds these
> checks, in a separate thread to avoid potentially confusing cfbot.

Please see attached the patch to that ensures we don't accidentally
access more parameters than that are passed to a SQL callable
function.

Best regards,
Gurjeet
http://Gurje.et
diff --git a/src/include/fmgr.h b/src/include/fmgr.h
index b120f5e7fe..a445ac56b9 100644
--- a/src/include/fmgr.h
+++ b/src/include/fmgr.h
@@ -206,7 +206,7 @@ extern void fmgr_symbol(Oid functionId, char **mod, char **fn);
  * If function is not marked "proisstrict" in pg_proc, it must check for
  * null arguments using this macro.  Do not try to GETARG a null argument!
  */
-#define PG_ARGISNULL(n)  (fcinfo->args[n].isnull)
+#define PG_ARGISNULL(n)  (AssertMacro(n < PG_NARGS()), fcinfo->args[n].isnull)
 
 /*
  * Support for fetching detoasted copies of toastable datatypes (all of
@@ -265,7 +265,7 @@ extern struct varlena *pg_detoast_datum_packed(struct varlena *datum);
 
 /* Macros for fetching arguments of standard types */
 
-#define PG_GETARG_DATUM(n)	 (fcinfo->args[n].value)
+#define PG_GETARG_DATUM(n)	 (AssertMacro(n < PG_NARGS()), fcinfo->args[n].value)
 #define PG_GETARG_INT32(n)	 DatumGetInt32(PG_GETARG_DATUM(n))
 #define PG_GETARG_UINT32(n)  DatumGetUInt32(PG_GETARG_DATUM(n))
 #define PG_GETARG_INT16(n)	 DatumGetInt16(PG_GETARG_DATUM(n))


pg_reload_conf() synchronously

2022-11-04 Thread Gurjeet Singh
In an internal conversation it was seen that for some tests that want
to enforce a behaviour, a behaviour that is controlled by a GUC, we
_need_ to perform a sleep for an arbitrary amount of time.
Alternatively, executing the rest of the test on a new connection also
helps to get the expected behaviour. Following is a sample snippet of
such a test.

ALTER SYSTEM SET param TO value;
SELECT pg_reload_conf();
-- Either pg_sleep(0.1) or \connect here for next command to behave as expected.
ALTER ROLE ... PASSWORD '...';

This is because of the fact that the SIGHUP, sent to Postmaster by
this backend, takes some time to get back to the issuing backend.

Although a pg_sleep() call works to alleviate the pain in most cases,
it does not provide any certainty. Following the Principle Of Least
Astonishment, we want a command that loads the configuration
_synchronously_, so that the subsequent commands from the client can
be confident that the requisite parameter changes have taken effect.

The attached patch makes the pg_reload_conf() function set
ConfigReloadPending to true, which will force the postgres main
command-processing loop to process and apply config changes _before_
executing the next command.

The only downside I can think of this approach is that it _might_
cause the issuing backend to process the config file twice; once after
it has processed the current command, and another time when the SIGHUP
signal comes from the Postmaster. If the SIGHUP signal from the
Postmaster comes before the end of current command, then the issuing
backend will process the config only once, as before the patch. In any
case, this extra processing of the config seems harmless, and the
benefit outweighs the extra processing done.

The alternate methods that I considered (see branch reload_my_conf at
[2])  were to either implement the SQL command RELOAD CONFIGURATION [
FOR ALL ], or to create an overloaded version of function
pg_reload_conf(). But both those approaches had much more significant
downsides, like additional GRANTs, etc.

There have been issues identified in the past (see [1]) that possibly
may be alleviated by this approach of applying config changes
synchronously.

[1]: https://www.postgresql.org/message-id/2138662.1623460441%40sss.pgh.pa.us
[2]: https://github.com/gurjeet/postgres/tree/reload_my_conf

Best regards,
Gurjeet
http://Gurje.et


reload_conf_synchronouly.patch
Description: Binary data


Automatic notification for top transaction IDs

2021-06-22 Thread Gurjeet Singh
I came across this thread [1] to disallow canceling a transaction not
yet confirmed by a synchronous replica. I think my proposed patch
might help that case as well, hence adding all involved in that thread
to BCC, for one-time notification.

As mentioned in that thread, when sending a cancellation signal, the
client cannot be sure if the cancel signal was honored, and if the
transaction was cancelled successfully. In the attached patch, the
backend emits a NotificationResponse containing the current full
transaction id. It does so only if the relevant GUC is enabled, and
when the top-transaction is being assigned the ID.

This information can be useful to the client, when:
i) it wants to cancel a transaction _after_ issuing a COMMIT, and
ii) it wants to check the status of its transaction that it sent
COMMIT for, but never received a response (perhaps because the server
crashed).

Additionally, this information can be useful for middleware, like
Transaction Processing Monitors, which can now transparently (without
any change in application code) monitor the status of transactions (by
watching for the transaction status indicator in the ReadyForQuery
protocol message). They can use the transaction ID from the
NotificationResponse to open a watcher, and on seeing either an 'E' or
'I' payload in subsequent ReadyForQuery messages, close the watcher.
On server crash, or other adverse events, they can then use the
transaction IDs still being watched to check status of those
transactions, and take appropriate actions, e.g. retry any aborted
transactions.

We cannot use the elog() mechanism for this notification because it is
sensitive to the value of client_min_messages. Hence I used the NOTIFY
infrastructure for this message. I understand that this usage violates
some expectations as to how NOTIFY messages are supposed to behave
(see [2] below), but I think these are acceptable violations; open to
hearing if/why this might not be acceptable, and any possible
alternatives.

I'm not very familiar with the parallel workers infrastructure, so the
patch is missing any consideration for those.

Reviews welcome.

[1]: subject was: Re: Disallow cancellation of waiting for synchronous
replication
thread: 
https://www.postgresql.org/message-id/flat/C1F7905E-5DB2-497D-ABCC-E14D4DEE506C%40yandex-team.ru

[2]:
 At present, NotificationResponse can only be sent outside a
 transaction, and thus it will not occur in the middle of a
 command-response series, though it might occur just before ReadyForQuery.
 It is unwise to design frontend logic that assumes that, however.
 Good practice is to be able to accept NotificationResponse at any
 point in the protocol.

Best regards,
--
Gurjeet Singh http://gurjeet.singh.im/


notify_xid.patch
Description: Binary data


Automatic notification of top transaction IDs

2021-06-30 Thread Gurjeet Singh
(Re-sending this email, because the Commitfest app mistakenly [3]
considered previous email [4] to be part of the old thread, whereas it
should not be considered that way)

I came across this thread [1] to disallow canceling a transaction not
yet confirmed by a synchronous replica. I think my proposed patch
might help that case as well, hence adding all involved in that thread
to BCC, for one-time notification.

As mentioned in that thread, when sending a cancellation signal, the
client cannot be sure if the cancel signal was honored, and if the
transaction was cancelled successfully. In the attached patch, the
backend emits a NotificationResponse containing the current full
transaction id. It does so only if the relevant GUC is enabled, and
when the top-transaction is being assigned the ID.

This information can be useful to the client, when:
i) it wants to cancel a transaction _after_ issuing a COMMIT, and
ii) it wants to check the status of its transaction that it sent
COMMIT for, but never received a response (perhaps because the server
crashed).

Additionally, this information can be useful for middleware, like
Transaction Processing Monitors, which can now transparently (without
any change in application code) monitor the status of transactions (by
watching for the transaction status indicator in the ReadyForQuery
protocol message). They can use the transaction ID from the
NotificationResponse to open a watcher, and on seeing either an 'E' or
'I' payload in subsequent ReadyForQuery messages, close the watcher.
On server crash, or other adverse events, they can then use the
transaction IDs still being watched to check status of those
transactions, and take appropriate actions, e.g. retry any aborted
transactions.

We cannot use the elog() mechanism for this notification because it is
sensitive to the value of client_min_messages. Hence I used the NOTIFY
infrastructure for this message. I understand that this usage violates
some expectations as to how NOTIFY messages are supposed to behave
(see [2] below), but I think these are acceptable violations; open to
hearing if/why this might not be acceptable, and any possible
alternatives.

I'm not very familiar with the parallel workers infrastructure, so the
patch is missing any consideration for those.

Reviews welcome.

[1]: subject was: Re: Disallow cancellation of waiting for synchronous
replication
thread: 
https://www.postgresql.org/message-id/flat/C1F7905E-5DB2-497D-ABCC-E14D4DEE506C%40yandex-team.ru

[2]:
 At present, NotificationResponse can only be sent outside a
 transaction, and thus it will not occur in the middle of a
 command-response series, though it might occur just before ReadyForQuery.
 It is unwise to design frontend logic that assumes that, however.
 Good practice is to be able to accept NotificationResponse at any
 point in the protocol.

[3]:

See Emails section in https://commitfest.postgresql.org/33/3198/

The email [4] is considered a continuation of a previous thread, _and_
the 'Latest attachment' entry points to a different email, even though
my email [4] contained a patch.

[4]: 
https://www.postgresql.org/message-id/CABwTF4VS+HVm11XRE_Yv0vGmG=5kpYdx759RyJEp9F+fiLTU=q...@mail.gmail.com

Best regards,
--
Gurjeet Singh http://gurjeet.singh.im/




Re: Automatic notification of top transaction IDs

2021-06-30 Thread Gurjeet Singh
The proposed patch is attached.

Best regards,
--
Gurjeet Singh http://gurjeet.singh.im/

On Wed, Jun 30, 2021 at 5:56 PM Gurjeet Singh  wrote:
>
> (Re-sending this email, because the Commitfest app mistakenly [3]
> considered previous email [4] to be part of the old thread, whereas it
> should not be considered that way)
>
> I came across this thread [1] to disallow canceling a transaction not
> yet confirmed by a synchronous replica. I think my proposed patch
> might help that case as well, hence adding all involved in that thread
> to BCC, for one-time notification.
>
> As mentioned in that thread, when sending a cancellation signal, the
> client cannot be sure if the cancel signal was honored, and if the
> transaction was cancelled successfully. In the attached patch, the
> backend emits a NotificationResponse containing the current full
> transaction id. It does so only if the relevant GUC is enabled, and
> when the top-transaction is being assigned the ID.
>
> This information can be useful to the client, when:
> i) it wants to cancel a transaction _after_ issuing a COMMIT, and
> ii) it wants to check the status of its transaction that it sent
> COMMIT for, but never received a response (perhaps because the server
> crashed).
>
> Additionally, this information can be useful for middleware, like
> Transaction Processing Monitors, which can now transparently (without
> any change in application code) monitor the status of transactions (by
> watching for the transaction status indicator in the ReadyForQuery
> protocol message). They can use the transaction ID from the
> NotificationResponse to open a watcher, and on seeing either an 'E' or
> 'I' payload in subsequent ReadyForQuery messages, close the watcher.
> On server crash, or other adverse events, they can then use the
> transaction IDs still being watched to check status of those
> transactions, and take appropriate actions, e.g. retry any aborted
> transactions.
>
> We cannot use the elog() mechanism for this notification because it is
> sensitive to the value of client_min_messages. Hence I used the NOTIFY
> infrastructure for this message. I understand that this usage violates
> some expectations as to how NOTIFY messages are supposed to behave
> (see [2] below), but I think these are acceptable violations; open to
> hearing if/why this might not be acceptable, and any possible
> alternatives.
>
> I'm not very familiar with the parallel workers infrastructure, so the
> patch is missing any consideration for those.
>
> Reviews welcome.
>
> [1]: subject was: Re: Disallow cancellation of waiting for synchronous
> replication
> thread: 
> https://www.postgresql.org/message-id/flat/C1F7905E-5DB2-497D-ABCC-E14D4DEE506C%40yandex-team.ru
>
> [2]:
>  At present, NotificationResponse can only be sent outside a
>  transaction, and thus it will not occur in the middle of a
>  command-response series, though it might occur just before ReadyForQuery.
>  It is unwise to design frontend logic that assumes that, however.
>  Good practice is to be able to accept NotificationResponse at any
>  point in the protocol.
>
> [3]:
>
> See Emails section in https://commitfest.postgresql.org/33/3198/
>
> The email [4] is considered a continuation of a previous thread, _and_
> the 'Latest attachment' entry points to a different email, even though
> my email [4] contained a patch.
>
> [4]: 
> https://www.postgresql.org/message-id/CABwTF4VS+HVm11XRE_Yv0vGmG=5kpYdx759RyJEp9F+fiLTU=q...@mail.gmail.com
>
> Best regards,
> --
> Gurjeet Singh http://gurjeet.singh.im/


notify_xid.patch
Description: Binary data


Slightly improve initdb --sync-only option's help message

2021-07-06 Thread Gurjeet Singh
When reading the output of `initdb --help` I could not clearly
understand what the purpose of the --sync-only option was, until I
read the documentation of initdb.

  -S, --sync-only   only sync data directory

Perhaps the confusion was caused by the fact that sync(hronization)
means different things in different contexts, and many of those
contexts apply to databases, and to data directories; time sync, data
sync, replica sync, etc.

I think it would be helpful if the help message was slightly more
descriptive. Some options:

Used in patch:
 only sync data directory; does not modify any data

To match the wording of --sync-only option:
write contents of data directory to disk; helpful after --no-sync option

Clearly specify the system operation used for the option
perform fsync on data directory; helpful after --no-sync option

Best regards,
--
Gurjeet Singh http://gurjeet.singh.im/


v1-0001-Explicitly-state-that-sync-only-does-not-modify-d.patch
Description: Binary data


Warn if initdb's --sync-only option is mixed with other options

2021-07-06 Thread Gurjeet Singh
When reading through code for my previous patch [1] I realized that
initdb does *not* warn users that it ignores all other options (except
-D/--pgdata) if the --sync-only option is used.

I'm not able to come up with an exact situation to prove this, but
this behaviour seems potentially dangerous. The user might mix the
--sync-only option with other options, but would be extremely
surprised if those other options didn't take effect.

I _think_ we should throw an error if the user specifies any options
that are being ignored. But an error might break someone's automation
(perhaps for their own good), since the current behaviour has been in
place for a very long time, so I'm willing to settle for at least a
warning in such a case.

[1]:
Slightly improve initdb --sync-only option's help message
https://www.postgresql.org/message-id/CABwTF4U6hbNNE1bv%3DLxQdJybmUdZ5NJQ9rKY9tN82NXM8QH%2BiQ%40mail.gmail.com

Best regards,
--
Gurjeet Singh http://gurjeet.singh.im/


v1-0001-Warn-if-sync-only-is-used-with-other-options.patch
Description: Binary data


Patch: Don't set LoadedSSL unless secure_initialize succeeds

2022-05-21 Thread Gurjeet Singh
The initialization in PostmasterMain() blindly turns on LoadedSSL,
irrespective of the outcome of secure_initialize(). I don't think
that's how it should behave, primarily because of the pattern followed
by the other places that call secure_initialize().

This patch makes PostmasterMain() behave identical to other places
(SIGHUP handler, and SubPostmasterMain()) where LoadedSSL is turned on
after checking success of secure_initialize() call. Upon failure of
secure_initialize(), it now emits a log message, instead of setting
LoadedSSL to true.

Best regards,
Gurjeet
http://Gurje.et


LoadedSSL.patch
Description: Binary data


Re: Patch: Don't set LoadedSSL unless secure_initialize succeeds

2022-05-25 Thread Gurjeet Singh
On Sun, May 22, 2022 at 12:17 AM Daniel Gustafsson  wrote:
> > On 22 May 2022, at 08:41, Gurjeet Singh  wrote:
>
> > The initialization in PostmasterMain() blindly turns on LoadedSSL,
> > irrespective of the outcome of secure_initialize().
>
> This call is invoked with isServerStart set to true so any error in
> secure_initialize should error out with ereport FATAL (in be_tls_init()).  
> That
> could be explained in a comment though, which is currently isn't.

That makes sense. I have attached a patch that adds a couple of lines
of comments explaining this at call-site.

> Did you manage to get LoadedSSL set to true without SSL having been properly
> initialized?

Fortunately, no. I'm trying to add a new network protocol, and caught
this inconsistency while reading/adapting the code.

If a committer sees some value in it, in the attached patch I have
also attempted to improve the readability of the code a little bit in
startup-packet handling, and in SSL functions. These are purely
cosmetic changes, but I think they reduce repetition, and improve
readability, by quite a bit. For example, every ereport call evaluates
the same 'isServerStart ? FATAL : LOG', over and over again; replacing
this with variable 'logLevel' reduces cognitive load for the reader.
And I've replace one 'goto retry1' with a 'while' loop, like the
GASSAPI does it below that occurrence.

There's an symmetry, almost a diametric opposition, between how SSL
initialization error is treated when it occurs during server startup,
versus when the error occurs during a reload/SIGHUP. During startup an
error in SSL initialization leads to FATAL, whereas during a SIGHUP
it's merely a LOG message.

I found this difference in treatment of SSL initialization errors
quite bothersome, and there is no ready explanation for this. Either a
properly initialized SSL stack is important for server operation, or
it is not. What do we gain by letting the server operate normally
after a reload that failed to initialize SSL stack. Conversely, why do
we kill the server during startup on SSL initialization error, when
it's okay to operate normally after a reload that is unable to
initialize SSL.

I have added a comment to be_tls_init(), which I hope explains this
difference in treatment of errors. I have also added comments to
be_tls_init(), explaining why we don't destroy/free the global
SSL_context variable in case of an error in re-initialization of SSL;
it's not just an optimization, it's essential to normal server
operation.

Best regards,
Gurjeet
http://Gurje.et


readability_improvements-ssl-startup_packet.patch
Description: Binary data


Re: Patch: Don't set LoadedSSL unless secure_initialize succeeds

2022-05-25 Thread Gurjeet Singh
On Mon, May 23, 2022 at 8:51 PM Tom Lane  wrote:
>
> Daniel Gustafsson  writes:
> >> On 22 May 2022, at 08:41, Gurjeet Singh  wrote:
> >> The initialization in PostmasterMain() blindly turns on LoadedSSL,
> >> irrespective of the outcome of secure_initialize().
>
> > This call is invoked with isServerStart set to true so any error in
> > secure_initialize should error out with ereport FATAL (in be_tls_init()).  
> > That
> > could be explained in a comment though, which is currently isn't.
>
> The comments for secure_initialize() and be_tls_init() both explain
> this already.

The comments above secure_initialize() do, but there are no comments
above be_tls_init(), and nothing in there attempts to explain the
FATAL vs. LOG difference.

I think it doesn't hurt, and may actively help, if we add a comment at
the call-site just alluding to the fact that the function call will
not return in case of an error, and that it's safe to assume certain
state has been initialized if the function returns.

The comments *inside* be_tls_init() attempt to explain allocation of a
new SSL_context, but end up making it sound like it's an optimization
to prevent memory leak. In the patch proposed a few minutes ago in
this thread, I have tried to explain above be_tls_init() the error
handling  behavior, as well as the reason to retain the active
SSL_context, if any.

> It's not great that be_tls_init() implements two different error
> handling behaviors, perhaps.  One could imagine separating those.
> But we've pretty much bought into such messes with the very fact
> that elog/ereport sometimes return and sometimes not.

I don't find the dual mode handling startling; I feel it's common in
Postgres code, but it's been a while since I've touched it.

What I would love to see improved around ereport() calls in SSL
functions would be to shrink the 'ereport(); goto error;' pattern into
one statement, so that we don't introduce an accidental "goto fail"
bug [1].

[1]: 
https://nakedsecurity.sophos.com/2014/02/24/anatomy-of-a-goto-fail-apples-ssl-bug-explained-plus-an-unofficial-patch/

Best regards,
Gurjeet
http://Gurje.et




Re: Patch: Don't set LoadedSSL unless secure_initialize succeeds

2022-05-25 Thread Gurjeet Singh
On Wed, May 25, 2022 at 10:05 PM Gurjeet Singh  wrote:
> I have added a comment to be_tls_init(), which I hope explains this
> difference in treatment of errors. I have also added comments to
> be_tls_init(), explaining why we don't destroy/free the global
> SSL_context variable in case of an error in re-initialization of SSL;
> it's not just an optimization, it's essential to normal server
> operation.

Please see attached patch that reverts the unintentional removal of a
comment in be_tls_init(). Forgot to put that comment back in after my
edits.

Best regards,
Gurjeet
http://Gurje.et


revert-unintentional-deletion.patch
Description: Binary data


Re: Patch: Don't set LoadedSSL unless secure_initialize succeeds

2022-05-26 Thread Gurjeet Singh
On Thu, May 26, 2022 at 12:16 PM Tom Lane  wrote:
> Gurjeet Singh  writes:
> > On Mon, May 23, 2022 at 8:51 PM Tom Lane  wrote:
> >> The comments for secure_initialize() and be_tls_init() both explain
> >> this already.
>
> > The comments above secure_initialize() do, but there are no comments
> > above be_tls_init(), and nothing in there attempts to explain the
> > FATAL vs. LOG difference.
>
> I was looking at the comments in libpq-be.h:
>
> /*
>  * Initialize global SSL context.
>  *
>  * If isServerStart is true, report any errors as FATAL (so we don't return).
>  * Otherwise, log errors at LOG level and return -1 to indicate trouble,
>  * preserving the old SSL state if any.  Returns 0 if OK.
>  */
> extern int  be_tls_init(bool isServerStart);
>
> It isn't our usual practice to put such API comments with the extern
> rather than the function definition,

Yep, and I didn't notice these comments, or even bothered to look at
the extern declaration, precisely because my knowledge of Postgres
coding convention told me the comments are supposed to be on the
function definition.

> so maybe those comments in libpq-be.h
> should be moved to their respective functions?  In any case, I'm not
> excited about having three separate comments covering the same point.

By 3 locations, I suppose you're referring to the definition of
secure_initialize(), extern declaration of be_tls_init(), and the
definition of be_tls_init().

The comment on the extern declaration does not belong there, so that
one definitely needs go. The other two locations need descriptive
comments, even if they might sound duplicate. Because the one on
secure_initialize() describes the abstraction's expectations, and the
one on be_tls_init() should refer to it, and additionally mention any
implementation details.


Best regards,
Gurjeet
http://Gurje.et




Re: Patch: Don't set LoadedSSL unless secure_initialize succeeds

2022-05-26 Thread Gurjeet Singh
On Thu, May 26, 2022 at 1:00 PM Robert Haas  wrote:
>
> On Thu, May 26, 2022 at 1:05 AM Gurjeet Singh  wrote:
> > There's an symmetry, almost a diametric opposition, between how SSL

I meant "an asymmetry".

> > initialization error is treated when it occurs during server startup,
> > versus when the error occurs during a reload/SIGHUP. During startup an
> > error in SSL initialization leads to FATAL, whereas during a SIGHUP
> > it's merely a LOG message.
> >
> > I found this difference in treatment of SSL initialization errors
> > quite bothersome, and there is no ready explanation for this. Either a
> > properly initialized SSL stack is important for server operation, or
> > it is not. What do we gain by letting the server operate normally
> > after a reload that failed to initialize SSL stack. Conversely, why do
> > we kill the server during startup on SSL initialization error, when
> > it's okay to operate normally after a reload that is unable to
> > initialize SSL.
>
> I think you're overreacting to a behavior that isn't really very surprising.

The behaviour is not surprising. I developed those opposing views as I
was reading the code. And I understood the behaviour after I was done
reading the code. But I was irked that it wasn't clearly explained
somewhere nearby in code. Hence my proposal:

> > I have added a comment to be_tls_init(), which I hope explains this
> > difference in treatment of errors.

> So I don't really know what behavior, other than what is actually
> implemented, would be reasonable.

I just wasn't happy about the fact that I had wasted time trying to
find holes (security holes!) in the behaviour. So my proposal is to
improve the docs/comments about this behaviour, and not the behaviour
itself.

Best regards,
Gurjeet
http://Gurje.et




Re: Patch: Don't set LoadedSSL unless secure_initialize succeeds

2022-05-26 Thread Gurjeet Singh
On Thu, May 26, 2022 at 2:40 PM Tom Lane  wrote:
>
> Robert Haas  writes:
> > I think you're overreacting to a behavior that isn't really very surprising.
>
> > If we don't initialize SSL the first time, we don't have a working SSL
> > stack. If we didn't choose to die at that point, we'd be starting up a
> > server that could not accept any SSL connections. I don't think users
> > would like that.
>
> > If we don't *reinitialize* it, we *do* have a working SSL stack. We
> > haven't been able to load the updated configuration, but we still have
> > the old one. We could fall over and die anyway, but I don't think
> > users would like that either. People don't expect 'pg_ctl reload' to
> > kill off a working server, even if the new configuration is bad.
>
> The larger context here is that this is (or at least is supposed to be)
> exactly the same as our reaction to any other misconfiguration: die if
> it's detected at server start, but if it's detected during a later SIGHUP
> reload, soldier on with the known-good previous settings.  I believe
> that's fairly well documented already.

This distinction (of server startup vs. reload) is precisely what I
think should be conveyed and addressed in the comments of functions
responsible for (re)initialization of resources. Such a comment,
specifically calling out processing/logging/error-handling differences
between startup and reload, would've definitely helped when I was
trying to understand the code, and trying to figure out the different
contexts these functions may be executed in. The fact that
ProcessStartupPacket() function calls these functions, and then also
calls itself recursively, made understanding the code and intent much
harder.

And since variable/parameter/function names also convey intent, their
naming should also be as explicit as possible, rather than being
vague.

Calling variables/parameters 'isServerStart' leaves so much to
interpretation; how many and what other cases is the code called in
when isServerStart == false? I think a better scheme would've been to
name the parameter as 'reason', and use an enum/constant to convey
that there are exactly 2 higher-level cases that the code is called in
context of: enum InitializationReason { ServerStartup, ServerReload }.

In these functions, it's not important to know the distinction of
whether the server is starting-up vs. already running (or whatever
other states the server may be in) , instead it's important to know
the distinction of whether the server is starting-up or being
reloaded; other states of the server operation, if any, do not matter
here.

Best regards,
Gurjeet
http://Gurje.et




Re: Patch: Don't set LoadedSSL unless secure_initialize succeeds

2022-05-26 Thread Gurjeet Singh
On Thu, May 26, 2022 at 4:13 PM Tom Lane  wrote:
> Gurjeet Singh  writes:
> > On Thu, May 26, 2022 at 12:16 PM Tom Lane  wrote:
> >> so maybe those comments in libpq-be.h
> >> should be moved to their respective functions?  In any case, I'm not
> >> excited about having three separate comments covering the same point.
>
> > By 3 locations, I suppose you're referring to the definition of
> > secure_initialize(), extern declaration of be_tls_init(), and the
> > definition of be_tls_init().
>
> No, I was counting the third comment as the one you proposed to add to
> secure_initialize's caller.

I think a comment at that call-site is definitely warranted. Consider
the code as it right now...

if (EnableSSL)
{
(void) secure_initialize(true);
LoadedSSL = true;
}

... as a first-time reader.

Reader> This is an important piece of code, not just because it is
called from PostmasterMain(), early in the startup process, but also
because it deals with SSL; it has 'SSL' and 'secure' plastered all
over it. But wait, they don't care what the outcome of this important
function call is??!! I might not have paid much attention to it, but
the call is adorned with '(void)', which (i) attracts my attention
more, and (ii) why are they choosing to throw away the result of such
important function call?! And then, they declare SSL has been
"Loaded"... somebody committed half-written code! Perhaps they we in a
hurry. Perhaps this is a result of an automatic git-merge gone wrong.
Let me dig through the code and see if I can find a vulnerability.
 Duh, there's nothing wrong here. .

Now, consider the same code, and the ensuing thought-process of the reader:

if (EnableSSL)
{
/* Any failure during SSL initialization here will result in
FATAL error. */
(void) secure_initialize(true);
/* ... so here we know for sure that SSL was successfully
initialized. */
LoadedSSL = true;
}

Reader> This is an important piece of code, not just because it is
called from PostmasterMain(), early in the startup process, but also
because it deals with SSL; it has 'SSL' and 'secure' plastered all
over it. But wait, they don't care what the outcome of this important
function call is??!! That's okay, because the explanation in the
comment makes sense.  There's nothing wrong here. .

> I think it's not a great idea to add such
> comments to call sites, as they're very likely to not get maintained
> when somebody adjusts the API of the function.  (We have a hard enough
> time getting people to update the comments directly next to the
> function :-(.)

That's unfortunate. But I think we should continue to strive for more
maintainable, readable, extensible code.

> I think what we ought to do here is just move the oddly-placed comments
> in libpq-be.h to be adjacent to the function definitions, as attached.
> (I just deleted the .h comments for the GSSAPI functions, as they seem
> to have adequate comments in their .c file already.)

Please see if anything from my patches is usable. I did not get
clarity around startup vs. reload handling until my previous email, so
there may not be much of use in my patches. But I think a few words
mentioning the difference in resource (re)initialization during
startup vs reload would add a lot of value.

Best regards,
Gurjeet
http://Gurje.et




Re: Hardening PostgreSQL via (optional) ban on local file system access

2022-06-24 Thread Gurjeet Singh
On Fri, Jun 24, 2022 at 4:13 PM Andres Freund  wrote:
> On 2022-06-25 00:08:13 +0200, Hannu Krosing wrote:

> > 3) should this be back-patched (we can provide batches for all
> > supported PgSQL versions)
>
> Err, what?

Translation: Backpatching these changes to any stable versions will
not be acceptable (per the project versioning policy [1]), since these
changes would be considered new feature. These changes can break
installations, if released in a minor version.

[1]: https://www.postgresql.org/support/versioning/

Best regards,
Gurjeet
http://Gurje.et




Re: Hardening PostgreSQL via (optional) ban on local file system access

2022-06-24 Thread Gurjeet Singh
(fixed your top-posting)

On Fri, Jun 24, 2022 at 4:59 PM Hannu Krosing  wrote:
> On Sat, Jun 25, 2022 at 1:46 AM Gurjeet Singh  wrote:
> >
> > On Fri, Jun 24, 2022 at 4:13 PM Andres Freund  wrote:
> > > On 2022-06-25 00:08:13 +0200, Hannu Krosing wrote:
> >
> > > > 3) should this be back-patched (we can provide batches for all
> > > > supported PgSQL versions)
> > >
> > > Err, what?
> >
> > Translation: Backpatching these changes to any stable versions will
> > not be acceptable (per the project versioning policy [1]), since these
> > changes would be considered new feature. These changes can break
> > installations, if released in a minor version.
> >
> > [1]: https://www.postgresql.org/support/versioning/
>
> My understanding was that unless activated by admin these changes
> would change nothing.
>
> And they would be (borderline :) ) security fixes
>
> And the versioning policy link actually does not say anything about
> not adding features to older versions (I know this is the policy, just
> pointing out the info in not on that page).

I wanted to be sure before I mentioned it, and also because I've been
away from the community for a few years [1], so I too searched the
page for any relevant mentions of the word "feature" on that page.
While you're correct that the policy does not address/prohibit
addition of new features in minor releases, but the following line
from the policy comes very close to saying it, without actually saying
it.

> ... PostgreSQL minor releases fix only frequently-encountered bugs, security 
> issues, and data corruption problems to reduce the risk associated with 
> upgrading ...

Like I recently heard a "wise one" recently say: "oh those [Postgres]
docs are totally unclear[,] but they're technically correct".

BTW, the "Translation" bit was for folks new to, or not familiar with,
community and its lingo; I'm sure you already knew what Andres meant
:-)

[1]: I'll milk the "I've been away from the community for a few years"
excuse for as long as possible ;-)

Best regards,
Gurjeet
http://Gurje.et




Re: [PoC/RFC] Multiple passwords, interval expirations

2022-06-30 Thread Gurjeet Singh
I am planning on picking it up next week; right now picking up steam,
and reviewing a different, smaller patch.

At his behest, I had a conversation with Joshua (OP), and have his
support to pick up and continue working on this patch. I have a some
ideas of my own, on what this patch should do, but since I haven't
fully reviewed the (bulky) patch, I'll reserve my proposals until I
wrap my head around it.

Please expect some activity on this patch towards the end of next week.

BCC: Joshua's new work email.

Best regards,
Gurjeet
http://Gurje.et

On Wed, Jun 29, 2022 at 2:27 PM Stephen Frost  wrote:
>
> Greetings,
>
> On Wed, Jun 29, 2022 at 17:22 Jacob Champion  wrote:
>>
>> On 4/8/22 10:04, Joshua Brindle wrote:
>> > It's unclear if I will be able to continue working on this featureset,
>> > this email address will be inactive after today.
>>
>> I'm assuming the answer to this was "no". Is there any interest out
>> there to pick this up for the July CF?
>
>
> Short answer to that is yes, I’m interested in continuing this (though 
> certainly would welcome it if there are others who are also interested, and 
> may be able to bring someone else to help work on it too but that might be 
> more August / September time frame).
>
> Thanks,
>
> Stephen




Re: generate_series for timestamptz and time zone problem

2022-06-30 Thread Gurjeet Singh
On Tue, Jun 21, 2022 at 7:56 AM Przemysław Sztoch  wrote:
> There is another patch.
> It works, but one thing is wrongly done because I lack knowledge.

Thank you for continuing to work on it despite this being your first
time contributing, and despite the difficulties. I'll try to help as
much as I can.

> Where I'm using DirectFunctionCall3 I need to pass the timezone name, but I'm 
> using cstring_to_text and I'm pretty sure there's a memory leak here. But I 
> need help to fix this.
> I don't know how best to store the timezone in the generate_series context. 
> Please, help.

In Postgres code we generally don't worry about memory leaks (a few
caveats apply). The MemoryContext infrastructure (see aset.c) enables
us to be fast and loose with memory allocations. A good way to know if
you should be worried about your allocations, is to look in the
neighboring code, and see what does it do with the memory it
allocates.

I think your use of cstring_to_text() is safe.

> Please give me feedback on how to properly store the timezone name in the 
> function context structure. I can't finish my work without it.

The way I see it, I don't think you need to store the tz-name in the
function context structure, like you're currently doing. I think you
can remove the additional member from the
generate_series_timestamptz_fctx struct, and refactor your code in
generate_series_timestamptz() to work without it.; you seem to  be
using the tzname member almost as a boolean flag, because the actual
value you pass to DFCall3() can be calculated without first storing
anything in the struct.

> Additionally, I added a new variant of the date_trunc function that takes 
> intervals as an argument.
> It enables functionality similar to date_bin, but supports monthly, 
> quarterly, annual, etc. periods.
> In addition, it is resistant to the problems of different time zones and 
> daylight saving time (DST).

This addition is beyond the original scope (add TZ param), so I think
it would be considered a separate change/feature. But for now, we can
keep it in.

Although not necessary, it'd be nice to have changes that can be
presented as single units, be a patch of their own. If  you're
proficient with Git, can you please maintain each SQL-callable
function as a separate commit in your branch,  and use `git
format-patch` to generate a series for submission.

Can you please explain why you chose to remove the provolatile
attribute from the existing entry of date_trunc in pg_proc.dat.

It seems like you've picked/reused code from neighboring functions
(e.g. from timestamptz_trunc_zone()). Can you please see if you can
turn such code into a function, and  call the function, instead of
copying it.

Also, according to the comment at the top of pg_proc.dat,

 # Once upon a time these entries were ordered by OID.  Lately it's often
 # been the custom to insert new entries adjacent to related older entries.

So instead of adding your entries at the bottom of the file, please
each entry closer to an existing entry that's relevant to it.

I'm glad that you're following the advice on the patch-submission wiki
page [1]. When submitting a patch for committers' consideration,
though, the submission needs to cross quite a few hurdles. So have
prepared a markdown doc [2]. Let's fill in as much detail there as
possible, before we mark it 'Ready for Committer' in the CF app.

[1]: https://wiki.postgresql.org/wiki/Submitting_a_Patch
[2]: https://wiki.postgresql.org/wiki/Patch_Reviews

Best regards,
Gurjeet
http://Gurje.et




Fwd: Unprivileged user can induce crash by using an SUSET param in PGOPTIONS

2022-07-20 Thread Gurjeet Singh
Moving the report from security to -hackers on Noah's advice. Since
the function(s) involved in the crash are not present in any of the
released versions, it is not considered a security issue.

I can confirm that this is reproducible on the latest commit on
master, 3c0bcdbc66. Below is the original analysis, followed by Noah's
analysis.

To be able to reproduce it, please note that perl support is required;
 hence `./configure --with-perl`.

The note about 'security concerns around on_plperl_init parameter',
below, refers to now-fixed issue, at commit 13d8388151.

Best regards,
Gurjeet
http://Gurje.et

Forwarded Conversation
Subject: Unprivileged user can induce crash by using an SUSET param in PGOPTIONS
----

From: Gurjeet Singh 
Date: Mon, Jul 4, 2022 at 10:24 AM
To: Postgres Security 
Cc: Bossart, Nathan 


While poking at plperl's GUC in an internal discussion, I was able to
induce a crash (or an assertion failure in assert-enabled builds) as
an unprivileged user.

My investigation so far has revealed that the code path for the
following condition has never been tested, and because of this, when a
user tries to override an SUSET param via PGOPTIONS, Postgres tries to
perform a table lookup during process initialization. Because there's
no transaction in progress, and because this table is not in the
primed caches, we end up with code trying to dereference an
uninitialized  CurrentResourceOwner.

The condition:
User specifies PGOPTIONS"-c custom.param"
"custom.param" is used by an extension which is specified in
session_preload_libraries
The extension uses DefineCustom*Variable("custom.param", PGC_SUSET)
inside set_config_option()
  record->context == PGC_SUSET
  context == PGC_BACKEND
  calls pg_parameter_aclcheck()  -> eventually leads to
assertion-failure (or crash, when assertions are disabled)

See below for 1. How to reproduce, 2. Assertion failure stack, and 3.
Crash stack

When the user does not specify PGOPTIONS, the code in
define_custom_variable() returns prematurely, after a failed bsearch()
lookup, and hence avoids this bug.

I think similar crash can be  induced when the custom parameter is of
kind PGC_SU_BACKEND, because the code to handle that also invokes
pg_parameter_aclcheck(). Also, I believe the same condition would
arise if the extension is specified local_preload_libraries.

I haven't  been  able to think of an attack vector using this bug, but
it can be used to cause a denial-of-service by an authenticated user.
I'm sending this report to security list, instead of -hackers, out of
abundance of caution; please feel free to move it to -hackers, if it's
not considered a security concern.

I discovered this bug a couple of days ago, just before leaving on a
trip. But because of shortage of time over the weekend, I haven't been
able to dig deeper into it. Since I don't think I'll be able to spend
any significant time on it for at least another couple of days, I'm
sending this report without a patch or a proposed fix.

CC: Nathan, whose security concerns around on_plperl_init parameter
lead to this discovery.

[1]: How to reproduce

$ psql -c 'create user test'
CREATE ROLE

$ psql -c "alter system set session_preload_libraries='plperl'"
ALTER SYSTEM

$ # restart server

$ psql -c 'show session_preload_libraries'
 session_preload_libraries
---
 plperl
(1 row)

$ PGOPTIONS="-c plperl.on_plperl_init=" psql -U test
psql: error: connection to server on socket "/tmp/.s.psql.5432"
failed: server closed the connection unexpectedly
┆   This probably means the server terminated abnormally
before or while processing the request.


[2]:  Assertion failure stack

LOG:  database system is ready to accept connections
TRAP: FailedAssertion("IsTransactionState()", File:
"../../../../../../POSTGRES/src/backend/utils/cache/catcache.c", Line:
1209, P
ID: 199868)
postgres: test postgres [local]
startup(ExceptionalCondition+0xd0)[0x55e503a4e6c9]
postgres: test postgres [local] startup(+0x7e069b)[0x55e503a2a69b]
postgres: test postgres [local] startup(SearchCatCache1+0x3a)[0x55e503a2a56b]
postgres: test postgres [local] startup(SearchSysCache1+0xc1)[0x55e503a46fe4]
postgres: test postgres [local]
startup(pg_parameter_aclmask+0x6f)[0x55e50345f098]
postgres: test postgres [local]
startup(pg_parameter_aclcheck+0x2d)[0x55e50346039c]
postgres: test postgres [local] startup(set_config_option+0x450)[0x55e503a70727]
postgres: test postgres [local] startup(+0x829ce8)[0x55e503a73ce8]
postgres: test postgres [local]
startup(DefineCustomStringVariable+0xa4)[0x55e503a74306]
/home/vagrant/dev/POSTGRES_builds/add_tz_param/db/lib/postgresql/plperl.so(_PG_init+0xd7)[0x7fed3d845425]
postgres: test postgres [local] startup(+0x80cc50)[0x55e503a56c50]
postgres: test postgres [local] star

Re: Fwd: Unprivileged user can induce crash by using an SUSET param in PGOPTIONS

2022-07-21 Thread Gurjeet Singh
On Thu, Jul 21, 2022 at 2:44 PM Tom Lane  wrote:
>
> Gurjeet Singh  writes:
> > While poking at plperl's GUC in an internal discussion, I was able to
> > induce a crash (or an assertion failure in assert-enabled builds) as
> > an unprivileged user.
> > My investigation so far has revealed that the code path for the
> > following condition has never been tested, and because of this, when a
> > user tries to override an SUSET param via PGOPTIONS, Postgres tries to
> > perform a table lookup during process initialization. Because there's
> > no transaction in progress, and because this table is not in the
> > primed caches, we end up with code trying to dereference an
> > uninitialized  CurrentResourceOwner.
>
> Right.  So there are basically two things we could do about this:
>
> 1. set_config_option could decline to call pg_parameter_aclcheck
> if not IsTransactionState(), instead failing the assignment.
> This isn't a great answer because it would result in disallowing
> GUC assignments that users might expect to work.
>
> 2. We could move process_session_preload_libraries() to someplace
> where a transaction is in progress -- probably, relocate it to
> inside InitPostgres().
>
> I'm inclined to think that #2 is a better long-term solution,
> because it'd allow you to session-preload libraries that expect
> to be able to do database access during _PG_init.  (Right now
> that'd fail with the same sort of symptoms seen here.)  But
> there's no denying that this might have surprising side-effects
> for extensions that weren't expecting such a change.
>
> It could also be reasonable to do both #1 and #2, with the idea
> that #1 might save us from crashing if there are any other
> code paths where we can reach that pg_parameter_aclcheck call
> outside a transaction.
>
> Thoughts?

I had debated just wrapping the process_session_preload_libraries()
call with a transaction, like Nathan's patch posted ealier on this
thread does. But I hesitated because of the sensitivity around the
order of operations/call during process initialization.

I like the idea of performing library initialization in
InitPostgres(), as it performs the first transaction of the
connection, and because of the libraries' ability to gin up new GUC
variables that might need special handling, and also if it allows them
to do database access.

I think anywhere after the 'PostAuthDelay' check in InitPostgres()
would be a good place to perform process_session_preload_libraries().
I'm inclined to invoke it as late as possible, before we commit the
transaction.

As for making set_config_option() throw an error if not in
transaction, I'm not a big fan of checks  that break the flow, and of
unrelated code showing up when reading a function. For a casual
reader, such a check for transaction would make for a jarring
experience; "why are we checking for active transaction in  the guts
of guc.c?", they might think. If anything, such an error should be
thrown from or below pg_parameter_aclcheck().

But I am not sure if it should be exposed as an error. A user
encountering that error is not at fault. Hence I believe an assertion
check is more suitable for catching code that invokes
set_config_option() outside a transaction.

Best regards,
Gurjeet
http://Gurje.et




Re: Fwd: Unprivileged user can induce crash by using an SUSET param in PGOPTIONS

2022-07-21 Thread Gurjeet Singh
On Thu, Jul 21, 2022 at 3:29 PM Nathan Bossart  wrote:
>
> On Thu, Jul 21, 2022 at 05:44:11PM -0400, Tom Lane wrote:
> > Right.  So there are basically two things we could do about this:
> >
> > 1. set_config_option could decline to call pg_parameter_aclcheck
> > if not IsTransactionState(), instead failing the assignment.
> > This isn't a great answer because it would result in disallowing
> > GUC assignments that users might expect to work.
> >
> > 2. We could move process_session_preload_libraries() to someplace
> > where a transaction is in progress -- probably, relocate it to
> > inside InitPostgres().
> >
> > I'm inclined to think that #2 is a better long-term solution,
> > because it'd allow you to session-preload libraries that expect
> > to be able to do database access during _PG_init.  (Right now
> > that'd fail with the same sort of symptoms seen here.)  But
> > there's no denying that this might have surprising side-effects
> > for extensions that weren't expecting such a change.
> >
> > It could also be reasonable to do both #1 and #2, with the idea
> > that #1 might save us from crashing if there are any other
> > code paths where we can reach that pg_parameter_aclcheck call
> > outside a transaction.
> >
> > Thoughts?
>
> I wrote up a small patch along the same lines as #2 before seeing this
> message.  It simply ensures that process_session_preload_libraries() is
> called within a transaction.  I don't have a strong opinion about doing it
> this way versus moving this call somewhere else as you proposed, but I'd
> agree that #2 is a better long-term solution than #1.  AFAICT
> shared_preload_libraries, even with EXEC_BACKEND, should not have the same
> problem.
>
> I'm not sure whether we should be worried about libraries that are already
> creating transactions in their _PG_init() functions.  Off the top of my
> head, I don't recall seeing anything like that.  Even if it does impact
> some extensions, it doesn't seem like it'd be too much trouble to fix.
>
> diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
> index 8ba1c170f0..fd471d74a3 100644
> --- a/src/backend/tcop/postgres.c
> +++ b/src/backend/tcop/postgres.c
> @@ -4115,8 +4115,15 @@ PostgresMain(const char *dbname, const char *username)
>  /*
>   * process any libraries that should be preloaded at backend start (this
>   * likewise can't be done until GUC settings are complete)
> + *
> + * If the user provided a setting at session startup for a custom GUC
> + * defined by one of these libraries, we might need syscache access when
> + * evaluating whether she has permission to set it, so do this step 
> within
> + * a transaction.
>   */
> +StartTransactionCommand();
>  process_session_preload_libraries();
> +CommitTransactionCommand();
>
>  /*
>   * Send this backend's cancellation info to the frontend.

(none of the following is your patch's fault)

I don't think that is a good call-site for
process_session_preload_libraries(), because a library being loaded
can declare its own GUCs, hence I believe this should be called at
least before the call to BeginReportingGUCOptions().

If an extension creates a GUC with GUC_REPORT flag, it is violating
expectations. But since the DefineCustomXVariable() stack does not
prevent the callers from doing so, we must still honor the protocol
followed for all params with GUC_REPORT. And hence the

I think it'd be a good idea to ban the callers of
DefineCustomXVariable() from declaring their variable GUC_REPORT, to
ensure that only core code can define such variables.

Best regards,
Gurjeet
http://Gurje.et




Re: Fwd: Unprivileged user can induce crash by using an SUSET param in PGOPTIONS

2022-07-21 Thread Gurjeet Singh
On Thu, Jul 21, 2022 at 4:35 PM Gurjeet Singh  wrote:
> I like the idea of performing library initialization in
> InitPostgres(), as it performs the first transaction of the
> connection, and because of the libraries' ability to gin up new GUC
> variables that might need special handling, and also if it allows them
> to do database access.
>
> I think anywhere after the 'PostAuthDelay' check in InitPostgres()
> would be a good place to perform process_session_preload_libraries().
> I'm inclined to invoke it as late as possible, before we commit the
> transaction.
>
> As for making set_config_option() throw an error if not in
> transaction, I'm not a big fan of checks  that break the flow, and of
> unrelated code showing up when reading a function. For a casual
> reader, such a check for transaction would make for a jarring
> experience; "why are we checking for active transaction in  the guts
> of guc.c?", they might think. If anything, such an error should be
> thrown from or below pg_parameter_aclcheck().
>
> But I am not sure if it should be exposed as an error. A user
> encountering that error is not at fault. Hence I believe an assertion
> check is more suitable for catching code that invokes
> set_config_option() outside a transaction.

Please see attached the patch that implements the above proposal.

The process_session_preload_libraries() call has been moved to the end
of InitPostgres(), just before we report the backend to
PgBackendStatus and commit the first transaction.

One notable side effect of this change is that
process_session_preload_libraries() is now called _before_ we
SetProcessingMode(NormalProcessing). Which means any database access
performed by _PG_init() of an extension will be doing it in
InitProcessing mode. I'm not sure if that's problematic.

The patch also adds an assertion in pg_parameter_aclcheck() to ensure
that there's a transaction is in progress before it's called.

The patch now lets the user connect, throws a warning, and does not crash.

$ PGOPTIONS="-c plperl.on_plperl_init=" psql -U test
WARNING:  permission denied to set parameter "plperl.on_plperl_init"
Expanded display is used automatically.
psql (15beta1)
Type "help" for help.

postgres@B:694512=>

Best regards,
Gurjeet
http://Gurje.et


move_process_session_preload_libraries.patch
Description: Binary data


Re: `make check` doesn't pass on MacOS Catalina

2022-08-06 Thread Gurjeet Singh
On Tue, Apr 20, 2021 at 9:06 AM Andrew Dunstan  wrote:
>
> On 4/20/21 11:02 AM, Tom Lane wrote:
> > Aleksander Alekseev  writes:
> >> While trying to build PostgreSQL from source (master branch, 95c3a195) on a
> >> MacBook I discovered that `make check` fails:
> > This is the usual symptom of not having disabled SIP :-(.
> >
> > If you don't want to do that, do "make install" before "make check".

> FYI the buildfarm client has a '--delay-check' option that does exactly
> this. It's useful on Alpine Linux as well as MacOS

I was trying to set up a buildfarm animal, and this exact problem lead
to a few hours of debugging and hair-pulling. Can the default
behaviour be changed in buildfarm client to perform `make check` only
after `make install`.

Current buildfarm client code looks something like:

make();
make_check() unless $delay_check;
... other steps ...
make_install();
... other steps-2...
make_check() if $delay_check;

There are no comments as to why one should choose to use --delay-check
($delay_check). This email, and the pointer to the paragraph buried in
the docs, shared by Tom, are the only two ways one can understand what
is causing this failure, and how to get around it.

Naive question: What's stopping us from rewriting the code as follows.
make();
make_install();
make_check();
... other steps ...
... other steps-2...
# or move make_check() call here

With a quick google search I could not find why --delay-check is
necessary on Apline linux, as well; can you please elaborate.

Best regards,
Gurjeet
http://Gurje.et




Re: Patch proposal: New hooks in the connection path

2022-08-13 Thread Gurjeet Singh
On Mon, Aug 8, 2022 at 3:51 AM Drouvot, Bertrand  wrote:
> Please find attached v2-0004-connection_hooks.patch

 /*
  * Stop here if it was bad or a cancel packet.  ProcessStartupPacket
  * already did any appropriate error reporting.
  */
 if (status != STATUS_OK)
+{
+#ifndef EXEC_BACKEND
+if (FailedConnection_hook)
+(*FailedConnection_hook) (FCET_BAD_STARTUP_PACKET, port);
+#endif
 proc_exit(0);
+}

Per the comment above the if condition, the `status != OK` may
represent a cancel packet, as well. Clearly, a cancel packet is not
the same as a _bad_ packet. So I think here you need to differentiate
between a cancel packet and a genuinely bad packet; I don't see
anything good coming good out of us, or the hook-developer, lumping
those 2 cases together.

I think we can reduce the number of places the hook is called, if we
call the hook from proc_exit(), and all the other places we simply set
a global variable to signify the reason for the failure. The case of
_exit(1) from the signal-handler cannot use such a mechanism, but I
think all the other cases of interest can simply register one of the
FCET_* value, and the hook call from proc_exit() can pass that value
to the hook.

If we can convinces ourselves that we can use proc_exit(1) in
StartupPacketTimeoutHandler(), instead of calling _exit(1), I think we
cal eliminate replace all call sites for this hook with
set-global-variable variant.

> ...
> * This should be the only function to call exit().
> * -cim 2/6/90
>...
> proc_exit(int code)

The comment on proc_exit() claims that should be the only place
calling exit(), except the add-on/extension hooks. So there must be a
strong reason why the signal-handler uses _exit() to bypass all
callbacks.

Best regards,
Gurjeet
http://Gurje.et




Re: Patch proposal: New hooks in the connection path

2022-08-13 Thread Gurjeet Singh
(reposting the same review, with many grammatical fixes)

On Mon, Aug 8, 2022 at 3:51 AM Drouvot, Bertrand  wrote:
> Please find attached v2-0004-connection_hooks.patch

 /*
  * Stop here if it was bad or a cancel packet.  ProcessStartupPacket
  * already did any appropriate error reporting.
  */
 if (status != STATUS_OK)
+{
+#ifndef EXEC_BACKEND
+if (FailedConnection_hook)
+(*FailedConnection_hook) (FCET_BAD_STARTUP_PACKET, port);
+#endif
 proc_exit(0);
+}

Per the comment above the if condition, the `status != OK` may
represent a cancel packet, as well. Clearly, a cancel packet is not
the same as a _bad_ packet. So I think here you need to differentiate
between a cancel packet and a genuinely bad packet; I don't see
anything good coming out of us, or the hook-developer, lumping
those 2 cases together.

I think we can reduce the number of places the hook is called, if we
call the hook from proc_exit(), and at all the other places we simply set
a global variable to signify the reason for the failure. The case of
_exit(1) from the signal-handler cannot use such a mechanism, but I
think all the other cases of interest can simply register one of the
FCET_* values, and let the call from proc_exit() pass that value
to the hook.

If we can convince ourselves that we can use proc_exit(1) in
StartupPacketTimeoutHandler(), instead of calling _exit(1), I think we
cal replace all call sites for this hook with the
set-global-variable variant.

> ...
> * This should be the only function to call exit().
> * -cim 2/6/90
>...
> proc_exit(int code)

The comment on proc_exit() claims that it should be the only place
calling exit(), except that the add-on/extension hooks may ignore this.
So there must be a strong reason why the signal-handler uses _exit()
to bypass all callbacks.

Best regards,
Gurjeet
http://Gurje.et




Returning to Postgres community work

2021-08-30 Thread Gurjeet Singh
Hi All,

 I'm very happy to announce that I now work for Supabase [1]. They
have hired me so that I can participate in, and contribute to the
Postgres community.

I'm announcing it here in the hopes that more companies feel
encouraged to contribute to Postgres. For those who don't know my past
work and involvement in the Postgres community, please see the
'PostgreSQL RDBMS' section in my resume [2] (on page 4).

I'm deeply indebted to Supabase for giving me this opportunity to
work with, and for the Postgres community.

Following is the statement by Paul (CEO) and Anthony (CTO), the
co-founders of Supabase:

Supabase is a PostgreSQL hosting service that makes PostgreSQL
incredibly easy to use. Since our inception in 2020 we've benefited
hugely from the work of the PostgreSQL community.

We've been long-time advocates of PostgreSQL, and we're now in a
position to contribute back in a tangible way. We're hiring Gurjeet
with the explicit goal of working on PostgreSQL community
contributions. We're excited to welcome Gurjeet to the team at
Supabase.

[1]: https://supabase.io/
[2]: https://gurjeet.singh.im/GurjeetResume.pdf

PS: Hacker News announcement is at https://news.ycombinator.com/item?id=

Best regards,
--
Gurjeet Singh http://gurjeet.singh.im/




Re: Returning to Postgres community work

2021-08-30 Thread Gurjeet Singh
On Mon, Aug 30, 2021 at 10:53 PM Gurjeet Singh  wrote:

> PS: Hacker News announcement is at https://news.ycombinator.com/item?id=

https://news.ycombinator.com/item?id=28364406

Best regards,
--
Gurjeet Singh http://gurjeet.singh.im/




Re: Returning to Postgres community work

2021-08-31 Thread Gurjeet Singh
On Tue, Aug 31, 2021 at 8:04 AM Alvaro Herrera  wrote:
>
> On 2021-Aug-30, Gurjeet Singh wrote:
>
> >  I'm very happy to announce that I now work for Supabase [1]. They
> > have hired me so that I can participate in, and contribute to the
> > Postgres community.
>
> Hey Gurjeet, welcome back.  Glad to hear you've found a good spot.

Thank you!

> You know what I've heard?  That your index advisor module languishes
> unmaintained and that there's no shortage of people wishing to use it.

Now there's a masterclass in making someone feel great and guilty in
the same sentence ;-)

> Heck, we spent a lot of back-and-forth in the spanish mailing list
> with somebody building a super obsolete version of Postgres just so that
> they could compile your index advisor.  I dunno, if you have some spare
> time, maybe updating that one would be a valuable contribution from
> users' perspective.

Aye-aye Capn' :-)

EDB folks reached out to me a few months ago to assign a license to
the project, which I did and it is now a Postgres-licensed project
[1].

Given the above, it is safe to assume that this tool is at least being
maintained by EDB, at least internally for their customers. I would
request them to contribute the changes back in the open.

Regardless of that, please rest assured that I will work on making it
compatible with the current supported versions of Postgres. Lack of
time is not an excuse anymore :-)

Thanks for bringing this to my attention!

[1]: https://github.com/gurjeet/pg_adviser/blob/master/LICENSE

Best regards,
--
Gurjeet Singh http://gurjeet.singh.im/




Re: Slightly improve initdb --sync-only option's help message

2021-07-28 Thread Gurjeet Singh
On Mon, Jul 26, 2021 at 11:05 AM Bossart, Nathan  wrote:
> Here are my suggestions in patch form.

+printf(_("  -S, --sync-only   safely write all database
files to disk and exit\n"));

Not your patch's fault, but the word "write" does not seem to convey
the true intent of the option, because generally a "write" operation
is still limited to dirtying the OS buffers, and does not guarantee
sync-to-disk.

It'd be better if the help message said, either "flush all database
files to disk and exit",or "sync all database files to disk and exit".

Best regards,
--
Gurjeet Singh http://gurjeet.singh.im/




Re: Slightly improve initdb --sync-only option's help message

2021-08-16 Thread Gurjeet Singh
On Mon, Aug 16, 2021 at 4:42 AM Daniel Gustafsson  wrote:
>
> > On 30 Jul 2021, at 18:27, Bossart, Nathan  wrote:
> >
> > On 7/30/21, 2:22 AM, "Daniel Gustafsson"  wrote:
> >> LGTM.  I took the liberty to rephrase the "and exit" part of the initdb 
> >> help
> >> output match the other exiting options in there.  Barring objections, I 
> >> think
> >> this is ready.
> >
> > LGTM.  Thanks!
>
> Pushed to master, thanks!

Thank you Daniel and Nathan! Much appreciated.

Best regards,
--
Gurjeet Singh http://gurjeet.singh.im/




Proposal: Division operator for (interval / interval => double precision)

2024-06-23 Thread Gurjeet Singh
Is there a desire to have a division operator / that takes dividend
and divisor of types interval, and results in a quotient of type
double precision.

This would be helpful in calculating how many times the divisor
interval can fit into the dividend interval.

To complement this division operator, it would be desirable to also
have a remainder operator %.

For example,

('365 days'::interval / '5 days'::interval) => 73
('365 days'::interval % '5 days'::interval) => 0

('365 days'::interval / '3 days'::interval) => 121
('365 days'::interval % '3 days'::interval) => 2

Best regards,
Gurjeet
http://Gurje.et




Re: DecodeInterval fixes

2023-07-08 Thread Gurjeet Singh
On Sat, Jul 8, 2023 at 1:33 PM Tom Lane  wrote:
>
> Gurjeet Singh  writes:
> > On Fri, Jul 7, 2023 at 4:13 PM Tom Lane  wrote:
> >> The ECPG datetime datatype support code has been basically unmaintained
> >> for years, and has diverged quite far at this point from the core code.
>
> > I was under the impression that anything in the postgresql.git
> > repository is considered core, and hence maintained as one unit, from
> > release to release.
>
> When I say that ecpglib is next door to unmaintained, I'm just stating
> the facts on the ground; project policy is irrelevant.  That situation
> is not likely to change until somebody steps up to do (a lot of) work
> on it, which is probably unlikely to happen unless we start getting
> actual complaints from ECPG users.  For the meantime, what's there now
> seems to be satisfactory to whoever is using it ... which might be
> nobody?
>
> In any case, you don't have to look far to notice that some parts of
> the tree are maintained far more actively than others.  ecpglib is
> just one of the more identifiable bits that's receiving little love.
> The quality of the code under contrib/ is wildly variable, and even
> the server code itself has backwaters.  (For instance, the "bit" types,
> which aren't even in the standard anymore; or the geometric types,
> or "money".)

Thanks for sharing your view on different parts of the code. This give
a clear direction if someone would be interested in stepping up.

As part of my mentoring a GSoC 2023 participant, last night we were
looking at the TODO wiki page, for something for the mentee to pick up
next. I feel the staleness/deficiencies you mention above are not
captured in the TODO wiki page. It'd be nice if these were documented,
so that newcomers to the community can pick up work that they feel is
an easy lift for them.

> By and large, I don't see this unevenness of maintenance effort as
> a problem.  It's more like directing our limited resources into the
> most useful places.  Code that isn't getting worked on is either not
> used at all by anybody, or it serves the needs of those who use it
> well enough already.  Since it's difficult to tell which of those
> cases applies, removing code just because it's not been improved
> lately is a hard choice to sell.  But so is putting maintenance effort
> into code that there might be little audience for.  In the end we
> solve this via the principle of "scratch your own itch": if somebody
> is concerned enough about a particular piece of code to put their own
> time into improving it, then great, it'll get improved.
>
> > Benign neglect doesn't sound nice from a user's/consumer's
> > perspective. Can it be labeled (i.e. declared as such in docs) as
> > deprecated.
>
> Deprecation would imply that we're planning to remove it, which
> we are not.

Good to know. Sorry I took "benign neglect" to mean that there's no
willingness to improve it. This makes it clear that community wants to
improve and maintain ECPG, it's just a matter of someone volunteering,
and better use of the resources available.



Best regards,
Gurjeet
http://Gurje.et




Re: BUG #18016: REINDEX TABLE failure

2023-07-10 Thread Gurjeet Singh
On Sun, Jul 9, 2023 at 7:21 AM Richard Veselý  wrote:
>
> ... there's no shortage of people that suffer from sluggish 
> pg_dump/pg_restore cycle and I imagine there are any number of people that 
> would be interested in improving bulk ingestion which is often a bottleneck 
> for analytical workloads as you are well aware. What's the best place to 
> discuss this topic further - pgsql-performance or someplace else?

(moved conversation to -hackers, and moved -bugs to BCC)

> I was dissatisfied with storage layer performance, especially during the 
> initial database population, so I rewrote it for my use case. I'm done with 
> the heap, but for the moment I still rely on PostgreSQL to build indexes,

It sounds like you've developed a method to speed up loading of
tables, and might have ideas/suggestions for speeding up CREATE
INDEX/REINDEX. The -hackers list feels like a place to discuss such
changes.

Best regards,
Gurjeet
http://Gurje.et




Re: BUG #18016: REINDEX TABLE failure

2023-07-11 Thread Gurjeet Singh
On Sun, Jul 9, 2023 at 7:18 AM Tom Lane  wrote:
>
> Michael Paquier  writes:
> > That should be OK, I assume.  However, if this is improved and
> > something we want to support in the long-run I guess that a TAP test
> > may be appropriate.
>
> I do not see the point of a TAP test.  It's not like the code isn't
> covered perfectly well.

Please find attached the patch that makes REINDEX TABLE perform
reindex on toast table before reindexing the main table's indexes.

The code block movement involved slightly more thought and care than I
had previously imagined. As explained in comments in the patch, the
enumeration and suppression of indexes on the main table must happen
before any CommandCounterIncrement() call, hence the
reindex-the-toast-table-if-any code had to be placed after that
enumeration.

In support of the argument above, the patch does not include any TAP
tests. Reliably reproducing the original error message involves
restarting the database, and since that can't be done via SQL
commands, no sql tests are included, either.

The patch also includes minor wordsmithing, and benign whitespace
changes in neighboring code.

Best regards,
Gurjeet
http://Gurje.et


v1-0001-Reindex-toast-table-s-index-before-main-table-s-i.patch
Description: Binary data


Re: Document that server will start even if it's unable to open some TCP/IP ports

2023-07-11 Thread Gurjeet Singh
On Mon, Jun 19, 2023 at 5:48 PM Bruce Momjian  wrote:
>
> On Tue, Jun 13, 2023 at 11:11:04PM -0400, Tom Lane wrote:
> >
> > There is certainly an argument that such a condition indicates that
> > something's very broken in our configuration and we should complain.
> > But I'm not sure how exciting the case is in practice.  The systemd
> > guys would really like us to be willing to come up before any network
> > interfaces are up, and then auto-listen to those interfaces when they
> > do come up.

That sounds like a reasonable expectation, as the network conditions
can change without any explicit changes made by someone.

> > On the other hand, the situation with Unix sockets is
> > much more static: if you can't make a socket in /tmp or /var/run at
> > the instant of postmaster start, it's unlikely you will be able to do
> > so later.

I think you're describing a setup where Postgres startup is automatic,
as part of server/OS startup. That is the most common case.

In cases where someone is performing a Postgres startup manually, they
are very likely to have the permissions to fix the problem preventing
the startup.

> > Maybe we need different rules for TCP versus Unix-domain sockets?
> > I'm not sure what exactly, but lumping those cases together for
> > a discussion like this feels wrong.

+1.

> If we are going to retry for network configuration changes, it seems we
> would also retry Unix domain sockets for cases like when the permissions
> are wrong, and then fixed.

The network managers (systemd, etc.) are expected to respond to
dynamic conditions, and hence they may perform network config changes
in response to things like network outages, and hardware failures,
time of day, etc.

On the other hand, the permissions required to create files for Unix
domain sockets are only expected to change if someone decides to make
that change. I wouldn't expect these permissions to be changed
dynamically.

On those grounds, keeping the treatment of Unix domain sockets out of
this discussion for this patch seems reasonable.

> However, it seem hard to figure out exactly what _is_ working if we take
> the approach of dynamically retrying listen methods.  Do we report
> anything helpful in the server logs when we start and can't listen on
> anything?

Yes. For every host listed in listen_addresses, if Postgres fails to
open the port on that address, we get a WARNING message in the server
log. After the end of processing of a non-empty listen_addresses, if
there are zero open TCP/IP connections, the server exits (with a FATAL
message, IIRC).

Best regards,
Gurjeet
http://Gurje.et




Re: MERGE ... RETURNING

2023-07-11 Thread Gurjeet Singh
On Fri, Jul 7, 2023 at 3:48 PM Dean Rasheed  wrote:
>
> On Thu, 6 Jul 2023 at 06:13, Gurjeet Singh  wrote:
> >
> > > One minor annoyance is that, due to the way that pg_merge_action() and
> > > pg_merge_when_clause() require access to the MergeActionState, they
> > > only work if they appear directly in the RETURNING list. They can't,
> > > for example, appear in a subquery in the RETURNING list, and I don't
> > > see an easy way round that limitation.
> >
> > I believe that's a serious limitation, and would be a blocker for the 
> > feature.
>
> Yes, that was bugging me for quite a while.
>
> Attached is a new version that removes that restriction, allowing the
> merge support functions to appear anywhere. This requires a bit of
> planner support, to deal with merge support functions in subqueries,
> in a similar way to how aggregates and GROUPING() expressions are
> handled. But a number of the changes from the previous patch are no
> longer necessary, so overall, this version of the patch is slightly
> smaller.

+1

> > I think the name of function pg_merge_when_clause() can be improved.
> > How about pg_merge_when_clause_ordinal().
> >
>
> That's a bit of a mouthful, but I don't have a better idea right now.
> I've left the names alone for now, in case something better occurs to
> anyone.

+1. How do we make sure we don't forget that it needs to be named
better. Perhaps a TODO item within the patch will help.

> > In the doc page of MERGE, you've moved the 'with_query' from the
> > bottom of Parameters section to the top of that section. Any reason
> > for this? Since the Parameters section is quite large, for a moment I
> > thought the patch was _adding_ the description of 'with_query'.
> >
>
> Ah yes, I was just making the order consistent with the
> INSERT/UPDATE/DELETE pages. That could probably be committed
> separately.

I don't think that's necessary, if it improves consistency with related docs.

> > +/*
> > + * Merge support functions should only be called directly from a MERGE
> > + * command, and need access to the parent ModifyTableState.  The parser
> > + * should have checked that such functions only appear in the RETURNING
> > + * list of a MERGE, so this should never fail.
> > + */
> > +if (IsMergeSupportFunction(funcid))
> > +{
> > +if (!state->parent ||
> > +!IsA(state->parent, ModifyTableState) ||
> > +((ModifyTableState *) state->parent)->operation != CMD_MERGE)
> > +elog(ERROR, "merge support function called in non-merge 
> > context");
> >
> > As the comment says, this is an unexpected condition, and should have
> > been caught and reported by the parser. So I think it'd be better to
> > use an Assert() here. Moreover, there's ERROR being raised by the
> > pg_merge_action() and pg_merge_when_clause() functions, when they
> > detect the function context is not appropriate.
> >
> > I found it very innovative to allow these functions to be called only
> > in a certain part of certain SQL command. I don't think  there's a
> > precedence for this in  Postgres; I'd be glad to learn if there are
> > other functions that Postgres exposes this way.
> >
> > -EXPR_KIND_RETURNING,/* RETURNING */
> > +EXPR_KIND_RETURNING,/* RETURNING in INSERT/UPDATE/DELETE */
> > +EXPR_KIND_MERGE_RETURNING,  /* RETURNING in MERGE */
> >
> > Having to invent a whole new ParseExprKind enum, feels like a bit of
> > an overkill. My only objection is that this is exactly like
> > EXPR_KIND_RETURNING, hence EXPR_KIND_MERGE_RETURNING needs to be dealt
> > with exactly in as many places. But I don't have any alternative
> > proposals.
> >
>
> That's all gone now from the new patch, since there is no longer any
> restriction on where these functions can appear.

I believe this elog can be safely turned into an Assert.

+switch (mergeActionCmdType)
 {
-CmdType commandType = relaction->mas_action->commandType;

+case CMD_INSERT:

+default:
+elog(ERROR, "unrecognized commandType: %d", (int)
mergeActionCmdType);

The same treatment can be applied to the elog(ERROR) in pg_merge_action().

> > +CREATE FUNCTION merge_into_sq_target(sid int, balance int, delta int,
> > + OUT action text, OUT tid int,
> > OUT new_balance int)
> > +LANGUAGE sql AS
> > +$$
> > +MERGE 

Re: MERGE ... RETURNING

2023-07-11 Thread Gurjeet Singh
On Tue, Jul 11, 2023 at 1:43 PM Gurjeet Singh  wrote:
>
> In the above hunk, if there's an exception/ERROR, I believe we should
> PG_RE_THROW(). If there's a reason to continue, we should at least set
> rslot = NULL, otherwise we may be returning an uninitialized value to
> the caller.

Excuse the brain-fart on my part. There's not need to PG_RE_THROW(),
since there's no PG_CATCH(). Re-learning the code's infrastructure
slowly :-)

Best regards,
Gurjeet
http://Gurje.et




Better help output for pgbench -I init_steps

2023-07-12 Thread Gurjeet Singh
These patches were created during an unrelated discussion about pgbench.

Please see emails [1] - [6] linked below, for the past discussion.

In brief:

> $ pgbench -i -I dtGvp -s 500

The init-steps are severely under-documented in pgbench --help output.
I think at least a pointer to the the pgbench docs should be mentioned
in the pgbench --help output; an average user may not rush to read the
code to find the explanation, but a hint to where to find more details
about what the letters in --init-steps mean, would save them a lot of
time.

Please see attached 4 variants of the patch. Variant 1 simply tells
the reader to consult pgbench documentation. The second variant
provides a description for each of the letters, as the documentation
does. The committer can pick  the one they find suitable.

The text ", in the specified order" is an important detail, that
should be included irrespective of the rest of the patch.

My preference would be to use the first variant, since the second one
feels too wordy for --help output. I believe we'll have to choose
between these two; the alternatives will not make anyone happy.

These two variants show the two extremes; bare minimum vs. everything
but the kitchen sink. So one may feel the need to find a middle ground
and provide a "sufficient, but not too much" variant. I have attempted
that in variants 3 and 4; also attached.

The third variant does away with the list of steps, and uses a
paragraph to describe the letters. And the fourth variant makes that
paragraph terse.

In the order of preference I'd choose variant 1, then 2. Variants 3
and 4 feel like a significant degradation from variant 2.

Attached samples.txt shows the snippets of --help output of each of
the variants/patches, for comparison.

In [6] below, Tristan showed preference for the second variant.

[1] My complaint about -I initi_steps being severely under-documented
in --help output
https://www.postgresql.org/message-id/CABwTF4XMdHTxemhskad41Vj_hp2nPgifjwegOqR52_8-wEbv2Q%40mail.gmail.com

[2] Tristan Partin agreeing with the complaint, and suggesting a patch
would be welcome
https://www.postgresql.org/message-id/CT8BC7RXT33R.3CHYIXGD5NVHK%40gonk

[3] Greg Smith agreeing and saying he'd welcome a few more words about
the init_steps in --help output
https://www.postgresql.org/message-id/CAHLJuCUp5_VUo%2BRJ%2BpSnxeiiZfcstRtTubRP8%2Bu8NEqmrbp4aw%40mail.gmail.com

[4] First set of patches
https://www.postgresql.org/message-id/CABwTF4UKv43ZftJadsxs8%3Da07BmA1U4RU3W1qbmDAguVKJAmZw%40mail.gmail.com

[5] Second set of patches
https://www.postgresql.org/message-id/CABwTF4Ww42arY1Q88_iaraVLxqSU%2B8Yb4oKiTT5gD1sineog9w%40mail.gmail.com

[6] Tristan showing preference for the second variant
https://www.postgresql.org/message-id/CTBN5E2K2YSJ.3QYXGZ09JZXIW%40gonk

+CC Tristan Partin and Greg Smith, since they were involved in the
initial thread.

Best regards,
Gurjeet
http://Gurje.et
 variant-1-brief-pointer-to-docs.patch
  -i, --initialize invokes initialization mode
  -I, --init-steps=[dtgGvpf]+ (default "dtgvp")
   run selected initialization steps, in the specified 
order
   see pgbench documentation for a description of these 
steps
  -F, --fillfactor=NUM set fill factor

 variant-2-detailed-description.patch
  -i, --initialize invokes initialization mode
  -I, --init-steps=[dtgGvpf]+ (default "dtgvp")
   run selected initialization steps, in the specified 
order
   d: Drop any existing pgbench tables
   t: Create the tables used by the standard pgbench 
scenario
   g: Generate data, client-side
   G: Generate data, server-side
   v: Invoke VACUUM on the standard tables
   p: Create primary key indexes on the standard tables
   f: Create foreign key constraints between the 
standard tables
  -F, --fillfactor=NUM set fill factor

 variant-3-details-not-list.patch
  -i, --initialize invokes initialization mode
  -I, --init-steps=[dtgGvpf]+ (default "dtgvp")
   run selected initialization steps, in the specified 
order.
   These steps operate on standard tables used by 
pgbench
   'd' drops the tables, 't' creates the tables, 'g' 
generates
   the data on client-side, 'G' generates data on 
server-side,
   'v' vaccums the tables, 'p' creates primary key 
constraints,
   and 'f' creates foreign key constraints
  -F, --fillfactor=NUM set fill factor

 variant-4-terse-details-not-list.patch
  -i, --initialize invokes initialization 

Re: Better help output for pgbench -I init_steps

2023-07-12 Thread Gurjeet Singh
On Wed, Jul 12, 2023 at 3:08 AM Peter Eisentraut  wrote:
>
> On 12.07.23 09:42, Gurjeet Singh wrote:
> > These two variants show the two extremes; bare minimum vs. everything
> > but the kitchen sink. So one may feel the need to find a middle ground
> > and provide a "sufficient, but not too much" variant. I have attempted
> > that in variants 3 and 4; also attached.
>
> If you end up with variant 3 or 4, please use double quotes instead of
> single quotes.

Will  do.

I believe you're suggesting this because in the neighboring help text
the string literals use double quotes. I see that other utilities,
such as psql also use double quotes in help  text.

If there's a convention, documented somewhere in our sources, I'd love
to know and learn other conventions.

Best regards,
Gurjeet
http://Gurje.et




Re: CommandStatus from insert returning when using a portal.

2023-07-12 Thread Gurjeet Singh
On Wed, Jul 12, 2023 at 1:03 PM Dave Cramer  wrote:
>
> With a simple insert such as
>
> INSERT INTO test_table (cnt) VALUES (1), (2) RETURNING id
>
> if a portal is used to get the results then the CommandStatus is not returned 
> on the execute only when the portal is closed. After looking at this more it 
> is really after all of the data is read which is consistent if you don't use 
> a portal, however it would be much more useful if we received the 
> CommandStatus after the insert was completed and before the data
>
> Obviously I am biased by the JDBC API which would like to have
>
> PreparedStatement.execute() return the number of rows inserted without having 
> to wait to read all of the rows returned

I believe if RETURNING clause is use, the protocol-level behaviour of
INSERT is expected to match that of SELECT. If the SELECT command
behaves like that (resultset followed by CommandStatus), then I'd say
the INSERT RETURNING is behaving as expected.

Best regards,
Gurjeet
http://Gurje.et




Re: Duplicated LLVMJitHandle->lljit assignment?

2023-07-12 Thread Gurjeet Singh
On Wed, Jul 12, 2023 at 5:22 PM Matheus Alcantara  wrote:
>
> I was reading the jit implementation and I notice that the lljit field of
> LLVMJitHandle is being assigned twice on llvm_compile_module function, is this
> correct? I'm attaching a supposed fixes that removes  the second assignment. I
> ran meson test and all tests have pass.

-handle->lljit = compile_orc;

LGTM.

Best regards,
Gurjeet
http://Gurje.et




Re: MERGE ... RETURNING

2023-07-13 Thread Gurjeet Singh
On Thu, Jul 13, 2023 at 8:38 AM Dean Rasheed  wrote:
>
> On Tue, 11 Jul 2023 at 21:43, Gurjeet Singh  wrote:

> >  { oid => '9499', descr => 'command type of current MERGE action',
> > -  proname => 'pg_merge_action',  provolatile => 'v',
> > +  proname => 'pg_merge_action',  provolatile => 'v', proparallel => 'r',
> > 
> >  { oid => '9500', descr => 'index of current MERGE WHEN clause',
> > -  proname => 'pg_merge_when_clause',  provolatile => 'v',
> > +  proname => 'pg_merge_when_clause',  provolatile => 'v', proparallel => 
> > 'r',
> > 
> >
> > I see that you've now set proparallel of these functions to 'r'. I'd
> > just like to understand how you got to that conclusion.
> >
>
> Now that these functions can appear in subqueries in the RETURNING
> list, there exists the theoretical possibility that the subquery might
> use a parallel plan (actually that can't happen today, for any query
> that modifies data, but maybe someday it may become a possibility),
> and it's possible to use these functions in a SELECT query inside a
> PL/pgSQL function called from the RETURNING list, which might consider
> a parallel plan. Since these functions rely on access to executor
> state that isn't copied to parallel workers, they must be run on the
> leader, hence I think PARALLEL RESTRICTED is the right level to use. A
> similar example is pg_trigger_depth().

Thanks for the explanation. That helps.

Best regards,
Gurjeet
http://Gurje.et




Re: Fix search_path for all maintenance commands

2023-07-13 Thread Gurjeet Singh
On Thu, Jul 13, 2023 at 11:56 AM Jeff Davis  wrote:
>
> The current approach seemed to get support from Noah, Nathan, and Greg
> Stark.
>
> Concerns were raised by Gurjeet, Tom, and Robert in the 16 cycle; but

I didn't see Tom's or Robert's concerns raised in this thread. I see
now that for some reason there are two threads with slightly different
subjects. I'll catch-up on that, as well.

The other thread's subject: "pgsql: Fix search_path to a safe value
during maintenance operations"

> I'm not sure whether those objections were specific to the 16 cycle or
> whether they are objections to the approach entirely. Comments?

The approach seems good to me. My concern is with this change's
potential to cause an extended database outage. Hence sending it out
as part of v16, without any escape hatch for the DBA, is my objection.

It it were some commercial database, we would have simply introduced a
hidden event, or a GUC, with default off. But a GUC for this feels too
heavy handed.

Perhaps we can provide an escape hatch as follows (warning, pseudocode ahead).

> if (first_element(search_path) != 
> "dont_override_search_patch_for_maintenance")
>  SetConfigOption("search_path", GUC_SAFE_SEARCH_PATH, ...);

So, if someone desperately wants to just plow through the maintenance
command, and are not ready or able to fix their dependence on their
search_path, the community can show them this escape-hatch.

Best regards,
Gurjeet
http://Gurje.et




Re: Fix search_path for all maintenance commands

2023-07-13 Thread Gurjeet Singh
On Thu, Jul 13, 2023 at 1:37 PM David G. Johnston
 wrote:
>
>  I'm against simply breaking the past without any recourse as what we did for 
> pg_dump/pg_restore still bothers me.

I'm sure this is tangential, but can you please provide some
context/links to the change you're referring to here.

Best regards,
Gurjeet
http://Gurje.et




Re: harmonize password reuse in vacuumdb, clusterdb, and reindexdb

2023-07-18 Thread Gurjeet Singh
On Mon, Jul 17, 2023 at 1:47 PM Nathan Bossart  wrote:
>
> Here is a new version of the patch in which I've updated this comment as
> proposed.  Gurjeet, do you have any other concerns about this patch?

With the updated comment, the patch looks good to me.

Best regards,
Gurjeet
http://Gurje.et




Re: There should be a way to use the force flag when restoring databases

2023-07-19 Thread Gurjeet Singh
On Tue, Jul 18, 2023 at 12:53 AM Joan  wrote:
>
> Since posgres 13 there's the option to do a FORCE when dropping a database 
> (so it disconnects current users) Documentation here: 
> https://www.postgresql.org/docs/current/sql-dropdatabase.html
>
> I am currently using dir format for the output
>pg_dump -d "bdname" -F d -j 4 -v -f /tmp/dir
>
> And restoring the database with
>   pg_restore -d postgres -C -c --exit-on-error -F d -j 3 -v /tmp/dir
>
> Having an option to add the FORCE option to either the generated dump by 
> pg_dump, or in the pg_restore would be very useful when restoring the 
> databases to another servers so it would avoid having to do scripting.
>
> In my specific case I am using this to refresh periodically a development 
> environment with data from production servers for a small database (~200M).

Making force-drop a part of pg_dump output may be dangerous, and not
provide much flexibility at restore time.

Adding a force option to pg_restore feels like providing the right tradeoff.

The docs for 'pg_restore --create` say "Create the database before
restoring into it. If --clean is also specified, drop and recreate the
target database before connecting to it."

If we provided a force option, it may then additionally say: "If the
--clean and --force options are specified, DROP DATABASE ... WITH
FORCE command will be used to drop the database."

Using WITH FORCE is not a guarantee, as the DROP DATABASE docs clarify
the conditions under which it may fail.

Best regards,
Gurjeet
http://Gurje.et




Re: Issue in _bt_getrootheight

2023-07-19 Thread Gurjeet Singh
On Tue, Jul 11, 2023 at 9:35 AM Ahmed Ibrahim
 wrote:
>
> We have been working on the pg_adviser extension whose goal is to suggest 
> indexes by creating virtual/hypothetical indexes and see how it affects the 
> query cost.
>
> The hypothetical index shouldn't take any space on the disk (allocates 0 
> pages) so we give it the flag INDEX_CREATE_SKIP_BUILD.
> But the problem comes from here when the function get_relation_info is called 
> in planning stage, it tries to calculate the B-Tree height by calling 
> function _bt_getrootheight, but the B-Tree is not built at all, and its 
> metadata page (which is block 0 in our case) doesn't exist, so this returns 
> error that it cannot read the page (since it doesn't exist).
>
> I tried to debug the code and found that this feature was introduced in 
> version 9.3 under this commit [1]. I think that in the code we need to check 
> if it's a B-Tree index AND the index is built/have some pages, then we can go 
> and calculate it otherwise just put it to -1

> I mean instead of this
> if (info->relam == BTREE_AM_OID)
> {
> /* For btrees, get tree height while we have the index open */
> info->tree_height = _bt_getrootheight(indexRelation);
> }
> else
> {
>  /* For other index types, just set it to "unknown" for now */
> info->tree_height = -1;
> }
>
> The first line should be
> if (info->relam == BTREE_AM_OID && info->pages > 0)
> or use the storage manager (smgr) to know if the first block exists.

I think the better method would be to calculate the index height
*after* get_relation_info_hook is called. That way, instead of the
server guessing whether or not an index is hypothetical it can rely on
the index adviser's notion of which index is hypothetical. The hook
implementer has the opportunity to not only mark the
indexOptInfo->hypothetical = true, but also calculate the tree height,
if they can.

Please see attached the patch that does this. Let me know if this patch helps.

Best regards,
Gurjeet
http://Gurje.et


calculate-index-height-after-calling-get_relation_info_hook.patch
Description: Binary data


Re: There should be a way to use the force flag when restoring databases

2023-07-20 Thread Gurjeet Singh
On Thu, Jul 20, 2023 at 2:10 AM Daniel Gustafsson  wrote:
>
> > On 19 Jul 2023, at 19:28, Gurjeet Singh  wrote:
> >
> > The docs for 'pg_restore --create` say "Create the database before
> > restoring into it. If --clean is also specified, drop and recreate the
> > target database before connecting to it."
> >
> > If we provided a force option, it may then additionally say: "If the
> > --clean and --force options are specified, DROP DATABASE ... WITH
> > FORCE command will be used to drop the database."
>
> pg_restore --clean refers to dropping any pre-existing database objects and 
> not
> just databases, but --force would only apply to databases.
>
> I wonder if it's worth complicating pg_restore with that when running dropdb
> --force before pg_restore is an option for those wanting to use WITH FORCE.

Fair point. But the same argument could've been applied to --clean
option, as well; why overload the meaning of --clean and make it drop
database, when a dropdb before pg_restore was an option.

IMHO, if pg_restore offers to drop database, providing an option to
the user to do it forcibly is not that much of a stretch, and within
reason for the user to expect it to be there, like Joan did.

Best regards,
Gurjeet
http://Gurje.et




Re: MERGE ... RETURNING

2023-07-20 Thread Gurjeet Singh
On Fri, Jul 14, 2023 at 1:55 AM Dean Rasheed  wrote:
>
> On Thu, 13 Jul 2023 at 20:14, Jeff Davis  wrote:
> >
> > On Thu, 2023-07-13 at 18:01 +0100, Dean Rasheed wrote:
> > > For some use cases, I can imagine allowing OLD/NEW.colname would mean
> > > you wouldn't need pg_merge_action() (if the column was NOT NULL), so
> > > I
> > > think the features should work well together.
> >
> > For use cases where a user could do it either way, which would you
> > expect to be the "typical" way (assuming we supported the new/old)?
> >
> >   MERGE ... RETURNING pg_merge_action(), id, val;
> >
> > or
> >
> >   MERGE ... RETURNING id, OLD.val, NEW.val;
> >
> > ?
> >
>
> I think it might depend on whether OLD.val and NEW.val were actually
> required, but I think I would still probably use pg_merge_action() to
> get the action, since it doesn't rely on specific table columns being
> NOT NULL.

+1. It would be better to expose the action explicitly, rather than
asking the user to deduce it based on the old and new values of a
column. The server providing that value is better than letting users
rely on error-prone methods.

> I found a 10-year-old thread discussing adding support for OLD/NEW to
> RETURNING [1],

Thanks for digging up that thread. An important concern brought up in
that thread was how the use of names OLD and NEW will affect plpgsql
(an possibly other PLs) trigger functions, which rely on specific
meaning for those names. The names BEFORE and AFTER, proposed there
are not as intuitive as OLD/NEW for the purpose of identifying old and
new versions of the row, but I don't have a better proposal. Perhaps
PREVIOUS and CURRENT?

> but it doesn't look like anything close to a
> committable solution was developed, or even a design that might lead
> to one. That's a shame, because there seemed to be a lot of demand for
> the feature,

+1

> > I am still bothered that pg_merge_action() is so context-sensitive.
> > "SELECT pg_merge_action()" by itself doesn't make any sense, but it's
> > allowed in the v8 patch. We could make that a runtime error, which
> > would be better, but it feels like it's structurally wrong. This is not
> > an objection, but it's just making me think harder about alternatives.
> >
> > Maybe instead of a function it could be a special table reference like:
> >
> >   MERGE ... RETURNING MERGE.action, MERGE.action_number, id, val?

I believe Jeff meant s/action_number/when_number/. Not that we've
settled on a name for this virtual column.

> Well, that's a little more concise, but I'm not sure that it really
> buys us that much, to be worth the extra complication.

After considering the options, and their pros and cons (ease of
implementation, possibility of conflict with SQL spec, intuitiveness
of syntax), I'm now strongly leaning towards the SQL syntax variant.
Exposing the action taken via a context-sensitive function feels
kludgy, when compared to Jeff's proposed SQL syntax. Don't get me
wrong, I still feel it was very clever how you were able to make the
function context sensitive, and make it work in expressions deeper in
the subqueries.

Plus, if we were able to make it work as SQL syntax, it's very likely
we can use the same technique to implement BEFORE and AFTER behaviour
in UPDATE ... RETURNING that the old thread could not accomplish a
decade ago.

> Presumably
> something in the planner would turn that into something the executor
> could handle, which might just end up being the existing functions
> anyway.

If the current patch's functions can serve the needs of the SQL syntax
variant, that'd be a neat win!

Best regards,
Gurjeet
http://Gurje.et




Re: MERGE ... RETURNING

2023-07-20 Thread Gurjeet Singh
On Mon, Jul 17, 2023 at 12:43 PM Jeff Davis  wrote:
>
> On Fri, 2023-07-14 at 09:55 +0100, Dean Rasheed wrote:
> > I found a 10-year-old thread discussing adding support for OLD/NEW to
> > RETURNING [1], but it doesn't look like anything close to a
> > committable solution was developed, or even a design that might lead
> > to one. That's a shame, because there seemed to be a lot of demand
> > for
> > the feature, but it's not clear how much effort it would be to
> > implement.
>
> It looks like progress was made in the direction of using a table alias
> with executor support to bring the right attributes along.

That patch introduced RTE_ALIAS to carry that info through to the
executor, and having to special-case that that in many places was seen
as a bad thing.

> There was some concern about how exactly the table alias should work
> such that it doesn't look too much like a join. Not sure how much of a
> problem that is.

My understanding of that thread is that the join example Robert shared
was for illustrative purposes only, to show that executor already has
enough information to produce the desired output, and to show that
it's a matter of tweaking the parser and planner to tell the executor
what output to produce. But later reviewers pointed out that it's not
that simple (example was given of ExecDelete performing
pullups/working hard to get the correct values of the old version of
the row).

The concerns were mainly around use of OLD.* and NEW.*, too much
special-casing of RTE_ALIAS, and then the code quality of the patch
itself.

> > > Maybe instead of a function it could be a special table reference
> > > like:
> > >
> > >   MERGE ... RETURNING MERGE.action, MERGE.action_number, id, val?
> > >
> >
> > Well, that's a little more concise, but I'm not sure that it really
> > buys us that much, to be worth the extra complication. Presumably
> > something in the planner would turn that into something the executor
> > could handle, which might just end up being the existing functions
> > anyway.
>
> The benefits are:
>
> 1. It is naturally constrained to the right context.

+1

> I'm not sure how much extra complication it would cause, though.

If that attempt with UPDATE RETURNING a decade ago is any indication,
it's probably a tough one.

Best regards,
Gurjeet
http://Gurje.et




Re: table_open/table_close with different lock mode

2023-07-20 Thread Gurjeet Singh
On Thu, Jul 20, 2023 at 11:38 PM Junwang Zhao  wrote:
>
> On Fri, Jul 21, 2023 at 2:26 PM Michael Paquier  wrote:
> >
> > On Fri, Jul 21, 2023 at 02:05:56PM +0800, Junwang Zhao wrote:
> > > I noticed there are some places calling table_open with
> > > RowExclusiveLock but table_close with NoLock, like in function
> > > toast_save_datum.
> > >
> > > Can anybody explain the underlying logic, thanks in advance.
> >
> > This rings a bell.  This is a wanted behavior, see commit f99870d and
> > its related thread:
> > https://postgr.es/m/17268-d2fb426e0895a...@postgresql.org
> >
>
> I see this patch, so all the locks held by a transaction will be released
> at the commit phase, right? Can you show me where the logic is located?

The NoLock is simple a marker that tells the underlying machinery to
not bother releasing any locks. As a matter of fact, you can pass
NoLock in *_open() calls, too, to indicate that you don't want any new
locks, perhaps because the transaction has already taken an
appropriate lock on the object.

As for lock-releasing codepath at transaction end, see
CommitTransaction() in xact.c, and specifically at the
ResourceOwnerRelease() calls in there.

Best regards,
Gurjeet
http://Gurje.et




Re: Issue in _bt_getrootheight

2023-07-24 Thread Gurjeet Singh
On Fri, Jul 21, 2023 at 10:42 AM Tom Lane  wrote:
>
> Gurjeet Singh  writes:
> > Please see attached the patch that does this. Let me know if this patch 
> > helps.
>
> I don't like this patch one bit, because it adds a lot of overhead
> (i.e., an extra index_open/close cycle for every btree index in every
> query) to support a tiny minority use-case.

I anticipated the patch's performance impact may be a concern, but
before addressing it I wanted to see if the patch actually helped
Index Adviser. Ahmed has confirmed that my proposed patch works for
him.

I believe the additional index_open() would not affect the performance
significantly, since the very same indexes were index_open()ed just
before calling the get_relation_info_hook. All the relevant caches
would be quite fresh because of the index_open() in the same function
above. And since the locks taken on these indexes haven't been
released, we don't have to work hard to take any new locks (hence the
index_open() with NoLock flag).

> How come we don't
> already know whether the index is hypothetical at the point where
> _bt_getrootheight is called now?

Because the 'hypthetical' flag is not stored in catalogs, and that's
okay; see below.

At that point, the only indication that an index may be a hypothetical
index is if RelationGetNumberOfBlocks() returns 0 for it, and that's
what Ahmed's proposed patch relied on. But I think extrapolating that
info->pages==0 implies it's a hypothetical index, is stretching that
assumption too far.

> Actually, looking at the existing comment at the call site:
>
> /*
>  * Allow a plugin to editorialize on the info we obtained from the
>  * catalogs.  Actions might include altering the assumed relation size,
>  * removing an index, or adding a hypothetical index to the indexlist.
>  */
> if (get_relation_info_hook)
> (*get_relation_info_hook) (root, relationObjectId, inhparent, rel);
>
> reminds me that the design intention was that hypothetical indexes
> would get added to the list by get_relation_info_hook itself.
> If that's not how the index adviser is operating, maybe we need
> to have a discussion about that.

Historically, to avoid having to hand-create the IndexOptInfo and risk
getting something wrong, the Index Adviser has used index_create() to
create a full-blown btree index, (sans that actual build step, with
skip_build = true), and saving the returned OID. This ensured that all
the catalog entries were in place before it called the
standard_planner(). This way Postgres would build IndexOptInfo from
the entries in the catalog, as usual. Then, inside the
get_relation_info_hook() callback, Index Adviser identifies these
virtual indexes by their OID, and at that point marks them with
hypothetical=true.

After planning is complete, the Index Adviser scans the plan to find
any IndexScan objects that have indexid matching the saved OIDs.

Index Adviser performs the whole thing in a subtransaction, which gets
rolled back. So the hypothetical indexes are not visible to any other
transaction, ever.

Assigning OID to a hypothetical index is necessary, and I believe
index_create() is the right way to do it. In fact, in the 9.1 cycle
there was a bug fixed (a2095f7fb5, where the hypothetical flag was
also invented), to solve precisely this problem; to allow the Index
Adviser to use OIDs to identify hypothetical indexes that were
used/chosen by the planner.

But now I believe this architecture of the Index Adviser needs to
change, primarily to alleviate the performance impact of creating
catalog entries, subtransaction overhead, and the catalog bloat caused
by index_create() (and then rolling back the subtransaction). As part
of this architecture change, the Index Adviser will have to cook up
IndexOptInfo objects and append them to the relation. And that should
line up with the design intention you mention.

But the immediate blocker is how to assign OIDs to the hypothetical
indexes so that all hypothetical indexes chosen by the planner can be
identified by the Index Adviser. I'd like the Index Adviser to work on
read-only /standby nodes as well, but that wouldn't be possible
because calling GetNewObjectId() is not allowed during recovery. I see
that HypoPG uses a neat little hack [1]. Perhaps Index Adviser will
also have to resort to that trick.

[1]: hypo_get_min_fake_oid() finds the usable oid range below
FirstNormalObjectId
https://github.com/HypoPG/hypopg/blob/57d832ce7a2937fe7d42b113c7e95dd1f129795b/hypopg.c#L458

Best regards,
Gurjeet
http://Gurje.et




Re: psql not responding to SIGINT upon db reconnection

2023-07-24 Thread Gurjeet Singh
On Mon, Jul 24, 2023 at 9:26 AM Tristan Partin  wrote:

> attached patch

+/*
+ * Restore the default SIGINT behavior while within libpq.
Otherwise, we
+ * can never exit from polling for the database connection. Failure to
+ * restore is non-fatal.
+ */
+newact.sa_handler = SIG_DFL;
+rc = sigaction(SIGINT, &newact, &oldact);

There's no action taken if rc != 0. It doesn't seem right to
continue as if everything's fine when the handler registration fails.
At least a warning is warranted, so that the user reports such
failures to the community.

Best regards,
Gurjeet
http://Gurje.et




Re: MERGE ... RETURNING

2023-07-25 Thread Gurjeet Singh
On Fri, Jul 21, 2023 at 7:17 PM Dean Rasheed  wrote:
>
> On Mon, 17 Jul 2023 at 20:43, Jeff Davis  wrote:
> >
> > > > Maybe instead of a function it could be a special table reference
> > > > like:
> > > >
> > > >   MERGE ... RETURNING MERGE.action, MERGE.action_number, id, val?
> > > >
> > The benefits are:
> >
> > 1. It is naturally constrained to the right context. It doesn't require
> > global variables and the PG_TRY/PG_FINALLY, and can't be called in the
> > wrong contexts (like SELECT).
> >
> > 2. More likely to be consistent with eventual support for NEW/OLD
> > (actually BEFORE/AFTER for reasons the prior thread discussed).
> >
>
> Thinking about this some more, I think that the point about
> constraining these functions to the right context is a reasonable one,
> and earlier versions of this patch did that better, without needing
> global variables or a PG_TRY/PG_FINALLY block.
>
> Here is an updated patch that goes back to doing it that way. This is
> more like the way that aggregate functions and GROUPING() work, in
> that the parser constrains the location from which the functions can
> be used, and at execution time, the functions rely on the relevant
> context being passed via the FunctionCallInfo context.
>
> It's still possible to use these functions in subqueries in the
> RETURNING list, but attempting to use them anywhere else (like a
> SELECT on its own) will raise an error at parse time. If they do
> somehow get invoked in a non-MERGE context, they will elog an error
> (again, just like aggregate functions), because that's a "shouldn't
> happen" error.
>
> This does nothing to be consistent with eventual support for
> BEFORE/AFTER, but I think that's really an entirely separate thing,

+1

> From a user perspective, writing something like "BEFORE.id" is quite
> natural, because it's clear that "id" is a column, and "BEFORE" is the
> old state of the table. Writing something like "MERGE.action" seems a
> lot more counter-intuitive, because "action" isn't a column of
> anything (and if it was, I think this syntax would potentially cause
> even more confusion).
>
> So really, I think "MERGE.action" is an abuse of the syntax,
> inconsistent with any other SQL syntax, and using functions is much
> more natural, akin to GROUPING(), for example.

There seems to be other use cases which need us to invent a method to
expose a command-specific alias. See Tatsuo Ishii's call for help in
his patch for Row Pattern Recognition [1].


I was not able to find a way to implement expressions like START.price
(START is not a table alias). Any suggestion is greatly appreciated.


It looks like the SQL standard has started using more of such
context-specific keywords, and I'd expect such keywords to only
increase in future, as the SQL committee tries to introduce more
features into the standard.

So if MERGE.action is not to your taste, perhaps you/someone can
suggest an alternative that doesn't cause a confusion, and yet
implementing it would open up the way for more such context-specific
keywords.

I performed the review vo v9 patch by comparing it to v8 and v7
patches, and then comparing to HEAD.

The v9 patch is more or less a complete revert to v7 patch, plus the
planner support for calling the merge-support functions in subqueries,
parser catching use of merge-support functions outside MERGE command,
and name change for one of the support functions.

But reverting to v7 also means that some of my gripes with that
version also return; e.g. invention of EXPR_KIND_MERGE_RETURNING. And
as noted in v7 review, I don't have a better proposal.

Function name changed from pg_merge_when_clause() to
pg_merge_when_clause_number(). That's better, even though it's a bit
of mouthful.

Doc changes (compared to v7) look good.

The changes made to tests (compared to v7) are for the better.

- * Uplevel PlaceHolderVars and aggregates are replaced, too.
+ * Uplevel PlaceHolderVars, aggregates, GROUPING() expressions and merge
+ * support functions are replaced, too.

Needs Oxford comma: s/GROUPING() expressions and/GROUPING() expressions, and/

+pg_merge_action(PG_FUNCTION_ARGS)
+{
...
+relaction = mtstate->mt_merge_action;
+if (relaction)
+{
..
+}
+
+PG_RETURN_NULL();
+}

Under what circumstances would the relaction be null? Is it okay to
return NULL from this function if relaction is null, or is it better
to throw an error? These questions apply to the
pg_merge_when_clause_number() function as well.

[1]: Row pattern recognition
https://www.postgresql.org/message-id/flat/20230625.210509.1276733411677577841.t-ishii%40sranhm.sra.co.jp

Best regards,
Gurjeet
http://Gurje.et




  1   2   >