Re: [PATCH] minor reloption regression tests improvement

2022-03-07 Thread Nikolay Shaplov
В письме от понедельник, 7 марта 2022 г. 20:04:49 MSK пользователь Greg Stark 
написал:
> I don't think this is worth spending time adding tests for. I get what
> you're saying that this is at least semi-intentional behaviour and
> desirable behaviour so it should have tests ensuring that it continues
> to work. But it's not documented behaviour and the test is basically
> testing that the implementation is this specific implementation.
> 
> I don't think the test is really a bad idea but neither is it really
> very useful and I think it's not worth having people spend time
> reviewing and discussing. I'm leaning to saying this patch is
> rejected.

This is a regression test. To test if behaviour brocken or not.

Actually I came to the idea of the test when I wrote my big reloption patch. 
I've broken this behaviour by mistake and  did not notice it as it have not 
been properly tested. So I decided it would be goo to add test to it before 
adding and big patches.

-- 
Nikolay Shaplov aka Nataraj
Fuzzing Engineer at Postgres Professional
Matrix IM: @dhyan:nataraj.su







Re: [PATCH][PROPOSAL] Refuse setting toast.* reloptions when TOAST table does not exist

2018-04-10 Thread Nikolay Shaplov
В письме от 10 апреля 2018 08:55:52 пользователь David Steele написал:
> On 1/25/18 12:27 PM, Nikolay Shaplov wrote:
> > В письме от 25 января 2018 11:29:34 пользователь Tom Lane написал:
> >> Alvaro Herrera  writes:
> >>> Tom Lane wrote:
> >>>> Well, maybe the right answer is to address that.  It's clear to me
> >>>> why that would happen if we store these things as reloptions on the
> >>>> toast table, but can't they be stored on the parent table?
> >>> 
> >>> Actually, Nikolay provided a possible solution: if you execute ALTER
> >>> TABLE SET (toast.foobar = xyz), and a toast table doesn't exist, create
> >>> one at that point.
> >> 
> >> That adds a lot of overhead if you never actually need the toast table.
> > 
> > I think this overhead case is not that terrible if it is properly warned
> > ;-)> 
> >> Still, maybe it's an appropriate amount of effort compared to the size
> >> of the use-case for this.
> > 
> > If you came to some final conclustion, please close the commiffest item
> > with "Return with feedback" resolution, and I write another patch...
> 
> I think this patch should be marked Returned with Feedback since it
> appears there is no consensus on whether it is useful or correct, so I
> have done that.
Exactly!

But I'd like to know what kind of feedback is it :-)
What conclusion have been reached (I did not got it)

Otherwise I would not know how to rewrite this patch.

I would suggest: create a TOAST relation whenever toast.* options is set, but 
give a warning it this relation will not be used for data storage (i.e. there 
is no toastable columns in the table)

But I need some confirmation, in order not to write patch in vain again :-)

> 
> If I got it wrong I'm happy to move it to the next CF in Waiting for
> Author state instead.
> 
> Thanks,

-- 
Do code for fun.

signature.asc
Description: This is a digitally signed message part.


Re: [PATCH][PROPOSAL] Add enum releation option type

2019-09-13 Thread Nikolay Shaplov
В письме от четверг, 5 сентября 2019 г. 11:42:27 MSK пользователь Alvaro 
Herrera from 2ndQuadrant написал:
> After looking closer once again, I don't like this patch.
> 
> I think the FOOBAR_ENUM_DEF defines serve no purpose, other than
> source-code placement next to the enum value definitions.  I think for
> example check_option, living in reloptions.c, should look like this:

This sounds as a good idea, I tried it, but did not succeed.

When I do as you suggest I get a bunch of warnings, and more over it, tests do 
not pass afterwards.

reloptions.c:447:3: warning: braces around scalar initializer
   {
   ^
reloptions.c:447:3: warning: (near initialization for 
‘enumRelOpts[0].members’)
reloptions.c:448:4: warning: braces around scalar initializer
{ "on",  GIST_OPTION_BUFFERING_ON },
^
reloptions.c:448:4: warning: (near initialization for 
‘enumRelOpts[0].members’)
reloptions.c:448:4: warning: initialization from incompatible pointer type
reloptions.c:448:4: warning: (near initialization for 
‘enumRelOpts[0].members’)

and so on, see full warning list attached.

I've played with it around, and did some googling, but without much success.
If we are moving this way (an this way seems to be good one), I need you help, 
because this thing is beyond my C knowledge, I will not manage it myself.

I also attached a diff of what I have done to get these warnings. It should be 
applied to latest version of patch we are discussing.
reloptions.c:447:3: warning: braces around scalar initializer
   {
   ^
reloptions.c:447:3: warning: (near initialization for ‘enumRelOpts[0].members’)
reloptions.c:448:4: warning: braces around scalar initializer
{"on",  GIST_OPTION_BUFFERING_ON },
^
reloptions.c:448:4: warning: (near initialization for ‘enumRelOpts[0].members’)
reloptions.c:448:4: warning: initialization from incompatible pointer type
reloptions.c:448:4: warning: (near initialization for ‘enumRelOpts[0].members’)
reloptions.c:448:4: warning: excess elements in scalar initializer
reloptions.c:448:4: warning: (near initialization for ‘enumRelOpts[0].members’)
reloptions.c:449:4: warning: braces around scalar initializer
{"off",  GIST_OPTION_BUFFERING_OFF },
^
reloptions.c:449:4: warning: (near initialization for ‘enumRelOpts[0].members’)
reloptions.c:449:4: warning: initialization from incompatible pointer type
reloptions.c:449:4: warning: (near initialization for ‘enumRelOpts[0].members’)
reloptions.c:449:4: warning: excess elements in scalar initializer
reloptions.c:449:4: warning: (near initialization for ‘enumRelOpts[0].members’)
reloptions.c:449:4: warning: excess elements in scalar initializer
reloptions.c:449:4: warning: (near initialization for ‘enumRelOpts[0].members’)
reloptions.c:450:4: warning: braces around scalar initializer
{"auto", GIST_OPTION_BUFFERING_AUTO },
^
reloptions.c:450:4: warning: (near initialization for ‘enumRelOpts[0].members’)
reloptions.c:450:4: warning: initialization from incompatible pointer type
reloptions.c:450:4: warning: (near initialization for ‘enumRelOpts[0].members’)
reloptions.c:450:4: warning: excess elements in scalar initializer
reloptions.c:450:4: warning: (near initialization for ‘enumRelOpts[0].members’)
reloptions.c:450:4: warning: excess elements in scalar initializer
reloptions.c:450:4: warning: (near initialization for ‘enumRelOpts[0].members’)
reloptions.c:451:4: warning: braces around scalar initializer
{ NULL }
^
reloptions.c:451:4: warning: (near initialization for ‘enumRelOpts[0].members’)
reloptions.c:451:4: warning: excess elements in scalar initializer
reloptions.c:451:4: warning: (near initialization for ‘enumRelOpts[0].members’)
diff --git a/.gitignore b/.gitignore
index 794e35b..37331c2 100644
diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c
index fffab3a..fcf4766 100644
--- a/src/backend/access/common/reloptions.c
+++ b/src/backend/access/common/reloptions.c
@@ -433,8 +433,6 @@ static relopt_real realRelOpts[] =
 	{{NULL}}
 };
 
-static relopt_enum_elt_def gist_buffering_enum_def[] =
-GIST_OPTION_BUFFERING_ENUM_DEF;
 static relopt_enum_elt_def view_check_option_enum_def[] =
 VIEW_OPTION_CHECK_OPTION_ENUM_DEF;
 static relopt_enum enumRelOpts[] =
@@ -446,8 +444,13 @@ static relopt_enum enumRelOpts[] =
 RELOPT_KIND_GIST,
 AccessExclusiveLock
 		},
-			gist_buffering_enum_def,
-			GIST_OPTION_BUFFERING_AUTO
+		{
+			{"on",		GIST_OPTION_BUFFERING_ON },
+			{"off",		GIST_OPTION_BUFFERING_OFF },
+			{"auto",	GIST_OPTION_BUFFERING_AUTO },
+			{ NULL }
+		},
+		GIST_OPTION_BUFFERING_AUTO
 	},
 	{
 		{
diff --git a/src/include/access/gist_private.h b/src/include/access/gist_private.h
index d586b04..047490a 100644
--- a/src/include/access/gist_private.h
+++ b/src/include/access/gist_private.h
@@ -379,24 +379,15 @@ typedef struct GISTBuildBuffers
 } GISTBuildBuffers;
 
 /*
- * Buffering is an enum option
- * gist_option_buffering_numeric_values defines a numeric representatio

Re: [PATCH] src/test/modules/dummy_index -- way to test reloptions from inside of access method

2019-09-18 Thread Nikolay Shaplov
В Fri, 2 Aug 2019 11:12:35 +1200
Thomas Munro  пишет:
 
> While moving this to the September CF, I noticed this failure:
> 
> test reloptions   ... FAILED   32 ms

Do you have any idea, how to reproduce this? I tried this patch on
current master, and did not get result you are talking about.
Is it still there for you BTW?





Re: [PATCH] src/test/modules/dummy_index -- way to test reloptions from inside of access method

2019-09-19 Thread Nikolay Shaplov
В письме от четверг, 19 сентября 2019 г. 17:32:03 MSK пользователь Michael 
Paquier написал:

> > src/test/modules/dummy_index_am directory check" I see a similar
> > failure with "ERROR:  unrecognized lock mode: 2139062143".  I changed
> 
> > that to a PANIC and got a core file containing this stack:
> A simple make check on the module reproduces the failure, so that's
> hard to miss.
For some reason it does not reproduce on my dev environment, but it not really 
important, since the core of the problem is found.
> 
> From what I can see it is not a problem caused directly by this
> module, specifically knowing that this test module is actually copying
> what bloom is doing when declaring its reloptions.  Take this example:
> CREATE EXTENSION bloom;
> CREATE TABLE tbloom AS
> SELECT
>   (random() * 100)::int as i1,
>   (random() * 100)::int as i2,
>   (random() * 100)::int as i3,
>   (random() * 100)::int as i4,
>   (random() * 100)::int as i5,
>   (random() * 100)::int as i6
> FROM
>generate_series(1,100);
> CREATE INDEX bloomidx ON tbloom USING bloom (i1,i2,i3)
>WITH (length=80, col1=2, col2=2, col3=4);
> ALTER INDEX bloomidx SET (length=100);
> 
> And then you get that:
> ERROR:  XX000: unrecognized lock mode: 2139062143
> LOCATION:  LockAcquireExtended, lock.c:756
> 
> So the options are registered in the relOpts array managed by
> reloptions.c but the data is not properly initialized.  Hence when
> looking at the lock needed we have an option match, but the lock
> number is incorrect, causing the failure.  It looks like there is no
> direct way to enforce the lockmode used for a reloption added via
> add_int_reloption which does the allocation to add the option to
> add_reloption(), but enforcing the value to be initialized fixes the
> issue:
> --- a/src/backend/access/common/reloptions.c
> +++ b/src/backend/access/common/reloptions.c
> @@ -658,6 +658,7 @@ allocate_reloption(bits32 kinds, int type, const
> char *name, const char *desc)
> newoption->kinds = kinds;
> newoption->namelen = strlen(name);
> newoption->type = type;
> +   newoption->lockmode = AccessExclusiveLock;
> MemoryContextSwitchTo(oldcxt);

What a good catch! dummy_index already proved to be useful ;-)


> I would think that initializing that to a sane default is something
> that we should do anyway, or is there some trick allowing the
> manipulation of relOpts I am missing? 

Yes I think AccessExclusiveLock is quite good default I think. Especially in 
the case when these options are not really used in real world ;-)

> Changing the relopts APIs in
> back-branches is a no-go of course, but we could improve that for
> 13~.

As you know I have plans for rewriting options engine and there would be same 
options code both for core Access Methods and for options for AM from 
extensions. So there would be API for setting lockmode...
But the way it is going right now, I am not sure it will reviewed to reach 
13...


PS. Michael, who will submit this lock mode patch? Hope you will do it? It 
should go separately from dummy_index for sure...




Re: [PATCH] src/test/modules/dummy_index -- way to test reloptions from inside of access method

2019-09-24 Thread Nikolay Shaplov
В Fri, 20 Sep 2019 20:58:27 +0900
Michael Paquier  пишет:


Sorry I am really slow to answer... I hope it is not too late.

> The GUCs are also basically not necessary, as you can just replace the
> various WARNING calls (please don't call elog on anything which can be
> reached by the user!) by lookups at reloptions in pg_class.  Once this
> is removed, the whole code gets more simple, and there is no point in
> having neither a separate header nor a different set of files and the
> size of the whole module gets really reduced.

Reading options from pg_class is not a good idea. We already do this in
reloption regression test. Here the thing is almost same...

My point of testing was to read these values from bytea right from
inside of the module. This is not exactly the same value as in pg_class.
It _should_ be the same. But nobody promised is _is_ the same. That is
why I was reading it right from relotions in-memory bytea, the same way
real access methods do it.

And then we came to a GUC variables. Because it we have five reloptions
and we print them all each time we change something, there would be
quite huge output.
It is ok when everything goes well. Comparing with 'expected' is cheap.
But is something goes wrong, then it would be very difficult to find
proper place in this output to deal with it.
So I created GUCs so we can get only one output in a row, not a whole
bunch.

These are my points.







Re: [PATCH] src/test/modules/dummy_index -- way to test reloptions from inside of access method

2019-09-24 Thread Nikolay Shaplov
В письме от вторник, 24 сентября 2019 г. 9:25:54 MSK пользователь Alvaro 
Herrera написал:

> 0003 looks useful, thanks for completing it.  I think it would be a good
> idea to test invalid values for each type of reloption too (passing
> floating point to integers, strings to floating point, and so on).

We already do it in reloption regression tests.

My idea was to test here only the things that can't be tested in regression 
tests, on in real indexes like bloom.






Re: [PATCH] Do not use StdRdOptions in Access Methods

2019-10-05 Thread Nikolay Shaplov
В Fri, 27 Sep 2019 17:24:49 +0900
Michael Paquier  пишет:

> > Looks like some good actionable feedback.  I've moved this patch to
> > September, and set it to "Waiting on Author".
>
> The patch is in this state for two months now, so I have switched it
> to "returned with feedback".  The latest patch does not apply, and it
> would require an update for the new test module dummy_index_am.

I've been thinking about this patch and came to a conclusion that it
would be better to split it to even smaller parts, so they can be
easily reviewed, one by one. May be even leaving most complex
Heap/Toast part for later.

This is first part of this patch. Here we give each Access Method it's
own option binary representation instead of StdRdOptions.

I think this change is obvious. Because, first, Access Methods do not
use most of the values defined in StdRdOptions.

Second this patch make Options structure code unified for all core
Access Methods. Before some AM used StdRdOptions, some AM used it's own
structure, now all AM uses own structures and code is written in the
same style, so it would be more easy to update it in future.

John Dent, would you join reviewing this part of the patch? I hope it
will be more easy now...


-- 
Software Developer: https://www.upwork.com/freelancers/~014a87e140ff02c0da
Body-oriented Therapist: https://vk.com/nataraj_rebalancing  (Russian)diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c
index b5072c0..33f770b 100644
--- a/src/backend/access/common/reloptions.c
+++ b/src/backend/access/common/reloptions.c
@@ -23,7 +23,7 @@
 #include "access/htup_details.h"
 #include "access/nbtree.h"
 #include "access/reloptions.h"
-#include "access/spgist.h"
+#include "access/spgist_private.h"
 #include "catalog/pg_type.h"
 #include "commands/defrem.h"
 #include "commands/tablespace.h"
diff --git a/src/backend/access/hash/hashpage.c b/src/backend/access/hash/hashpage.c
index 838ee68..eec2100 100644
--- a/src/backend/access/hash/hashpage.c
+++ b/src/backend/access/hash/hashpage.c
@@ -359,7 +359,7 @@ _hash_init(Relation rel, double num_tuples, ForkNumber forkNum)
 	data_width = sizeof(uint32);
 	item_width = MAXALIGN(sizeof(IndexTupleData)) + MAXALIGN(data_width) +
 		sizeof(ItemIdData);		/* include the line pointer */
-	ffactor = RelationGetTargetPageUsage(rel, HASH_DEFAULT_FILLFACTOR) / item_width;
+	ffactor = (BLCKSZ * HashGetFillFactor(rel) / 100) / item_width;
 	/* keep to a sane range */
 	if (ffactor < 10)
 		ffactor = 10;
diff --git a/src/backend/access/hash/hashutil.c b/src/backend/access/hash/hashutil.c
index 3fb92ea..5170634 100644
--- a/src/backend/access/hash/hashutil.c
+++ b/src/backend/access/hash/hashutil.c
@@ -289,7 +289,28 @@ _hash_checkpage(Relation rel, Buffer buf, int flags)
 bytea *
 hashoptions(Datum reloptions, bool validate)
 {
-	return default_reloptions(reloptions, validate, RELOPT_KIND_HASH);
+	relopt_value *options;
+	HashRelOptions *rdopts;
+	int			numoptions;
+	static const relopt_parse_elt tab[] = {
+		{"fillfactor", RELOPT_TYPE_INT, offsetof(HashRelOptions, fillfactor)},
+	};
+
+	options = parseRelOptions(reloptions, validate, RELOPT_KIND_HASH,
+			  &numoptions);
+
+	/* if none set, we're done */
+	if (numoptions == 0)
+		return NULL;
+
+	rdopts = allocateReloptStruct(sizeof(HashRelOptions), options, numoptions);
+
+	fillRelOptions((void *) rdopts, sizeof(HashRelOptions), options, numoptions,
+   validate, tab, lengthof(tab));
+
+	pfree(options);
+
+	return (bytea *) rdopts;
 }
 
 /*
diff --git a/src/backend/access/nbtree/nbtree.c b/src/backend/access/nbtree/nbtree.c
index 4cfd528..b460d13 100644
--- a/src/backend/access/nbtree/nbtree.c
+++ b/src/backend/access/nbtree/nbtree.c
@@ -816,7 +816,7 @@ _bt_vacuum_needs_cleanup(IndexVacuumInfo *info)
 	}
 	else
 	{
-		StdRdOptions *relopts;
+		BTRelOptions *relopts;
 		float8		cleanup_scale_factor;
 		float8		prev_num_heap_tuples;
 
@@ -827,7 +827,7 @@ _bt_vacuum_needs_cleanup(IndexVacuumInfo *info)
 		 * tuples exceeds vacuum_cleanup_index_scale_factor fraction of
 		 * original tuples count.
 		 */
-		relopts = (StdRdOptions *) info->index->rd_options;
+		relopts = (BTRelOptions *) info->index->rd_options;
 		cleanup_scale_factor = (relopts &&
 relopts->vacuum_cleanup_index_scale_factor >= 0)
 			? relopts->vacuum_cleanup_index_scale_factor
diff --git a/src/backend/access/nbtree/nbtsort.c b/src/backend/access/nbtree/nbtsort.c
index ab19692..f7c2377 100644
--- a/src/backend/access/nbtree/nbtsort.c
+++ b/src/backend/access/nbtree/nbtsort.c
@@ -725,8 +725,9 @@ _bt_pagestate(BTWriteState *wstate, uint32 level)
 	if (level > 0)
 		state->btps_full = (BLCKSZ * (100 - BTREE_NONLEAF_FILLFACTOR) / 100);
 	else
-		state->btps_full = RelationGetTargetPageFreeSpace(wstate->index,
-		  BTREE_DEFAULT_FILLFACTOR);
+		state->btps_full = (BLCKSZ * (100 - BTGetFillFactor(wstate->index))
+			 / 100);
+
 	/* no parent level, yet */
 	state->btps_next = NULL;
 
diff --gi

[PATCH] Add some useful asserts into View Options macroses

2019-10-05 Thread Nikolay Shaplov
This thread is a follow up to the thread 
https://www.postgresql.org/message-id/2620882.s52SJui4ql@x200m where I've been 
trying to remove StdRdOptions 
structure and replace it with unique structure for each relation kind.

I've decided to split that patch into smaller parts.

This part adds some asserts to ViewOptions macroses.
Since an option pointer there is converted into (ViewOptions *) it would be 
really good to make sure that this macros is called in proper context, and we 
do the convertation properly. At least when running tests with asserts turned 
on.

-- 
Software Developer: https://www.upwork.com/freelancers/~014a87e140ff02c0da
Body-oriented Therapist: https://vk.com/nataraj_rebalancing  (Russian)diff --git a/src/include/utils/rel.h b/src/include/utils/rel.h
index a5cf804..b24fb1d 100644
--- a/src/include/utils/rel.h
+++ b/src/include/utils/rel.h
@@ -351,9 +351,10 @@ typedef struct ViewOptions
  *		Returns whether the relation is security view, or not.  Note multiple
  *		eval of argument!
  */
-#define RelationIsSecurityView(relation)	\
-	((relation)->rd_options ?\
-	 ((ViewOptions *) (relation)->rd_options)->security_barrier : false)
+#define RelationIsSecurityView(relation)	\
+	(AssertMacro(relation->rd_rel->relkind == RELKIND_VIEW),\
+	 ((relation)->rd_options ?\
+	  ((ViewOptions *) (relation)->rd_options)->security_barrier : false))
 
 /*
  * RelationHasCheckOption
@@ -361,9 +362,10 @@ typedef struct ViewOptions
  *		or the cascaded check option.  Note multiple eval of argument!
  */
 #define RelationHasCheckOption(relation)	\
+	(AssertMacro(relation->rd_rel->relkind == RELKIND_VIEW),\
 	((relation)->rd_options &&\
 	 ((ViewOptions *) (relation)->rd_options)->check_option !=\
-	 VIEW_OPTION_CHECK_OPTION_NOT_SET)
+	 VIEW_OPTION_CHECK_OPTION_NOT_SET))
 
 /*
  * RelationHasLocalCheckOption
@@ -371,9 +373,10 @@ typedef struct ViewOptions
  *		option.  Note multiple eval of argument!
  */
 #define RelationHasLocalCheckOption(relation)\
+	(AssertMacro(relation->rd_rel->relkind == RELKIND_VIEW),\
 	((relation)->rd_options &&\
 	 ((ViewOptions *) (relation)->rd_options)->check_option ==\
-	 VIEW_OPTION_CHECK_OPTION_LOCAL)
+	 VIEW_OPTION_CHECK_OPTION_LOCAL))
 
 /*
  * RelationHasCascadedCheckOption
@@ -381,9 +384,10 @@ typedef struct ViewOptions
  *		option.  Note multiple eval of argument!
  */
 #define RelationHasCascadedCheckOption(relation)			\
+	(AssertMacro(relation->rd_rel->relkind == RELKIND_VIEW),\
 	((relation)->rd_options &&\
 	 ((ViewOptions *) (relation)->rd_options)->check_option ==\
-	  VIEW_OPTION_CHECK_OPTION_CASCADED)
+	  VIEW_OPTION_CHECK_OPTION_CASCADED))
 
 /*
  * RelationIsValid


signature.asc
Description: This is a digitally signed message part.


[PATCH] use separate PartitionedRelOptions structure to store partitioned table options

2019-10-06 Thread Nikolay Shaplov
Hi!

This message is follow up to the "Get rid of the StdRdOptions" patch thread:
https://www.postgresql.org/message-id/2620882.s52SJui4ql@x200m

I've split patch into even smaller parts and commitfest want each patch in 
separate thread. So it is new thread.

The idea of this patch is following: If you read the code, partitioned tables 
do not have any options (you will not find RELOPT_KIND_PARTITIONED in 
boolRelOpts, intRelOpts, realRelOpts, stringRelOpts and enumRelOpts in 
reloption.c), but it uses StdRdOptions to store them (these no options).

If partitioned table is to have it's own option set (even if it is empty now) 
it would be better to save it into separate structure, like it is done for 
Views, not adding them to StdRdOptions, like current code hints to do.

So in this patch I am creating a structure that would store partitioned table 
options (it is empty for now as there are no options for this relation kind), 
and all other code that would use this structure as soon as the first option 
comes.

I think it is bad idea to suggest option adder to ad it to StdRdOption, we 
already have a big mess there. Better if he add it to an new empty structure.

-- 
Software Developer: https://www.upwork.com/freelancers/~014a87e140ff02c0da
Body-oriented Therapist: https://vk.com/nataraj_rebalancing  (Russian)diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c
index b5072c0..f219ad3 100644
--- a/src/backend/access/common/reloptions.c
+++ b/src/backend/access/common/reloptions.c
@@ -1099,9 +1099,11 @@ extractRelOptions(HeapTuple tuple, TupleDesc tupdesc,
 		case RELKIND_RELATION:
 		case RELKIND_TOASTVALUE:
 		case RELKIND_MATVIEW:
-		case RELKIND_PARTITIONED_TABLE:
 			options = heap_reloptions(classForm->relkind, datum, false);
 			break;
+		case RELKIND_PARTITIONED_TABLE:
+			options = partitioned_reloptions(datum, false);
+			break;
 		case RELKIND_VIEW:
 			options = view_reloptions(datum, false);
 			break;
@@ -1538,6 +1540,25 @@ default_reloptions(Datum reloptions, bool validate, relopt_kind kind)
 }
 
 /*
+ * Option parser for partitioned relations
+ */
+bytea *
+partitioned_reloptions(Datum reloptions, bool validate)
+{
+   int   numoptions;
+
+  /*
+   * Since there is no options for patitioned table for now, we just do
+   * validation to report incorrect option error and leave.
+   */
+
+  if (validate)
+		parseRelOptions(reloptions, validate, RELOPT_KIND_PARTITIONED,
+		&numoptions);
+   return NULL;
+}
+
+/*
  * Option parser for views
  */
 bytea *
@@ -1593,9 +1614,6 @@ heap_reloptions(char relkind, Datum reloptions, bool validate)
 		case RELKIND_RELATION:
 		case RELKIND_MATVIEW:
 			return default_reloptions(reloptions, validate, RELOPT_KIND_HEAP);
-		case RELKIND_PARTITIONED_TABLE:
-			return default_reloptions(reloptions, validate,
-	  RELOPT_KIND_PARTITIONED);
 		default:
 			/* other relkinds are not supported */
 			return NULL;
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 05593f3..db27f30 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -720,10 +720,17 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId,
 	reloptions = transformRelOptions((Datum) 0, stmt->options, NULL, validnsps,
 	 true, false);
 
-	if (relkind == RELKIND_VIEW)
-		(void) view_reloptions(reloptions, true);
-	else
-		(void) heap_reloptions(relkind, reloptions, true);
+	switch ((int)relkind)
+	{
+		case RELKIND_VIEW:
+			(void) view_reloptions(reloptions, true);
+			break;
+		case RELKIND_PARTITIONED_TABLE:
+			(void) partitioned_reloptions(reloptions, true);
+			break;
+		default:
+			(void) heap_reloptions(relkind, reloptions, true);
+	}
 
 	if (stmt->ofTypename)
 	{
@@ -12158,9 +12165,11 @@ ATExecSetRelOptions(Relation rel, List *defList, AlterTableType operation,
 		case RELKIND_RELATION:
 		case RELKIND_TOASTVALUE:
 		case RELKIND_MATVIEW:
-		case RELKIND_PARTITIONED_TABLE:
 			(void) heap_reloptions(rel->rd_rel->relkind, newOptions, true);
 			break;
+		case RELKIND_PARTITIONED_TABLE:
+			(void) partitioned_reloptions(newOptions, true);
+			break;
 		case RELKIND_VIEW:
 			(void) view_reloptions(newOptions, true);
 			break;
diff --git a/src/include/access/reloptions.h b/src/include/access/reloptions.h
index 6bde209..0ad5c74 100644
--- a/src/include/access/reloptions.h
+++ b/src/include/access/reloptions.h
@@ -301,6 +301,7 @@ extern bytea *default_reloptions(Datum reloptions, bool validate,
  relopt_kind kind);
 extern bytea *heap_reloptions(char relkind, Datum reloptions, bool validate);
 extern bytea *view_reloptions(Datum reloptions, bool validate);
+extern bytea *partitioned_reloptions(Datum reloptions, bool validate);
 extern bytea *index_reloptions(amoptions_function amoptions, Datum reloptions,
 			   bool validate);
 extern bytea *attribute_reloptions(Datum reloptions, bool validate);
diff --git a/src/include/utils/rel.h b/src/include/utils/r

Re: [PATCH] Do not use StdRdOptions in Access Methods

2019-10-06 Thread Nikolay Shaplov
Hi! I am starting a new thread as commitfest wants new thread for new patch.

This new thread is a follow up to an https://www.postgresql.org/message-id/
2620882.s52SJui4ql%40x200m thread, where I've been trying to get rid of 
StdRdOpions structure, and now I've splitted the patch into smaller parts.

Read the quote below, to get what this patch is about

> I've been thinking about this patch and came to a conclusion that it
> would be better to split it to even smaller parts, so they can be
> easily reviewed, one by one. May be even leaving most complex
> Heap/Toast part for later.
> 
> This is first part of this patch. Here we give each Access Method it's
> own option binary representation instead of StdRdOptions.
> 
> I think this change is obvious. Because, first, Access Methods do not
> use most of the values defined in StdRdOptions.
> 
> Second this patch make Options structure code unified for all core
> Access Methods. Before some AM used StdRdOptions, some AM used it's own
> structure, now all AM uses own structures and code is written in the
> same style, so it would be more easy to update it in future.
> 
> John Dent, would you join reviewing this part of the patch? I hope it
> will be more easy now...

And now I have a newer version of the patch, as I forgot to remove 
vacuum_cleanup_index_scale_factor from StdRdOptions as it was used only in 
Btree index and now do not used at all. New version fixes it.

-- 
Software Developer: https://www.upwork.com/freelancers/~014a87e140ff02c0da
Body-oriented Therapist: https://vk.com/nataraj_rebalancing  (Russian)diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c
index b5072c0..02ee3c9 100644
--- a/src/backend/access/common/reloptions.c
+++ b/src/backend/access/common/reloptions.c
@@ -23,7 +23,7 @@
 #include "access/htup_details.h"
 #include "access/nbtree.h"
 #include "access/reloptions.h"
-#include "access/spgist.h"
+#include "access/spgist_private.h"
 #include "catalog/pg_type.h"
 #include "commands/defrem.h"
 #include "commands/tablespace.h"
@@ -1513,8 +1513,6 @@ default_reloptions(Datum reloptions, bool validate, relopt_kind kind)
 		offsetof(StdRdOptions, user_catalog_table)},
 		{"parallel_workers", RELOPT_TYPE_INT,
 		offsetof(StdRdOptions, parallel_workers)},
-		{"vacuum_cleanup_index_scale_factor", RELOPT_TYPE_REAL,
-		offsetof(StdRdOptions, vacuum_cleanup_index_scale_factor)},
 		{"vacuum_index_cleanup", RELOPT_TYPE_BOOL,
 		offsetof(StdRdOptions, vacuum_index_cleanup)},
 		{"vacuum_truncate", RELOPT_TYPE_BOOL,
diff --git a/src/backend/access/hash/hashpage.c b/src/backend/access/hash/hashpage.c
index 838ee68..eec2100 100644
--- a/src/backend/access/hash/hashpage.c
+++ b/src/backend/access/hash/hashpage.c
@@ -359,7 +359,7 @@ _hash_init(Relation rel, double num_tuples, ForkNumber forkNum)
 	data_width = sizeof(uint32);
 	item_width = MAXALIGN(sizeof(IndexTupleData)) + MAXALIGN(data_width) +
 		sizeof(ItemIdData);		/* include the line pointer */
-	ffactor = RelationGetTargetPageUsage(rel, HASH_DEFAULT_FILLFACTOR) / item_width;
+	ffactor = (BLCKSZ * HashGetFillFactor(rel) / 100) / item_width;
 	/* keep to a sane range */
 	if (ffactor < 10)
 		ffactor = 10;
diff --git a/src/backend/access/hash/hashutil.c b/src/backend/access/hash/hashutil.c
index 3fb92ea..5170634 100644
--- a/src/backend/access/hash/hashutil.c
+++ b/src/backend/access/hash/hashutil.c
@@ -289,7 +289,28 @@ _hash_checkpage(Relation rel, Buffer buf, int flags)
 bytea *
 hashoptions(Datum reloptions, bool validate)
 {
-	return default_reloptions(reloptions, validate, RELOPT_KIND_HASH);
+	relopt_value *options;
+	HashRelOptions *rdopts;
+	int			numoptions;
+	static const relopt_parse_elt tab[] = {
+		{"fillfactor", RELOPT_TYPE_INT, offsetof(HashRelOptions, fillfactor)},
+	};
+
+	options = parseRelOptions(reloptions, validate, RELOPT_KIND_HASH,
+			  &numoptions);
+
+	/* if none set, we're done */
+	if (numoptions == 0)
+		return NULL;
+
+	rdopts = allocateReloptStruct(sizeof(HashRelOptions), options, numoptions);
+
+	fillRelOptions((void *) rdopts, sizeof(HashRelOptions), options, numoptions,
+   validate, tab, lengthof(tab));
+
+	pfree(options);
+
+	return (bytea *) rdopts;
 }
 
 /*
diff --git a/src/backend/access/nbtree/nbtree.c b/src/backend/access/nbtree/nbtree.c
index 4cfd528..b460d13 100644
--- a/src/backend/access/nbtree/nbtree.c
+++ b/src/backend/access/nbtree/nbtree.c
@@ -816,7 +816,7 @@ _bt_vacuum_needs_cleanup(IndexVacuumInfo *info)
 	}
 	else
 	{
-		StdRdOptions *relopts;
+		BTRelOptions *relopts;
 		float8		cleanup_scale_factor;
 		float8		prev_num_heap_tuples;
 
@@ -827,7 +827,7 @@ _bt_vacuum_needs_cleanup(IndexVacuumInfo *info)
 		 * tuples exceeds vacuum_cleanup_index_scale_factor fraction of
 		 * original tuples count.
 		 */
-		relopts = (StdRdOptions *) info->index->rd_options;
+		relopts = (BTRelOptions *) info->index->rd_options;
 		cleanup_scale_factor = (relopts &&
 relopts->vacuum_cleanup_index_scale_factor

Re: [PATCH] get rid of StdRdOptions, use individual binary reloptions representation for each relation kind instead

2019-10-06 Thread Nikolay Shaplov
В письме от пятница, 27 сентября 2019 г. 17:24:49 MSK пользователь Michael 
Paquier написал:

> The patch is in this state for two months now, so I have switched it
> to "returned with feedback". 

So I've split this patch into even smaller parts, so it would be more easy to 
review.

Do not use StdRdOptions in Access Methods
https://www.postgresql.org/message-id/4127670.gFlpRb6XCm@x200m

Use empty PartitionedRelOption structure for storing partitioned table options 
instead of StdRdOption
https://www.postgresql.org/message-id/1627387.Qykg9O6zpu@x200m

and 

Some useful asserts in ViewOptions Macroses
https://www.postgresql.org/message-id/3634983.eHpMQ1mJnI@x200m

as for removing StdRdOptions for Heap and Toast, I would suggest for commit it 
later. It is not critical for my reloptions refactoring plans. I can do it 
having one structure for two relation kinds. So we can split it into two 
later, or do not split at all...

-- 
Software Developer: https://www.upwork.com/freelancers/~014a87e140ff02c0da
Body-oriented Therapist: https://vk.com/nataraj_rebalancing  (Russian)

signature.asc
Description: This is a digitally signed message part.


Re: [PATCH] use separate PartitionedRelOptions structure to store partitioned table options

2019-10-07 Thread Nikolay Shaplov
В письме от понедельник, 7 октября 2019 г. 14:57:14 MSK пользователь Michael 
Paquier написал:
> On Sun, Oct 06, 2019 at 03:47:46PM +0300, Nikolay Shaplov wrote:
> > This message is follow up to the "Get rid of the StdRdOptions" patch
> > thread: https://www.postgresql.org/message-id/2620882.s52SJui4ql@x200m
> > 
> > I've split patch into even smaller parts and commitfest want each patch in
> > separate thread. So it is new thread.
> 
> Splitting concepts into different threads may be fine, and usually
> recommended.  Splitting a set of patches into multiple entries to ease
> review and your goal to get a patch integrated and posted all these
> into the same thread is usually recommended.  Now posting a full set
> of patches across multiple threads, in way so as they have
> dependencies with each other, is what I would call a confusing
> situation.  That's hard to follow.
I understand that. I've tried to add new patches to original thread, but 
commitfest did not accept that for some reason. You can try to add patch from 
this letter https://www.postgresql.org/message-id/2620882.s52SJui4ql@x200m 
just to see how it works.

Since discussion actually did not started yet, it can be moved anywhere you 
suggest, but please tell how exactly it should be done, because I do not 
understand what is the better way.

> > The idea of this patch is following: If you read the code, partitioned
> > tables do not have any options (you will not find RELOPT_KIND_PARTITIONED
> > in boolRelOpts, intRelOpts, realRelOpts, stringRelOpts and enumRelOpts in
> > reloption.c), but it uses StdRdOptions to store them (these no options).
> I am not even sure that we actually need that.  What kind of reloption
> you would think would suit into this subset?

Actually I do not know. But the author of partitioned patch, added a stub for 
partitioned tables to have some reloptions in future. But this stub is 
designed to use StdRdOptions. Which is not correct, as I presume. So here I am 
correcting the stub.

-- 
Software Developer: https://www.upwork.com/freelancers/~014a87e140ff02c0da
Body-oriented Therapist: https://vk.com/nataraj_rebalancing  (Russian)

signature.asc
Description: This is a digitally signed message part.


Re: [PATCH] Do not use StdRdOptions in Access Methods

2019-10-08 Thread Nikolay Shaplov
В письме от понедельник, 7 октября 2019 г. 18:55:20 MSK пользователь Dent John 
написал:

> I like the new approach. And I agree with the ambition — to split out the
> representation from StdRdOptions.
Thanks.
 
> However, with that change, in the AM’s *options() function, it looks as if
> you could simply add new fields to the relopt_parse_elt list. That’s still
> not true, because parseRelOptions() will fail to find a matching entry,
> causing numoptions to be left zero, and an early exit made. (At least,
> that’s if I correctly understand how things work.)
> 
> I think that is fine as an interim limitation, because your change has not
> yet fully broken the connection to the boolRelOpts, intRelOpts, realRelOpts
> and stringRelOpts strutures. But perhaps a comment would help to make it
> clear. Perhaps add something like this above the tab[]: "When adding or
> changing a relopt in the relopt_parse_elt tab[], ensure the corresponding
> change is made to boolRelOpts, intRelOpts, realRelOpts or stringRelOpts."
Whoa-whoa!

I am not inventing something new here. Same code is already used in brin 
(brin.c:820), gin (ginutils.c:602) and gist (gistutils.c:909) indexes. I've 
just copied the idea, to do all index code uniform.

This does not mean that these code can't be improved, but as far as I can 
guess it is better to do it in small steps, first make option code uniform, and 
then improve all of it this way or another...

So I here I would suggest to discuss it I copied this code correctly, without 
going very deeply into discussion how we can improve code I've used as a 
source for cloning.

And then I have ideas how to do it better. But this will come later...

-- 
Software Developer: https://www.upwork.com/freelancers/~014a87e140ff02c0da
Body-oriented Therapist: https://vk.com/nataraj_rebalancing  (Russian)




Re: [PATCH] Add some useful asserts into View Options macroses

2019-10-08 Thread Nikolay Shaplov
В письме от понедельник, 7 октября 2019 г. 12:59:27 MSK пользователь Robert 
Haas написал:

> > This thread is a follow up to the thread
> > https://www.postgresql.org/message-id/2620882.s52SJui4ql@x200m where I've
> > been trying to remove StdRdOptions structure and replace it with unique
> > structure for each relation kind.
> > 
> > I've decided to split that patch into smaller parts.
> > 
> > This part adds some asserts to ViewOptions macroses.
> > Since an option pointer there is converted into (ViewOptions *) it would
> > be
> > really good to make sure that this macros is called in proper context, and
> > we do the convertation properly. At least when running tests with asserts
> > turned on.
> Seems like a good idea.  Should we try to do something similar for the
> macros in that header file that cast to StdRdOptions?

That would not be as easy as for ViewOptions. For example as for the current 
master code, fillfactor from StdRdOptions is used in Toast, Heap, Hash index, 
nbtree index, and spgist index. This will make RelationGetFillFactor macros a 
bit complicated for example.

Now I have patches that limits usage of StdRdOptions to Heap and Toast.

When StdRdOptions is not that widely used, we whould be able to add asserts 
for it, it will not make the code too complex.

So I would suggest to do ViewOptions asserts now, and keep dealing with 
StdRdOptions for later. When we are finished with my current patches, I will 
take care about it.

-- 
Software Developer: https://www.upwork.com/freelancers/~014a87e140ff02c0da
Body-oriented Therapist: https://vk.com/nataraj_rebalancing  (Russian)




Re: [PATCH] use separate PartitionedRelOptions structure to store partitioned table options

2019-10-08 Thread Nikolay Shaplov
В письме от вторник, 8 октября 2019 г. 16:00:49 MSK пользователь Amit Langote 
написал:

> > > > The idea of this patch is following: If you read the code, partitioned
> > > > tables do not have any options (you will not find
> > > > RELOPT_KIND_PARTITIONED
> > > > in boolRelOpts, intRelOpts, realRelOpts, stringRelOpts and enumRelOpts
> > > > in
> > > > reloption.c), but it uses StdRdOptions to store them (these no
> > > > options).
> > > 
> > > I am not even sure that we actually need that.  What kind of reloption
> > > you would think would suit into this subset?
> > 
> > Actually I do not know. But the author of partitioned patch, added a stub
> > for partitioned tables to have some reloptions in future. But this stub
> > is designed to use StdRdOptions. Which is not correct, as I presume. So
> > here I am correcting the stub.
> 
> I wrote the patch that introduced RELOPT_KIND_PARTITIONED.  Yes, it
> was added as a stub relopt_kind to eventually apply to reloptions that
> could be sensibly applied to partitioned tables.  We never got around
> to working on making the existing reloptions relevant to partitioned
> tables, nor did we add any new partitioned table-specific reloptions,
> so it remained an unused relopt_kind.
Thank you for clarifying thing.
 
> IIUC, this patch invents PartitionedRelOptions as the binary
> representation for future RELOPT_KIND_PARTITIONED parameters.  As long
> as others are on board with using different *Options structs for
> different object kinds, I see no problem with this idea.
Yes, this is correct. Some Access Methods already use it's own Options 
structure. As far as I can guess StdRdOptions still exists only for historical 
reasons, and became quite a mess because of adding all kind of stuff there. 
Better to separate it.

BTW, as far as you are familiar with this part of the code, may be you will 
join the review if this particular patch?

-- 
Software Developer: https://www.upwork.com/freelancers/~014a87e140ff02c0da
Body-oriented Therapist: https://vk.com/nataraj_rebalancing  (Russian)




Re: [PATCH] Do not use StdRdOptions in Access Methods

2019-10-09 Thread Nikolay Shaplov
В письме от среда, 9 октября 2019 г. 20:26:14 MSK пользователь Dent John 
написал:

> I didn’t spot it was an existing pattern.
Sorry, this might be my mistake I should explicitly mention it in the first 
place. 
 
> And I agree — making the code uniform will make it easier to evolve in
> future.
> 
> Gets my vote.
Thanks!

Can you please check, I did not do any mistake while copying and adapting the 
code.

-- 
Software Developer: https://www.upwork.com/freelancers/~014a87e140ff02c0da
Body-oriented Therapist: https://vk.com/nataraj_rebalancing  (Russian)

Re: [PATCH] use separate PartitionedRelOptions structure to store partitioned table options

2019-10-11 Thread Nikolay Shaplov
В Thu, 10 Oct 2019 15:50:05 +0900
Amit Langote  пишет:

> > I think it is bad idea to suggest option adder to ad it to
> > StdRdOption, we already have a big mess there. Better if he add it
> > to an new empty structure.
> 
> I tend to agree that this improves readability of the reloptions code
> a bit.
> 
> Some comments on the patch:
> 
> How about naming the function partitioned_table_reloptions() instead
> of partitioned_reloptions()?

I have my doubts about using word table here... In relational model
there are no such concept as "table", it uses concept "relation". And
in postgres there were no tables, there were only relations. Heap
relation, toast relation, all kind of index relations... I do not
understand when and why word "table" appeared when we speak about some
virtual relation that is made of several real heap relation. That is
why I am not using the word table here...

But since you are the author of partition table code, and this code is
already accepted in the core, you should know better. So I will change
it the way you say.
 
> +switch ((int)relkind)
> 
> Needs a space between (int) and relkind, but I don't think the (int)
> cast is really necessary.  I don't see it in other places.
Oh. Yeh. This is my mistake... I had some strange compilation
problems, and this is a remnant of my efforts to find the cause of
it, I've forgot to clean...
Thanks!
   
> Speaking of partitioned relations vs tables, I see that you didn't
> touch partitioned indexes (RELKIND_PARTITIONED_INDEX relations).  Is
> that because we leave option handling to the index AMs?

Because for partitioned indexes the code says "Use same options
original index does"

bytea * 
extractRelOptions(HeapTuple tuple, TupleDesc tupdesc,   
  amoptions_function amoptions) 
{  
 
switch (classForm->relkind) 
{   
case RELKIND_RELATION:  
case RELKIND_TOASTVALUE:
case RELKIND_MATVIEW:   
options = heap_reloptions(classForm->relkind, datum, false);
break;  
case RELKIND_PARTITIONED_TABLE: 
options = partitioned_table_reloptions(datum, false);   
break;  
case RELKIND_VIEW:  
options = view_reloptions(datum, false);
break;  
case RELKIND_INDEX: 
case RELKIND_PARTITIONED_INDEX: 
options = index_reloptions(amoptions, datum, false);
break;  


Here you see the function accepts amoptions method that know how to
parse options for a particular index, and passes it to index_reloptions
functions. For both indexes and partitioned indexes it is taken from AM
"method" amoptions. So options uses exactly the same code and same
options both for indexes and for partitioned indexes.

I do not know if it is correct from global point of view, but from the
point of view of reloptions engine, it does not require any attention:
change index options and get partitioned_index options for free...

Actually I would expect some problems there, because sooner or later,
somebody would want to set custom fillfactor to partitioned table, or
set some custom autovacuum options for it. But I would prefer to think
about it when I am done with reloption engine rewriting... Working in
both direction will cause more trouble then get benefits...


diff --git a/.gitignore b/.gitignore
index 794e35b..37331c2 100644
diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c
index b5072c0..067441f 100644
--- a/src/backend/access/common/reloptions.c
+++ b/src/backend/access/common/reloptions.c
@@ -1099,9 +1099,11 @@ extractRelOptions(HeapTuple tuple, TupleDesc tupdesc,
 		case RELKIND_RELATION:
 		case RELKIND_TOASTVALUE:
 		case RELKIND_MATVIEW:
-		case RELKIND_PARTITIONED_TABLE:
 			options = heap_reloptions(classForm->relkind, datum, false);
 			break;
+		case RELKIND_PARTITIONED_TABLE:
+			options = partitioned_table_reloptions(datum, false);
+			break;
 		case RELKIND_VIEW:
 			options = view_reloptions(datum, false);
 			break;
@@ -1538,6 +1540,25 @@ default_reloptions(Datum reloptions, bool

Re: [PATCH] Do not use StdRdOptions in Access Methods

2019-10-11 Thread Nikolay Shaplov
В письме от четверг, 10 октября 2019 г. 17:17:30 MSK пользователь Amit Langote 
написал:

> I read comments that Tomas left at:
> https://www.postgresql.org/message-id/20190727173841.7ypzo4xuzizvijge%40deve
> lopment
> 
> I'd like to join Michael in reiterating one point from Tomas' review.
> I think the patch can go further in trying to make the code in this
> area more maintainable.
> 
> For example, even without this patch, the following stanza is repeated
> in many places:
> 
> options = parseRelOptions(reloptions, validate, foo_relopt_kind,
> &numoptions);
> rdopts = allocateReloptStruct(sizeof(FooOptions), options, numoptions);
> fillRelOptions((void *) rdopts, sizeof(FooOptions), options, numoptions,
> validate, foo_relopt_tab, lengthof(foo_relopt_tab)); return (bytea *)
> rdopts;
> 
> and this patch adds few more instances as it's adding more Options structs.
> 
> I think it wouldn't be hard to encapsulate the above stanza in a new
> public function in reloptions.c and call it from the various places
> that now have the above code.
The code of reloptions is very historical and illogical. I also noticed that 
these lines are repeated several time. And may be it would be better to put 
them into reloptions.c. But could anybody clearly explain what are they doing? 
Just to give function a proper name. I understand what they are doing, but I 
am unable to give short and clear explanation.

I am planning to rewrite this part completely. So we have none of this lines 
repeated. I had a proposal you can see it here https://
commitfest.postgresql.org/15/992/ but people on the list told be that patch is 
too complex and I should commit it part by part.

So I am doing it now. I am almost done. But to provide clear and logical patch 
that introduces my concept, I need StdRdOption to be divided into separated 
structures. At least for AM. And I need at to be done as simply as possible 
because the rest of the code is going to be rewritten anyway.

That is why I want to follow the steps: make the code uniform, and then 
improve it. I have improvement in the pocket, but I need a uniform code before 
revealing it.

If you think it is absolutely necessary to put these line into one function, I 
will do it. It will not make code more clear, I guess. I See no benefits, but 
I can do it, but I would avoid doing it, if possible. At least at this step.

-- 
Software Developer: https://www.upwork.com/freelancers/~014a87e140ff02c0da
Body-oriented Therapist: https://vk.com/nataraj_rebalancing  (Russian)




Re: [PATCH] use separate PartitionedRelOptions structure to store partitioned table options

2019-10-11 Thread Nikolay Shaplov
> > I think it is bad idea to suggest option adder to ad it to
> > StdRdOption, we already have a big mess there. Better if he add it
> > to an new empty structure.  
>
> I tend to agree that this improves readability of the reloptions code
> a bit.
>
> Some comments on the patch:
>
> How about naming the function partitioned_table_reloptions() instead
> of partitioned_reloptions()?  

I have my doubts about using word table here... In relational model
there are no such concept as "table", it uses concept "relation". And
in postgres there were no tables, there were only relations. Heap
relation, toast relation, all kind of index relations... I do not
understand when and why word "table" appeared when we speak about some
virtual relation that is made of several real heap relation. That is
why I am not using the word table here...

But since you are the author of partition table code, and this code is
already accepted in the core, you should know better. So I will change
it the way you say.
 
> +switch ((int)relkind)
>
> Needs a space between (int) and relkind, but I don't think the (int)
> cast is really necessary.  I don't see it in other places.  
Oh. Yeh. This is my mistake... I had some strange compilation
problems, and this is a remnant of my efforts to find the cause of
it, I've forgot to clean...
Thanks!
   
> Speaking of partitioned relations vs tables, I see that you didn't
> touch partitioned indexes (RELKIND_PARTITIONED_INDEX relations).  Is
> that because we leave option handling to the index AMs?  

Because for partitioned indexes the code says "Use same options
original index does"

bytea
* extractRelOptions(HeapTuple tuple, TupleDesc
tupdesc, amoptions_function amoptions) 
{  
 
switch
(classForm->relkind)
{ case
RELKIND_RELATION: case
RELKIND_TOASTVALUE: case
RELKIND_MATVIEW: options = heap_reloptions(classForm->relkind, datum,
false);
break; case
RELKIND_PARTITIONED_TABLE: options =
partitioned_table_reloptions(datum, false);
break; case
RELKIND_VIEW: options = view_reloptions(datum,
false);
break; case
RELKIND_INDEX: case
RELKIND_PARTITIONED_INDEX: options = index_reloptions(amoptions, datum,
false); break;  


Here you see the function accepts amoptions method that know how to
parse options for a particular index, and passes it to index_reloptions
functions. For both indexes and partitioned indexes it is taken from AM
"method" amoptions. So options uses exactly the same code and same
options both for indexes and for partitioned indexes.

I do not know if it is correct from global point of view, but from the
point of view of reloptions engine, it does not require any attention:
change index options and get partitioned_index options for free...

Actually I would expect some problems there, because sooner or later,
somebody would want to set custom fillfactor to partitioned table, or
set some custom autovacuum options for it. But I would prefer to think
about it when I am done with reloption engine rewriting... Working in
both direction will cause more trouble then get benefits...diff --git a/.gitignore b/.gitignore
index 794e35b..37331c2 100644
diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c
index b5072c0..067441f 100644
--- a/src/backend/access/common/reloptions.c
+++ b/src/backend/access/common/reloptions.c
@@ -1099,9 +1099,11 @@ extractRelOptions(HeapTuple tuple, TupleDesc tupdesc,
 		case RELKIND_RELATION:
 		case RELKIND_TOASTVALUE:
 		case RELKIND_MATVIEW:
-		case RELKIND_PARTITIONED_TABLE:
 			options = heap_reloptions(classForm->relkind, datum, false);
 			break;
+		case RELKIND_PARTITIONED_TABLE:
+			options = partitioned_table_reloptions(datum, false);
+			break;
 		case RELKIND_VIEW:
 			options = view_reloptions(datum, false);
 			break;
@@ -1538,6 +1540,25 @@ default_reloptions(Datum reloptions, bool validate, relopt_kind kind)
 }
 
 /*
+ * Option parser for partitioned tables
+ */
+bytea *
+partitioned_table_reloptions(Datum reloptions, bool validate)
+{
+   int   numoptions;
+
+  /*
+   * Since there are no options for patitioned tables for now, we just do
+   * validation to report incorrect option error and leave.
+   */
+
+  if (validate)
+		parseRelOptions(reloptions, validate, RELOPT_KIND_PARTITIONED,
+		&numoptions);
+   return NULL;
+}
+
+/*
  * Option parser for views
  */
 bytea *
@@ -1593,9 +1614,6 @@ heap_reloptions(char relkind, Datum reloptions, bool validate)
 		case RELKIND_RELATION:
 		case RELKIND_MATVIEW:
 			return default_reloptions(reloptions, validate, RELOPT_KIND_HEAP);
-		case RELKIND_PARTITIONED_TABLE:
-			return default_reloptions(reloptions, validate,
-	  RELOPT_KIND_PARTITIONED);
 		default:
 			/* other relkinds are not supported */
 			return NULL;
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 05593f3..f44e865 100644
--- a/src/backend/comma

[PATCH] src/test/modules/dummy_index -- way to test reloptions from inside of access method

2019-03-18 Thread Nikolay Shaplov
Hi!

This patch introduce a dummy_index access method module, that does not do any 
indexing at all, but allow to test reloptions from inside of access method 
extension.

This patch is part of my bigger work on reloptions refactoring.

It came from 
https://www.postgresql.org/message-id/20190220060832.GI15532%40paquier.xyz 
thread where I suggested to add a "enum" reloption type, and we came to 
conclusion that we need to test how this new option works for access method 
created from extension (it does not work in the same way as in-core access 
methods) . But we can't add this option to bloom index, so we need an index 
extension that can be freely used for tests.

So I created src/test/modules/dummy_index, it does no real indexing, but it 
has all types of reloptions that can be set (reloption_int, reloption_real, 
reloption_bool, reloption_string and reloption_string2). It also has set of 
boolean GUC variables that enables test output concerning certain reloption:
(do_test_reloption_int, do_test_reloption_real, do_test_reloption_bool and 
do_test_reloption_string and  do_test_reloption_string2) also set 
do_test_reloptions to true to get any output at all.
Dummy index will print this output when index is created, and when record is 
inserted (this needed to check if your ALTER TABLE did well)
Then you just use normal regression tests: turns on test output, sets some 
reloption and check test output, that it properly reaches the access method 
internals.

While writing this module I kept in mind the idea that this module can be also 
used for other am-related tests, so I separated the code into two parts: 
dummy_index.c has only code related to implementation of an empty access 
method, and all code related to reloptions tests  were stored into 
direloptions.c. So in future somebody can add di[what_ever_he_wants].c whith 
his own tests code, add necessary calls to dummy_index.c, create some GUC 
variables, and has his own feature tested.

So I kindly ask you to review and commit this module, so I would be able to 
continue my work on reloptions refactoring...

Thanks! 

diff --git a/.gitignore b/.gitignore
index 794e35b..37331c2 100644
diff --git a/src/test/modules/Makefile b/src/test/modules/Makefile
index 19d60a5..aa34320 100644
--- a/src/test/modules/Makefile
+++ b/src/test/modules/Makefile
@@ -7,6 +7,7 @@ include $(top_builddir)/src/Makefile.global
 SUBDIRS = \
 		  brin \
 		  commit_ts \
+		  dummy_index \
 		  dummy_seclabel \
 		  snapshot_too_old \
 		  test_bloomfilter \
diff --git a/src/test/modules/dummy_index/.gitignore b/src/test/modules/dummy_index/.gitignore
new file mode 100644
index 000..5dcb3ff
--- /dev/null
+++ b/src/test/modules/dummy_index/.gitignore
@@ -0,0 +1,4 @@
+# Generated subdirectories
+/log/
+/results/
+/tmp_check/
diff --git a/src/test/modules/dummy_index/Makefile b/src/test/modules/dummy_index/Makefile
new file mode 100644
index 000..95c1fcc
--- /dev/null
+++ b/src/test/modules/dummy_index/Makefile
@@ -0,0 +1,21 @@
+# contrib/bloom/Makefile
+
+MODULE_big = dummy_index
+OBJS = dummy_index.o direloptions.o $(WIN32RES)
+
+EXTENSION = dummy_index
+DATA = dummy_index--1.0.sql
+PGFILEDESC = "dummy index access method - needed for all kinds of tests"
+
+REGRESS = reloptions
+
+ifdef USE_PGXS
+PG_CONFIG = pg_config
+PGXS := $(shell $(PG_CONFIG) --pgxs)
+include $(PGXS)
+else
+subdir = src/test/modules/dummy_index
+top_builddir = ../../../..
+include $(top_builddir)/src/Makefile.global
+include $(top_srcdir)/contrib/contrib-global.mk
+endif
diff --git a/src/test/modules/dummy_index/README b/src/test/modules/dummy_index/README
new file mode 100644
index 000..b704112
--- /dev/null
+++ b/src/test/modules/dummy_index/README
@@ -0,0 +1,34 @@
+DUMMY INDEX
+
+Dummy index, an index module for testing am-related internal calls that can't be
+properly tested inside production indexes, but better to be tested inside actual
+access method module.
+
+Guidelines:
+1. Keep this index as simple as as possible. It should not do any real indexing
+(unless you need it for your tests), if you need it make it as simple as
+possible;
+2. Keep all code related to feature you test inside id[name_of_a_feature].c
+file. dummy_index.c file should contain code that is needed for everyone, and
+make calls to feature-related code;
+3. Code related to your feature tests should be enabled and disabled by GUC
+variables. Create as many boolean GUC variables as you need and set them on so
+your test will know when it is time to do test output. Thus output from
+different features tests are not interfered;
+4. Add section to this README file that describes the general idea of what your
+tests do.
+
+RELOPTIONS TESTS
+
+Here we check that values of reloptions properly reaches am-internals, and that
+all reloption-related code works as expected. Several GUC variables are defined
+to control test's output. do_test_reloptions turns on and off any
+reloptions-related output. You will also get some test out

Re: [PATCH][PROPOSAL] Add enum releation option type

2019-03-18 Thread Nikolay Shaplov
В письме от среда, 20 февраля 2019 г. 15:08:32 MSK пользователь Michael 
Paquier написал:

> > 2.5  May be this src/test/modules dummy index is subject to another patch.
> > So I will start working on it right now, but we will do this work not
> > dependent to any other patches. And just add there what we need when it
> > is ready. I would actually add there some code that checks all types of
> > options, because we actually never check that option value from reloptons
> > successfully reaches extension code. I did this checks manually, when I
> > wrote that bigger reloption patch, but there is no facilities to do
> > regularly check is via test suit. Creating dummy index will create such
> > facilities.
> 
> bloom is a user-facing extension, while src/test/modules are normally
> not installed (there is an exception for MSVC anyway..), so stressing
> add_enum_reloption in src/test/modules looks more appropriate to me,
> except if you can define an option which is useful for the user and is
> an enum.
I've created a module in src/test/modules where we would be able to add enum 
support when that module is commited.

https://commitfest.postgresql.org/23/2064/

I've filed it as a separate patch (it is standalone work as I can feel it). 
Sadly I did not manage to prepare it before this commitfest, so I've added it 
to a next one. :-((





[PATCH][HOTFIX] vacuum_cost_delay type change from int to real have not been done everywhere

2019-03-26 Thread Nikolay Shaplov
Hi!

In caf626b2 type of vacuum_cost_delay have been switched from int to real, 
everywhere, but not in *RelOpts[] arrays.

For some reason it continued to build and work. But I think it is better to 
move vacuum_cost_delay from int to real there too...

Patch attached.

PS. As you can see current reloption code is error-prone. To properly change 
reloptions you should simultaneously change code in several different places, 
and as you can see, it may not report if you missed something.
I am working on reloptions code refactoring now, please join reviewing my 
patches. This work is important as you can see from this example... 
 
diff --git a/.gitignore b/.gitignore
index 794e35b..37331c2 100644
diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c
index 3b0b138..ba90235 100644
--- a/src/backend/access/common/reloptions.c
+++ b/src/backend/access/common/reloptions.c
@@ -214,15 +214,6 @@ static relopt_int intRelOpts[] =
 	},
 	{
 		{
-			"autovacuum_vacuum_cost_delay",
-			"Vacuum cost delay in milliseconds, for autovacuum",
-			RELOPT_KIND_HEAP | RELOPT_KIND_TOAST,
-			ShareUpdateExclusiveLock
-		},
-		-1, 0, 100
-	},
-	{
-		{
 			"autovacuum_vacuum_cost_limit",
 			"Vacuum cost amount available before napping, for autovacuum",
 			RELOPT_KIND_HEAP | RELOPT_KIND_TOAST,
@@ -366,6 +357,16 @@ static relopt_real realRelOpts[] =
 	},
 	{
 		{
+			"autovacuum_vacuum_cost_delay",
+			"Vacuum cost delay in milliseconds, for autovacuum",
+			RELOPT_KIND_HEAP | RELOPT_KIND_TOAST,
+			ShareUpdateExclusiveLock
+		},
+		-1, 0, 100
+	},
+
+	{
+		{
 			"seq_page_cost",
 			"Sets the planner's estimate of the cost of a sequentially fetched disk page.",
 			RELOPT_KIND_TABLESPACE,


Re: [PATCH] get rid of StdRdOptions, use individual binary reloptions representation for each relation kind instead

2019-03-31 Thread Nikolay Shaplov
В письме от понедельник, 18 марта 2019 г. 3:03:04 MSK пользователь Iwata, Aya 
написал:
> Hi Nikolay,
Hi!
Sorry for long delay. Postgres is not my primary work, so sometimes it takes a 
while to get to it.

> This patch does not apply.
Oh... Sorry... here goes new version

> Please refer to http://commitfest.cputube.org/
> and update it.
Oh! a nice service... Wish it can stream status changes as RSS feeds... But I 
can wirte a script on top of it. It would be more easy... 

> How about separating your patch by feature or units that
> can be phased commit. For example, adding assert macro at first,
> refactoring StdRdOptions by the next, etc.
No I think we should not. All Macros changes are driven by removing 
StdRdOptions. (Actually AssertMarco added there, but I do not think it is a 
great addition that require a singe patch)
If it is really necessary I would file AssertMacro addition as a single patch, 
but I would abstain from doing it if possible...
 diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c
index b58a1f7..db5397f 100644
--- a/src/backend/access/common/reloptions.c
+++ b/src/backend/access/common/reloptions.c
@@ -22,7 +22,7 @@
 #include "access/htup_details.h"
 #include "access/nbtree.h"
 #include "access/reloptions.h"
-#include "access/spgist.h"
+#include "access/spgist_private.h"
 #include "access/tuptoaster.h"
 #include "catalog/pg_type.h"
 #include "commands/defrem.h"
@@ -46,9 +46,8 @@
  * upper and lower bounds (if applicable); for strings, consider a validation
  * routine.
  * (ii) add a record below (or use add__reloption).
- * (iii) add it to the appropriate options struct (perhaps StdRdOptions)
- * (iv) add it to the appropriate handling routine (perhaps
- * default_reloptions)
+ * (iii) add it to the appropriate options struct
+ * (iv) add it to the appropriate handling routine
  * (v) make sure the lock level is set correctly for that operation
  * (vi) don't forget to document the option
  *
@@ -1010,7 +1009,7 @@ extractRelOptions(HeapTuple tuple, TupleDesc tupdesc,
 		case RELKIND_TOASTVALUE:
 		case RELKIND_MATVIEW:
 		case RELKIND_PARTITIONED_TABLE:
-			options = heap_reloptions(classForm->relkind, datum, false);
+			options = relation_reloptions(classForm->relkind, datum, false);
 			break;
 		case RELKIND_VIEW:
 			options = view_reloptions(datum, false);
@@ -1343,63 +1342,69 @@ fillRelOptions(void *rdopts, Size basesize,
 
 
 /*
- * Option parser for anything that uses StdRdOptions.
+ * Option parsing definition for autovacuum. Used in toast and heap options.
+ */
+
+#define AUTOVACUUM_RELOPTIONS(OFFSET)\
+		{"autovacuum_enabled", RELOPT_TYPE_BOOL, \
+		OFFSET + offsetof(AutoVacOpts, enabled)},\
+		{"autovacuum_vacuum_threshold", RELOPT_TYPE_INT, \
+		OFFSET + offsetof(AutoVacOpts, vacuum_threshold)},   \
+		{"autovacuum_analyze_threshold", RELOPT_TYPE_INT,\
+		OFFSET + offsetof(AutoVacOpts, analyze_threshold)},  \
+		{"autovacuum_vacuum_cost_delay", RELOPT_TYPE_REAL,   \
+		OFFSET + offsetof(AutoVacOpts, vacuum_cost_delay)},  \
+		{"autovacuum_vacuum_cost_limit", RELOPT_TYPE_INT,\
+		OFFSET + offsetof(AutoVacOpts, vacuum_cost_limit)},  \
+		{"autovacuum_freeze_min_age", RELOPT_TYPE_INT,   \
+		OFFSET + offsetof(AutoVacOpts, freeze_min_age)}, \
+		{"autovacuum_freeze_max_age", RELOPT_TYPE_INT,   \
+		OFFSET + offsetof(AutoVacOpts, freeze_max_age)}, \
+		{"autovacuum_freeze_table_age", RELOPT_TYPE_INT, \
+		OFFSET + offsetof(AutoVacOpts, freeze_table_age)},   \
+		{"autovacuum_multixact_freeze_min_age", RELOPT_TYPE_INT, \
+		OFFSET + offsetof(AutoVacOpts, multixact_freeze_min_age)},   \
+		{"autovacuum_multixact_freeze_max_age", RELOPT_TYPE_INT, \
+		OFFSET + offsetof(AutoVacOpts, multixact_freeze_max_age)},   \
+		{"autovacuum_multixact_freeze_table_age", RELOPT_TYPE_INT,   \
+		OFFSET + offsetof(AutoVacOpts, multixact_freeze_table_age)}, \
+		{"log_autovacuum_min_duration", RELOPT_TYPE_INT, \
+		OFFSET + offsetof(AutoVacOpts, log_min_duration)},   \
+		{"autovacuum_vacuum_scale_factor", RELOPT_TYPE_REAL, \
+		OFFSET + offsetof(AutoVacOpts, vacuum_scale_factor)},\
+		{"autovacuum_analyze_scale_factor", RELOPT_TYPE_REAL,\
+		OFFSET + offsetof(AutoVacOpts, analyze_scale_factor)}
+
+/*
+ * Option parser for heap
  */
 bytea *
-default_reloptions(Datum reloptions, bool validate, relopt_kind kind)
+heap_reloptions(Datum reloptions, bool validate)
 {
 	relopt_value *options;
-	StdRdOptions *rdopts;
+	HeapRelOptions *rdopts;
 	int			numoptions;
 	static const relopt_parse_elt tab[] = {
-		{"fillfactor", RELOPT_TYPE_INT, offsetof(StdRdOptions, fillfactor)},
-		{"autovacuum_enabled", RELOPT_TYPE_BOOL,
-		offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, enabled)},
-		{"a

Re: [PATCH] get rid of StdRdOptions, use individual binary reloptions representation for each relation kind instead

2019-03-31 Thread Nikolay Shaplov
В письме от понедельник, 18 марта 2019 г. 17:00:24 MSK пользователь Kyotaro 
HORIGUCHI написал:

> > So I change status to "Waiting for Author".
> That seems to be a good oppotunity. I have some comments.
> 
> rel.h:
> -#define RelationGetToastTupleTarget(relation, defaulttarg) \
> -((relation)->rd_options ? \
> - ((StdRdOptions *) (relation)->rd_options)->toast_tuple_target :
> (defaulttarg)) +#define RelationGetToastTupleTarget(relation, defaulttarg) 
>\ +(AssertMacro(relation->rd_rel->relkind ==
> RELKIND_RELATION ||\ + relation->rd_rel->relkind ==
> RELKIND_MATVIEW),\ + ((relation)->rd_options ? 
>\ +  ((HeapRelOptions *)
> (relation)->rd_options)->toast_tuple_target : \ +   
> (defaulttarg)))
> 
> Index AMs parse reloptions by their handler
> functions. HeapRelOptions in this patch are parsed in
> relation_reloptions calling heap_reloptions. Maybe at least it
> should be called as table_options. But I'm not sure what is the
> desirable shape of relation_reloptions for the moment.

If we create some TableOptions, or table_options  we will create a bigger 
mess, then we have now. Table == relation, and index is also relation.
So better to follow the rule: we have heap relation, toast relation, and all 
variety  of index relations. Each kind of relation have it's own options set, 
each kind of relation has own marcoses to access it's options. This will make 
the situation more structured. 

> -saveFreeSpace = RelationGetTargetPageFreeSpace(relation,
> -  
> HEAP_DEFAULT_FILLFACTOR); +if (IsToastRelation(relation))
> +saveFreeSpace = ToastGetTargetPageFreeSpace();
> +else
> +saveFreeSpace = HeapGetTargetPageFreeSpace(relation);
> 
> This locution appears four times in the patch and that's the all
> where the two macros appear. And it might not be good that
> RelationGetBufferForTuple identifies a heap directly since I
> suppose that currently tost is a part of heap. Thus it'd be
> better that HeapGetTargetPageFreeSpace handles the toast case.
> Similary, it doesn't looks good that RelationGetBufferForTuple
> consults HeapGetTargretPageFreeSpace() directly. Perhaps it
> should be called via TableGetTargetPageFreeSpace(). I'm not sure
> what is the right shape of the relationship among a relation and
> a table and other kinds of relation. extract_autovac_opts
> penetrates through the modularity boundary of toast/heap in a
> similar way.
So I started from the idea, I said above: each relation kind has it's own 
macroses to access it's option.
If some options are often used combined, it might be good to create some 
helper-macros, that will do this combination. But Alvaro is against adding any 
new macroses (I understand why), and keep old one as intact as possible. So 
here I can suggest only one thing: keep to the rule: "Each reloption kind has 
it's own option access macroses" and let the developers of heap-core make 
their live more comfortable with a helpers function the way they need it. 

So I would leave this decision to Alvaro... He knows better...

> plancat.c:
> +if (relation->rd_rel->relkind == RELKIND_RELATION ||
> +relation->rd_rel->relkind == RELKIND_MATVIEW)
> +rel->rel_parallel_workers = RelationGetParallelWorkers(relation,
> -1); +else
> +rel->rel_parallel_workers = -1;
> 
> rel.h:
> #define RelationGetParallelWorkers(relation, defaultpw) \
> (AssertMacro(relation->rd_rel->relkind == RELKIND_RELATION ||\
>  relation->rd_rel->relkind == RELKIND_MATVIEW),\
> ((relation)->rd_options ? \
> ((HeapRelOptions *) (relation)->rd_options)->parallel_workers : \
> (defaultpw)))
> 
> These function/macros are doing the same check twice at a call.
No. The first check is actual check, that does in runtime in production, and it 
decides if we need to fetch some options or just use default value.

The second check is AssertMacro check. If you look into AssertMacro code you 
will see that in production builds it do not perform any real check, just an 
empty function.
AssertMacro is needed for developer builds, where it would crash if check is 
not passed. It is needed to make sure that function is always used in proper 
context. You should build postgres with --enable-cassert options to get it to 
work. So there is no double checks here...







Re: [PATCH] get rid of StdRdOptions, use individual binary reloptions representation for each relation kind instead

2019-03-31 Thread Nikolay Shaplov
В письме от среда, 20 марта 2019 г. 6:15:38 MSK пользователь Iwata, Aya 
написал:

> You told us "big picture" about opclass around the beginning of this thread.
> In my understanding, the purpose of this refactoring is to make reloptions
> more flexible to add opclass. I understand this change may be needed for
> opclass, however I think that this is not the best way to refactor
> reloption.
> 
> How about discussing more about this specification including opclass, and
> finding the best way to refactor reloption? I have not read the previous
> thread tightly, so you may have already started preparing.

The idea is the following: now there are options that are build in (and 
actually nailed to) the postgres core. And there are options that can be 
created in Access  Methods in extensions. They share some code, but not all of 
it. And it is bad. There should be one set of option-related code for both 
in-core relations and indexes, and for indexes from extensions. If this code 
is well written it can be used for opclass options as well.

So we need to unnail options code from reloptions.c, so no options are nailed 
to it. 
So you need to move options definitions (at least for indexes) inside access 
method code. But we can't do it just that, because some indexes uses 
StdRdOptions structure for options, it is big, and indexes uses only fillfactor 
from there...
What should we do? Create an individual Options structure for each index.
So we did it.
And now we have StdRdOptions that is used only for Heap and Toast. And Toast 
also does not use all of the variables of the structure.
Why everywhere we have it's own option structure, but for Heap and Toast it is 
joined, and in not a very effective way? 
To successfully apply a patch I plan to commit I need a single option 
structure for each relation kind. Otherwise I will have to write some hack 
code around it.
I do not want to do so. So it is better to get rid of StdRdOptions completely.

This is the only purpose of this patch. Get rid of StdRdOptions and give each 
relation kind it's own option set. 

StdRdOptions is ancient stuff. I guess it were added when there was fillfactor 
only. Now life is more complex. Each relation kind has it's own set of 
options. Let's not mix them together!

PS. If you wand to have some impression of what refactioring I am planning at 
the end, have a look at the patch https://commitfest.postgresql.org/15/992/
It is old, but you can get an idea.





Re: Ltree syntax improvement

2019-03-31 Thread Nikolay Shaplov
В письме от четверг, 7 марта 2019 г. 13:09:49 MSK пользователь Chris Travers 
написал:

>  We maintain an extension (https://github.com/adjust/wltree)
> which has a fixed separator (::) and allows any utf-8 character in the tree.
> 
> In our case we currently use our extended tree to store user-defined
> hierarchies of labels, which might contain whitespace, Chinese, Japanese,
> or Korean characters, etc.
> 
> I would love to be able to deprecate our work on this extension and
> eventually use stock ltree.
I am afraid, that if would not be possible to have ltree with custom 
separator. Or we need to pass a very long way to reach there.

To have custom separator we will need some place to store it.

We can use GUC variable, and set separator for ltree globally. It might solve 
some of the problems. But will get some more. If for example we dump database, 
and then restore it on instance where that GUC option is not set, everything 
will be brocken.

It is not opclass option (that are discussed  here on the list), because 
opclass options is no about parsing, but about comparing things that was 
already parsed.

It is not option of an attribute (if we can have custom attribute option), 
because we can have ltree as a variable, without creating an attribute...

It should be an option of ltree type itself. I have no idea how we can 
implement this. And who will allow us to commit such strange thing ;-)




[PATCH][PROPOSAL] Refuse setting toast.* reloptions when TOAST table does not exist

2018-01-17 Thread Nikolay Shaplov

Hi!
This patch is part of a bigger patch I've offered before
https://www.postgresql.org/message-id/flat/2146419.veIEZdk4E4@x200m#2146419.veIEZdk4E4@x200m
as we agreed I am trying to commit it by smaller bits

This patch raises error if user tries o set or change toast.* option for a
table that does not have a TOST relation.

I believe it is the only right thing to do, as now if you set toast reloption
for table that does not  have TOAST table, the value of this option will be
lost without any warning. You will not get it back with pg_dump, it will not
be effective when you add varlen attributes to the table later.

So you offer DB some value to store, it accepts it without errors, and
immediately loses it. I would consider it a bad behavior.

I also think that we should not change this error to warning, as toast.*
options are usually used by very experienced users for precised DB tunning. I
hardly expect them to do TOAST tuning for tables without TOAST relations. So
chances to get problem with existing SQL code are minimal.

So I would suggest to throw an error in this case.

Possible flaws: I tied to write error messages according to guide lines. But I
suppose it is still not prefect enough as I am not so good with English. May
be somebody who knows the language well, can make it better.

--
Do code for fun.diff --git a/src/backend/catalog/toasting.c b/src/backend/catalog/toasting.c
index 0b4b5631..2551023 100644
--- a/src/backend/catalog/toasting.c
+++ b/src/backend/catalog/toasting.c
@@ -36,7 +36,7 @@
 /* Potentially set by pg_upgrade_support functions */
 Oid			binary_upgrade_next_toast_pg_type_oid = InvalidOid;

-static void CheckAndCreateToastTable(Oid relOid, Datum reloptions,
+static bool CheckAndCreateToastTable(Oid relOid, Datum reloptions,
 		 LOCKMODE lockmode, bool check);
 static bool create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid,
    Datum reloptions, LOCKMODE lockmode, bool check);
@@ -67,23 +67,26 @@ NewHeapCreateToastTable(Oid relOid, Datum reloptions, LOCKMODE lockmode)
 	CheckAndCreateToastTable(relOid, reloptions, lockmode, false);
 }

-void
+bool
 NewRelationCreateToastTable(Oid relOid, Datum reloptions)
 {
-	CheckAndCreateToastTable(relOid, reloptions, AccessExclusiveLock, false);
+	return CheckAndCreateToastTable(relOid, reloptions,
+	AccessExclusiveLock, false);
 }

-static void
+static bool
 CheckAndCreateToastTable(Oid relOid, Datum reloptions, LOCKMODE lockmode, bool check)
 {
 	Relation	rel;
+	bool		success;

 	rel = heap_open(relOid, lockmode);

 	/* create_toast_table does all the work */
-	(void) create_toast_table(rel, InvalidOid, InvalidOid, reloptions, lockmode, check);
+	success = create_toast_table(rel, InvalidOid, InvalidOid, reloptions, lockmode, check);

 	heap_close(rel, NoLock);
+	return success;
 }

 /*
diff --git a/src/backend/commands/createas.c b/src/backend/commands/createas.c
index 3d82edb..7745aa5 100644
--- a/src/backend/commands/createas.c
+++ b/src/backend/commands/createas.c
@@ -89,6 +89,7 @@ create_ctas_internal(List *attrList, IntoClause *into)
 	Datum		toast_options;
 	static char *validnsps[] = HEAP_RELOPT_NAMESPACES;
 	ObjectAddress intoRelationAddr;
+	bool		toast_created;

 	/* This code supports both CREATE TABLE AS and CREATE MATERIALIZED VIEW */
 	is_matview = (into->viewQuery != NULL);
@@ -130,7 +131,15 @@ create_ctas_internal(List *attrList, IntoClause *into)

 	(void) heap_reloptions(RELKIND_TOASTVALUE, toast_options, true);

-	NewRelationCreateToastTable(intoRelationAddr.objectId, toast_options);
+	toast_created = NewRelationCreateToastTable(intoRelationAddr.objectId,
+toast_options);
+	if (!toast_created && toast_options)
+		ereport(ERROR,
+(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("can't set TOAST relation options for a new table"),
+ errdetail("TOAST relation were not created"),
+ errhint("do not specify toast.* options, or add some variable length attributes to the table")
+ ));

 	/* Create the "view" part of a materialized view. */
 	if (is_matview)
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index f2a928b..a169e14 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -10557,6 +10557,19 @@ ATExecSetRelOptions(Relation rel, List *defList, AlterTableType operation,

 		heap_close(toastrel, NoLock);
 	}
+	else
+	{
+		newOptions = transformRelOptions((Datum) 0, defList, "toast",
+		 validnsps, false, false);
+		if (newOptions)
+			ereport(ERROR,
+	(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+errmsg("can't alter TOAST relation options for \"%s\" table",
+	   RelationGetRelationName(rel)),
+	 errdetail("TOAST relation does not exist"),
+	 errhint("do not specify toast.* options, or add some variable length attributes to the table")
+	 ));
+	}

 	heap_close(pgclass, RowExclusiveLock);
 }
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index ec98

Re: [HACKERS] [PATCH] Move all am-related reloption code into src/backend/access/[am-name] and get rid of relopt_kind for custom AM

2018-01-17 Thread Nikolay Shaplov
В письме от 3 сентября 2017 11:45:43 пользователь Alvaro Herrera написал:

> The new checks around toast table creation look like they belong to a
> completely independent patch also ... the error message there goes
> against message style guidelines also.

Offered toast relation checks as a separate patch:
https://www.postgresql.org/message-id/3413542.LWpeoxCNq5@x200m


-- 
Do code for fun.

signature.asc
Description: This is a digitally signed message part.


Re: [PATCH][PROPOSAL] Refuse setting toast.* reloptions when TOAST table does not exist

2018-01-19 Thread Nikolay Shaplov
В письме от 18 января 2018 18:42:01 пользователь Tom Lane написал:
> >> This patch raises error if user tries o set or change toast.* option for
> >> a
> >> table that does not have a TOST relation.
> > 
> > I think there is a problem with this idea, which is that the rules for
> > whether or not a given table has an associated TOAST table
> > occasionally change from one major release to the next.  Suppose that,
> > in release X, a particular table definition causes a TOAST table to be
> > created, but in release X+1, it does not.  If a table with that
> > definition has a toast.* option set, then upgrading from release X to
> > release X+1 via pg_dump and restore will fail.  That's bad.
> 
> Yeah --- and it doesn't even have to be a major version change; the
> same version on different hardware might make different choices too.
> Not to mention that there is discussion out there about making the
> toasting rules more configurable.
> 
> There might be a case for raising a warning in this situation,
> but I would disagree with making it a hard error in any case.
> All that's going to accomplish is to break people's scripts and
> get them mad at you.

These all sound very reasonable, but still does not solve problem with loosing 
toast option values when you set one for table without TOAST relation.

May be, if reasons for existence TOAST relation is no so much fixed thing (I 
thought it is almost as fixed as a rock), may be the solution would be to 
create a TOAST relation anyway if toast options is set, and gave a warning 
that may be setting this option is not the thing the user really want?
This way we will not loose option values. And it would be 100% backward 
compatible.

The main misfeature here is that we will have empty TOAST relation in this 
case. But first I do not think it will really harm anybody, and second, we 
would WARN that it is not the best way to do things, so DB user will be able 
to find way around.

What do you think about it?

-- 
Do code for fun.

signature.asc
Description: This is a digitally signed message part.


[PATCH][PROPOSAL] Add enum releation option type

2018-01-21 Thread Nikolay Shaplov

Hi!
While working with my big reloption patch,
https://www.postgresql.org/message-id/flat/2146419.veIEZdk4E4@x200m#2146419.veIEZdk4E4@x200m
I found out, that all relation options of string type in current postgres, are
actually behaving as "enum" type. But each time this behavior is implemented
as validate function plus strcmp to compare option value against one of the
possible values.

I think it is not the best practice. It is better to have enum type where it
is technically enum, and keep sting type for further usage (for example for
some kind of index patterns or something like this).

Now strcmp in this case does not really slow down postgres, as both string
options are checked when index is created. One check there will not really
slow down. But if in future somebody would want to have such option checked on
regular basis, it is better to have it as enum type: once "strcmp" it while
parsing, and then just "==" when one need to check option value in runtime.

The patch is in attachment. I hope the code is quite clear.

Possible flaws:

1. I've changed error message from 'Valid values are "XXX", "YYY" and "ZZZ".'
to 'Valid values are "XXX", "YYY", "ZZZ".' to make a code a bit simpler. If it
is not acceptable, please let me know, I will add "and" to the string.

2. Also about the string with the list of acceptable values: the code that
creates this string is inside parse_one_reloption function now. It is a bit
too complex. May be there is already exists some helper function that creates
a string "XXX", "YYY", "ZZZ" from the list of XXX YYY ZZZ values, I do not
know of? Or may be it is reason to create such a function. If so where to
create it? Inside "reloptions.c"? Or it can be reused and I'd better put it
somewhere else?

I hope there would be not further difficulties with this patch. Hope it can be
committed in proper time.

--
Do code for fun.diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c
index 274f7aa..3d12a30 100644
--- a/src/backend/access/common/reloptions.c
+++ b/src/backend/access/common/reloptions.c
@@ -404,7 +404,9 @@ static relopt_real realRelOpts[]  	{{NULL}}
 };

-static relopt_string stringRelOpts[] +static const char *gist_buffering_enum_names[] = GIST_OPTION_BUFFERING_VALUE_NAMES;
+static const char *view_check_option_names[] = VIEW_OPTION_CHECK_OPTION_VALUE_NAMES;
+static relopt_enum enumRelOpts[]  {
 	{
 		{
@@ -413,10 +415,8 @@ static relopt_string stringRelOpts[]  			RELOPT_KIND_GIST,
 			AccessExclusiveLock
 		},
-		4,
-		false,
-		gistValidateBufferingOption,
-		"auto"
+		gist_buffering_enum_names,
+		GIST_OPTION_BUFFERING_AUTO
 	},
 	{
 		{
@@ -425,11 +425,14 @@ static relopt_string stringRelOpts[]  			RELOPT_KIND_VIEW,
 			AccessExclusiveLock
 		},
-		0,
-		true,
-		validateWithCheckOption,
-		NULL
+		view_check_option_names,
+		VIEW_OPTION_CHECK_OPTION_NOT_SET
 	},
+	{{NULL}}
+};
+
+static relopt_string stringRelOpts[] +{
 	/* list terminator */
 	{{NULL}}
 };
@@ -476,6 +479,12 @@ initialize_reloptions(void)
    realRelOpts[i].gen.lockmode));
 		j++;
 	}
+	for (i = 0; enumRelOpts[i].gen.name; i++)
+	{
+		Assert(DoLockModesConflict(enumRelOpts[i].gen.lockmode,
+   enumRelOpts[i].gen.lockmode));
+		j++;
+	}
 	for (i = 0; stringRelOpts[i].gen.name; i++)
 	{
 		Assert(DoLockModesConflict(stringRelOpts[i].gen.lockmode,
@@ -514,6 +523,14 @@ initialize_reloptions(void)
 		j++;
 	}

+	for (i = 0; enumRelOpts[i].gen.name; i++)
+	{
+		relOpts[j] = &enumRelOpts[i].gen;
+		relOpts[j]->type = RELOPT_TYPE_ENUM;
+		relOpts[j]->namelen = strlen(relOpts[j]->name);
+		j++;
+	}
+
 	for (i = 0; stringRelOpts[i].gen.name; i++)
 	{
 		relOpts[j] = &stringRelOpts[i].gen;
@@ -611,6 +628,9 @@ allocate_reloption(bits32 kinds, int type, const char *name, const char *desc)
 		case RELOPT_TYPE_REAL:
 			size = sizeof(relopt_real);
 			break;
+		case RELOPT_TYPE_ENUM:
+			size = sizeof(relopt_enum);
+			break;
 		case RELOPT_TYPE_STRING:
 			size = sizeof(relopt_string);
 			break;
@@ -690,6 +710,24 @@ add_real_reloption(bits32 kinds, const char *name, const char *desc, double defa
 }

 /*
+ * add_enuum_reloption
+ *		Add a new enum reloption
+ */
+void
+add_enum_reloption(bits32 kinds, const char *name, const char *desc,
+	 const char **allowed_values, int default_val)
+{
+	relopt_enum *newoption;
+
+	newoption = (relopt_enum *) allocate_reloption(kinds, RELOPT_TYPE_ENUM,
+   name, desc);
+	newoption->allowed_values = allowed_values;
+	newoption->default_val = default_val;
+
+	add_reloption((relopt_gen *) newoption);
+}
+
+/*
  * add_string_reloption
  *		Add a new string reloption
  *
@@ -1192,6 +1230,78 @@ parse_one_reloption(relopt_value *option, char *text_str, int text_len,
 	   optreal->min, optreal->max)));
 			}
 			break;
+		case RELOPT_TYPE_ENUM:
+			{
+relopt_enum *opt_enum = (relopt_enum *) option->gen;
+int			i = 0;
+
+parsed = false;
+while (opt_enum->allowed_values[i])
+{
+	if (pg_

Re: [HACKERS] [PATCH] Move all am-related reloption code into src/backend/access/[am-name] and get rid of relopt_kind for custom AM

2018-01-21 Thread Nikolay Shaplov
В письме от 3 сентября 2017 11:45:43 пользователь Alvaro Herrera написал:

> I think we should split this in at least two commits,
Added another part for commit:
https://www.postgresql.org/message-id/43332102.S2V5pIjXRx@x200m
This one adds an enum relation option type.

-- 
Do code for fun.

signature.asc
Description: This is a digitally signed message part.


[PATCH] Minor fixes for reloptions tests

2018-01-22 Thread Nikolay Shaplov

I have a small fixes for already committed reloption test patch
(https://www.postgresql.org/message-id/2615372.orqtEn8VGB@x200m)

First one is missing tab symbol where it should be.

The second is a comment. "The OIDS option is not stored" is not quite correct.
They are stored, but not as reloption. I've added this notion there...


--
Do code for fun.diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index c4107d5..df3c99d 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -77,7 +77,7 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 ALTER TABLE reloptions_test RESET (autovacuum_enabled,
 	autovacuum_analyze_scale_factor);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass AND
-reloptions IS NULL;
+   reloptions IS NULL;
  reloptions
 

@@ -86,7 +86,7 @@ reloptions IS NULL;
 -- RESET fails if a value is specified
 ALTER TABLE reloptions_test RESET (fillfactor);
 ERROR:  RESET must not include values for parameters
--- The OIDS option is not stored
+-- The OIDS option is not stored as reloption
 DROP TABLE reloptions_test;
 CREATE TABLE reloptions_test(i INT) WITH (fillfactor , oids=true);
 SELECT reloptions, relhasoids FROM pg_class WHERE oid = 'reloptions_test'::regclass;
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index c9119fd..37fbf41 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -47,12 +47,12 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 ALTER TABLE reloptions_test RESET (autovacuum_enabled,
 	autovacuum_analyze_scale_factor);
 SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass AND
-reloptions IS NULL;
+   reloptions IS NULL;

 -- RESET fails if a value is specified
 ALTER TABLE reloptions_test RESET (fillfactor);

--- The OIDS option is not stored
+-- The OIDS option is not stored as reloption
 DROP TABLE reloptions_test;
 CREATE TABLE reloptions_test(i INT) WITH (fillfactor , oids=true);
 SELECT reloptions, relhasoids FROM pg_class WHERE oid = 'reloptions_test'::regclass;


signature.asc
Description: This is a digitally signed message part.


Re: [HACKERS] [PATCH] Tests for reloptions

2018-01-22 Thread Nikolay Shaplov
В письме от 29 октября 2017 17:08:29 пользователь Nikolay Shaplov написал:
 
> While merging this commit to my branch, I found two issues that as I think
> needs fixing. Hope this does not require creating new commit request...

To draw more attention to this issue, I've filed it as a new thread
https://www.postgresql.org/message-id/3951112.MkJ1MAZpIQ%40x200m
with a entry for next commit fest.
Hope this will help fixing missing tab.


-- 
Do code for fun.

signature.asc
Description: This is a digitally signed message part.


Re: [PATCH][PROPOSAL] Refuse setting toast.* reloptions when TOAST table does not exist

2018-01-23 Thread Nikolay Shaplov
В письме от 23 января 2018 12:03:50 пользователь Peter Eisentraut написал:

> >>> This patch raises error if user tries o set or change toast.* option for
> >>> a table that does not have a TOST relation.
> > 
> > There might be a case for raising a warning in this situation,
> > but I would disagree with making it a hard error in any case.
> > All that's going to accomplish is to break people's scripts and
> > get them mad at you.
> 
> It might also be useful to set these reloptions before you add a new
> column to a table.
As Robert have just said, this will not work with current master.

If we, as I've suggested in previous letter, will force TOAST creation if 
toast.* option is set, then your use case will also work.

-- 
Do code for fun.

signature.asc
Description: This is a digitally signed message part.


Re: [PATCH][PROPOSAL] Refuse setting toast.* reloptions when TOAST table does not exist

2018-01-25 Thread Nikolay Shaplov
В письме от 25 января 2018 11:29:34 пользователь Tom Lane написал:
> Alvaro Herrera  writes:
> > Tom Lane wrote:
> >> Well, maybe the right answer is to address that.  It's clear to me
> >> why that would happen if we store these things as reloptions on the
> >> toast table, but can't they be stored on the parent table?
> > 
> > Actually, Nikolay provided a possible solution: if you execute ALTER
> > TABLE SET (toast.foobar = xyz), and a toast table doesn't exist, create
> > one at that point.
> 
> That adds a lot of overhead if you never actually need the toast table.
I think this overhead case is not that terrible if it is properly warned ;-)

> Still, maybe it's an appropriate amount of effort compared to the size
> of the use-case for this.
If you came to some final conclustion, please close the commiffest item with 
"Return with feedback" resolution, and I write another patch... 

-- 
Do code for fun.

signature.asc
Description: This is a digitally signed message part.


Re: [PATCH][PROPOSAL] Add enum releation option type

2018-02-11 Thread Nikolay Shaplov
В письме от 9 февраля 2018 18:45:29 пользователь Alvaro Herrera написал:

> If this patch gets in, I wonder if there are any external modules that
> use actual strings.  An hypothetical example would be something like a
> SSL cipher list; it needs to be somewhat free-form that an enum would
> not cut it.  If there are such modules, then even if we remove all
> existing in-core use cases we should keep the support code for strings.
I did not remove string option support from the code. It might be needed 
later.

> Maybe we need some in-core user to verify the string case still works.
> A new module in src/test/modules perhaps?  
This sound as a good idea. I am too do not feel really comfortable with that 
this string options possibility exists, but is not tested. I'll have a look 
there, it it will not require a great job, I will add tests for string options 
there.

> On the other hand, if we can
> find no use for these string reloptions, maybe we should just remove the
> support, since as I recall it's messy enough.
No, the implementation of string options is quite good. And may be needed 
later.

> > Possible flaws:
> > 
> > 1. I've changed error message from 'Valid values are "XXX", "YYY" and
> > "ZZZ".' to 'Valid values are "XXX", "YYY", "ZZZ".' to make a code a bit
> > simpler. If it is not acceptable, please let me know, I will add "and" to
> > the string.
> I don't think we care about this, but is this still the case if you use
> a stringinfo?
May be not. I'll try to do it better.

> > 2. Also about the string with the list of acceptable values: the code that
> > creates this string is inside parse_one_reloption function now.
> 
> I think you could save most of that mess by using appendStringInfo and
> friends.
Thanks. I will rewrite this part using these functions. That was really 
helpful.

> I don't much like the way you've represented the list of possible values
> for each enum.  I think it'd be better to have a struct that represents
> everything about each value (string name and C symbol.
I actually do not like it this way too. I would prefer one structure, not two 
lists. But I did not find way how to do it in one struct. How to gave have 
string value and C symbol in one structure, without defining C symbols 
elsewhere. Otherwise it will be two lists again.
I do not have a lot of hardcore C development experience, so I can miss 
something. Can you provide an example of the structure you are talking about? 

> Maybe the
> numerical value too if that's needed, but is it?  I suppose all code
> should use the C symbol only, so why do we care about the numerical
> value?).
It is comfortable to have numerical values when debugging. I like to write 
something like

elog(WARNING,"buffering_mode=%i",opt.buffering_mode);

to check that everything works as expected. Such cases is the only reason to 
keep numerical value.


-- 
Do code for fun.

signature.asc
Description: This is a digitally signed message part.


Re: [PATCH][PROPOSAL] Add enum releation option type

2018-02-14 Thread Nikolay Shaplov
В письме от 9 февраля 2018 18:45:29 пользователь Alvaro Herrera написал:

> > 1. I've changed error message from 'Valid values are "XXX", "YYY" and
> > "ZZZ".' to 'Valid values are "XXX", "YYY", "ZZZ".' to make a code a bit
> > simpler. If it is not acceptable, please let me know, I will add "and" to
> > the string.
> I don't think we care about this, but is this still the case if you use
> a stringinfo?
>
> > 2. Also about the string with the list of acceptable values: the code that
> > creates this string is inside parse_one_reloption function now.
>
> I think you could save most of that mess by using appendStringInfo and
> friends.

Here is the second verion of the patch where I use appendStringInfo to prepare
error message. The code is much more simple here now, and it now create value
list with "and" at the end: '"xxx", "yyy" and "zzz"'


--
Do code for fun.diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c
index 46276ce..82a0492 100644
--- a/src/backend/access/common/reloptions.c
+++ b/src/backend/access/common/reloptions.c
@@ -404,7 +404,9 @@ static relopt_real realRelOpts[]  	{{NULL}}
 };

-static relopt_string stringRelOpts[] +static const char *gist_buffering_enum_names[] = GIST_OPTION_BUFFERING_VALUE_NAMES;
+static const char *view_check_option_names[] = VIEW_OPTION_CHECK_OPTION_VALUE_NAMES;
+static relopt_enum enumRelOpts[]  {
 	{
 		{
@@ -413,10 +415,8 @@ static relopt_string stringRelOpts[]  			RELOPT_KIND_GIST,
 			AccessExclusiveLock
 		},
-		4,
-		false,
-		gistValidateBufferingOption,
-		"auto"
+		gist_buffering_enum_names,
+		GIST_OPTION_BUFFERING_AUTO
 	},
 	{
 		{
@@ -425,11 +425,14 @@ static relopt_string stringRelOpts[]  			RELOPT_KIND_VIEW,
 			AccessExclusiveLock
 		},
-		0,
-		true,
-		validateWithCheckOption,
-		NULL
+		view_check_option_names,
+		VIEW_OPTION_CHECK_OPTION_NOT_SET
 	},
+	{{NULL}}
+};
+
+static relopt_string stringRelOpts[] +{
 	/* list terminator */
 	{{NULL}}
 };
@@ -476,6 +479,12 @@ initialize_reloptions(void)
    realRelOpts[i].gen.lockmode));
 		j++;
 	}
+	for (i = 0; enumRelOpts[i].gen.name; i++)
+	{
+		Assert(DoLockModesConflict(enumRelOpts[i].gen.lockmode,
+   enumRelOpts[i].gen.lockmode));
+		j++;
+	}
 	for (i = 0; stringRelOpts[i].gen.name; i++)
 	{
 		Assert(DoLockModesConflict(stringRelOpts[i].gen.lockmode,
@@ -514,6 +523,14 @@ initialize_reloptions(void)
 		j++;
 	}

+	for (i = 0; enumRelOpts[i].gen.name; i++)
+	{
+		relOpts[j] = &enumRelOpts[i].gen;
+		relOpts[j]->type = RELOPT_TYPE_ENUM;
+		relOpts[j]->namelen = strlen(relOpts[j]->name);
+		j++;
+	}
+
 	for (i = 0; stringRelOpts[i].gen.name; i++)
 	{
 		relOpts[j] = &stringRelOpts[i].gen;
@@ -611,6 +628,9 @@ allocate_reloption(bits32 kinds, int type, const char *name, const char *desc)
 		case RELOPT_TYPE_REAL:
 			size = sizeof(relopt_real);
 			break;
+		case RELOPT_TYPE_ENUM:
+			size = sizeof(relopt_enum);
+			break;
 		case RELOPT_TYPE_STRING:
 			size = sizeof(relopt_string);
 			break;
@@ -690,6 +710,24 @@ add_real_reloption(bits32 kinds, const char *name, const char *desc, double defa
 }

 /*
+ * add_enuum_reloption
+ *		Add a new enum reloption
+ */
+void
+add_enum_reloption(bits32 kinds, const char *name, const char *desc,
+	 const char **allowed_values, int default_val)
+{
+	relopt_enum *newoption;
+
+	newoption = (relopt_enum *) allocate_reloption(kinds, RELOPT_TYPE_ENUM,
+   name, desc);
+	newoption->allowed_values = allowed_values;
+	newoption->default_val = default_val;
+
+	add_reloption((relopt_gen *) newoption);
+}
+
+/*
  * add_string_reloption
  *		Add a new string reloption
  *
@@ -1190,6 +1228,50 @@ parse_one_reloption(relopt_value *option, char *text_str, int text_len,
 	   optreal->min, optreal->max)));
 			}
 			break;
+		case RELOPT_TYPE_ENUM:
+			{
+relopt_enum *opt_enum = (relopt_enum *) option->gen;
+int			i = 0;
+
+parsed = false;
+while (opt_enum->allowed_values[i])
+{
+	if (pg_strcasecmp(value, opt_enum->allowed_values[i]) == 0)
+	{
+		option->values.enum_val = i;
+		parsed = true;
+		break;
+	}
+	i++;
+}
+if (!parsed)
+{
+	StringInfoData buf;
+
+	initStringInfo(&buf);
+	i = 0;
+	while (opt_enum->allowed_values[i])
+	{
+		appendStringInfo(&buf,"\"%s\"",
+		 opt_enum->allowed_values[i]);
+		if (opt_enum->allowed_values[i + 1])
+		{
+			if (opt_enum->allowed_values[i + 2])
+appendStringInfo(&buf,", ");
+			else
+appendStringInfo(&buf," and ");
+		}
+		i++;
+	}
+	ereport(ERROR,
+			(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+			 errmsg("invalid value for \"%s\" option",
+	option->gen->name),
+			 errdetail("Valid values are %s.", /*str*/ buf.data)));
+	pfree(buf.data);
+}
+			}
+			break;
 		case RELOPT_TYPE_STRING:
 			{
 relopt_string *optstring = (relopt_string *) option->gen;
@@ -1283,6 +1365,11 @@ fillRelOptions(void *

Re: [PATCH][PROPOSAL] Add enum releation option type

2018-02-15 Thread Nikolay Shaplov
В письме от 9 февраля 2018 18:45:29 пользователь Alvaro Herrera написал:

> Maybe we need some in-core user to verify the string case still works.
> A new module in src/test/modules perhaps? 
I've looked attentively in src/test/modules... To properly test all reloptions 
hooks for modules wee need to create an extension with some dummy index in it. 
This way we can properly test everything. Creating dummy index would be fun, 
but it a quite big deal to create it, so it will require a separate patch to 
deal with. So I suppose string reloptions is better to leave untested for now, 
with a notion, that it should be done sooner or later

> I don't much like the way you've represented the list of possible values
> for each enum.  I think it'd be better to have a struct that represents
> everything about each value (string name and C symbol.  Maybe the
> numerical value too if that's needed, but is it?  I suppose all code
> should use the C symbol only, so why do we care about the numerical
> value?).
One more reason to keep numeric value, that came to my mind, is that it seems 
to be logical to keep enum value in postgres internals represented as C-enum. 
And C-enum is actually an int value (can be easily casted both ways). It is 
not strictly necessary, but it seems to be a bit logical... 


-- 
Do code for fun.

signature.asc
Description: This is a digitally signed message part.


Re: [PATCH][PROPOSAL] Add enum releation option type

2018-02-15 Thread Nikolay Shaplov
В письме от 15 февраля 2018 12:53:27 пользователь Alvaro Herrera написал:

> > > Maybe we need some in-core user to verify the string case still works.
> > > A new module in src/test/modules perhaps?
> > 
> > I've looked attentively in src/test/modules... To properly test all
> > reloptions hooks for modules wee need to create an extension with some
> > dummy index in it. This way we can properly test everything. Creating
> > dummy index would be fun, but it a quite big deal to create it, so it
> > will require a separate patch to deal with. So I suppose string
> > reloptions is better to leave untested for now, with a notion, that it
> > should be done sooner or later
> 
> Do we really need a dummy index?  I was thinking in something that just
> calls a few C functions to create and parse a string reloption should be
> more than enough.

Technically we can add_reloption_kind(); then add some string options to it 
using add_string_reloption, and then call fillRelOptions with some dummy data 
and validate argument on and see what will happen.

But I do not think it will test a lot. I think it is better to test it 
altogether, not just some part of it.

Moreover when my whole patch is commited these all should be rewritten, as I 
changed some options internals for some good reasons. 

So I would prefer to keep it untested while we are done with reloptions, and 
then test it in a good way, with creating dummy index and so on. I think it 
will be needed for more tests and educational purposes...

But if you will insist on it as a reviewer, I will do as you say.

> > > I don't much like the way you've represented the list of possible values
> > > for each enum.  I think it'd be better to have a struct that represents
> > > everything about each value (string name and C symbol.  Maybe the
> > > numerical value too if that's needed, but is it?  I suppose all code
> > > should use the C symbol only, so why do we care about the numerical
> > > value?).
> > 
> > One more reason to keep numeric value, that came to my mind, is that it
> > seems to be logical to keep enum value in postgres internals represented
> > as C-enum. And C-enum is actually an int value (can be easily casted both
> > ways). It is not strictly necessary, but it seems to be a bit logical...
> 
> Oh, I didn't mean to steer you away from a C enum.  I just meant that we
> don't need to define the numerical values ourselves -- it should be fine
> to use whatever the C compiler chooses for each C symbol (enum member
> name).  In the code we don't refer to the values by numerical value,
> only by the C symbol.
Ah that is what you are talking about :-)

I needed this numbers for debug purposes, nothing more. If it is not good to 
keep them, they can be removed now...
(I would prefer to keep them for further debugging, but if it is not right, I 
can easily remove them, I do not need them right now)

-- 
Do code for fun.

signature.asc
Description: This is a digitally signed message part.


Re: [PATCH] Add some useful asserts into View Options macroses

2019-11-08 Thread Nikolay Shaplov
В письме от пятница, 1 ноября 2019 г. 13:29:58 MSK пользователь Peter 
Eisentraut написал:
 
> Committed.
> 
> I simplified the parentheses by one level from your patch.
Thank you!

-- 
Software Developer: https://www.upwork.com/freelancers/~014a87e140ff02c0da
Body-oriented Therapist: https://vk.com/nataraj_rebalancing  (Russian)

Re: [PATCH] use separate PartitionedRelOptions structure to store partitioned table options

2019-11-11 Thread Nikolay Shaplov
В письме от среда, 23 октября 2019 г. 11:59:45 MSK пользователь Amit Langote 
написал:

> Sorry for the late reply.
Same apologies from my side. Get decent time-slot for postgres dev only now.



> I looked atthe v2 patch and noticed a typo:
> 
> + * Binary representation of relation options for rtitioned tables.
> 
> s/rtitioned/partitioned/g
> 
> Other than that, looks good.
Here goes v3 patch with the typo fixed

-- 
Software Developer: https://www.upwork.com/freelancers/~014a87e140ff02c0da
Body-oriented Therapist: https://vk.com/nataraj_rebalancing  (Russian)diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c
index d8790ad..d30f3db 100644
--- a/src/backend/access/common/reloptions.c
+++ b/src/backend/access/common/reloptions.c
@@ -1099,9 +1099,11 @@ extractRelOptions(HeapTuple tuple, TupleDesc tupdesc,
 		case RELKIND_RELATION:
 		case RELKIND_TOASTVALUE:
 		case RELKIND_MATVIEW:
-		case RELKIND_PARTITIONED_TABLE:
 			options = heap_reloptions(classForm->relkind, datum, false);
 			break;
+		case RELKIND_PARTITIONED_TABLE:
+			options = partitioned_table_reloptions(datum, false);
+			break;
 		case RELKIND_VIEW:
 			options = view_reloptions(datum, false);
 			break;
@@ -1572,6 +1574,25 @@ build_reloptions(Datum reloptions, bool validate,
 }
 
 /*
+ * Option parser for partitioned tables
+ */
+bytea *
+partitioned_table_reloptions(Datum reloptions, bool validate)
+{
+   int   numoptions;
+
+  /*
+   * Since there are no options for patitioned tables for now, we just do
+   * validation to report incorrect option error and leave.
+   */
+
+  if (validate)
+		parseRelOptions(reloptions, validate, RELOPT_KIND_PARTITIONED,
+		&numoptions);
+   return NULL;
+}
+
+/*
  * Option parser for views
  */
 bytea *
@@ -1614,9 +1635,6 @@ heap_reloptions(char relkind, Datum reloptions, bool validate)
 		case RELKIND_RELATION:
 		case RELKIND_MATVIEW:
 			return default_reloptions(reloptions, validate, RELOPT_KIND_HEAP);
-		case RELKIND_PARTITIONED_TABLE:
-			return default_reloptions(reloptions, validate,
-	  RELOPT_KIND_PARTITIONED);
 		default:
 			/* other relkinds are not supported */
 			return NULL;
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 5597be6..424654d 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -721,10 +721,17 @@ DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId,
 	reloptions = transformRelOptions((Datum) 0, stmt->options, NULL, validnsps,
 	 true, false);
 
-	if (relkind == RELKIND_VIEW)
-		(void) view_reloptions(reloptions, true);
-	else
-		(void) heap_reloptions(relkind, reloptions, true);
+	switch (relkind)
+	{
+		case RELKIND_VIEW:
+			(void) view_reloptions(reloptions, true);
+			break;
+		case RELKIND_PARTITIONED_TABLE:
+			(void) partitioned_table_reloptions(reloptions, true);
+			break;
+		default:
+			(void) heap_reloptions(relkind, reloptions, true);
+	}
 
 	if (stmt->ofTypename)
 	{
@@ -12189,9 +12196,11 @@ ATExecSetRelOptions(Relation rel, List *defList, AlterTableType operation,
 		case RELKIND_RELATION:
 		case RELKIND_TOASTVALUE:
 		case RELKIND_MATVIEW:
-		case RELKIND_PARTITIONED_TABLE:
 			(void) heap_reloptions(rel->rd_rel->relkind, newOptions, true);
 			break;
+		case RELKIND_PARTITIONED_TABLE:
+			(void) partitioned_table_reloptions(newOptions, true);
+			break;
 		case RELKIND_VIEW:
 			(void) view_reloptions(newOptions, true);
 			break;
diff --git a/src/include/access/reloptions.h b/src/include/access/reloptions.h
index db42aa3..ee7248a 100644
--- a/src/include/access/reloptions.h
+++ b/src/include/access/reloptions.h
@@ -306,6 +306,7 @@ extern bytea *default_reloptions(Datum reloptions, bool validate,
  relopt_kind kind);
 extern bytea *heap_reloptions(char relkind, Datum reloptions, bool validate);
 extern bytea *view_reloptions(Datum reloptions, bool validate);
+extern bytea *partitioned_table_reloptions(Datum reloptions, bool validate);
 extern bytea *index_reloptions(amoptions_function amoptions, Datum reloptions,
 			   bool validate);
 extern bytea *attribute_reloptions(Datum reloptions, bool validate);
diff --git a/src/include/utils/rel.h b/src/include/utils/rel.h
index 8b8b237..1eb323a 100644
--- a/src/include/utils/rel.h
+++ b/src/include/utils/rel.h
@@ -278,6 +278,16 @@ typedef struct StdRdOptions
 #define HEAP_DEFAULT_FILLFACTOR		100
 
 /*
+ * PartitionedRelOptions
+ * Binary representation of relation options for partitioned tables.
+ */
+typedef struct PartitionedRelOptions
+{
+   int32   vl_len_;/* varlena header (do not touch directly!) */
+   /* No options defined yet */
+} PartitionedRelOptions;
+
+/*
  * RelationGetToastTupleTarget
  *		Returns the relation's toast_tuple_target.  Note multiple eval of argument!
  */


Re: [PATCH] Do not use StdRdOptions in Access Methods

2019-11-13 Thread Nikolay Shaplov
В письме от среда, 13 ноября 2019 г. 16:05:20 MSK пользователь Michael Paquier 
написал:

Guys! Sorry for being away for so long. I did not have much opportunities to 
pay my attention to postgres recently.

Thank you for introducing build_reloptions function. It is approximately the 
direction I wanted to move afterwards myself. 

But nevertheless, I am steady on my way, and I want to get rid of StdRdOptions 
before doing anything else myself. This structure is long outdated and is not 
suitable for access method's options at all.

I've changed the patch to use build_reloptions function and again propose it 
to the commitfest.



-- 
Software Developer: https://www.upwork.com/freelancers/~014a87e140ff02c0da
Body-oriented Therapist: https://vk.com/nataraj_rebalancing  (Russian)diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c
index d8790ad..f40d68c 100644
--- a/src/backend/access/common/reloptions.c
+++ b/src/backend/access/common/reloptions.c
@@ -23,7 +23,7 @@
 #include "access/htup_details.h"
 #include "access/nbtree.h"
 #include "access/reloptions.h"
-#include "access/spgist.h"
+#include "access/spgist_private.h"
 #include "catalog/pg_type.h"
 #include "commands/defrem.h"
 #include "commands/tablespace.h"
@@ -1510,8 +1510,6 @@ default_reloptions(Datum reloptions, bool validate, relopt_kind kind)
 		offsetof(StdRdOptions, user_catalog_table)},
 		{"parallel_workers", RELOPT_TYPE_INT,
 		offsetof(StdRdOptions, parallel_workers)},
-		{"vacuum_cleanup_index_scale_factor", RELOPT_TYPE_REAL,
-		offsetof(StdRdOptions, vacuum_cleanup_index_scale_factor)},
 		{"vacuum_index_cleanup", RELOPT_TYPE_BOOL,
 		offsetof(StdRdOptions, vacuum_index_cleanup)},
 		{"vacuum_truncate", RELOPT_TYPE_BOOL,
diff --git a/src/backend/access/hash/hashpage.c b/src/backend/access/hash/hashpage.c
index 63697bf..0cc4cb6 100644
--- a/src/backend/access/hash/hashpage.c
+++ b/src/backend/access/hash/hashpage.c
@@ -358,7 +358,7 @@ _hash_init(Relation rel, double num_tuples, ForkNumber forkNum)
 	data_width = sizeof(uint32);
 	item_width = MAXALIGN(sizeof(IndexTupleData)) + MAXALIGN(data_width) +
 		sizeof(ItemIdData);		/* include the line pointer */
-	ffactor = RelationGetTargetPageUsage(rel, HASH_DEFAULT_FILLFACTOR) / item_width;
+	ffactor = (BLCKSZ * HashGetFillFactor(rel) / 100) / item_width;
 	/* keep to a sane range */
 	if (ffactor < 10)
 		ffactor = 10;
diff --git a/src/backend/access/hash/hashutil.c b/src/backend/access/hash/hashutil.c
index c5005f4..669dccc 100644
--- a/src/backend/access/hash/hashutil.c
+++ b/src/backend/access/hash/hashutil.c
@@ -289,7 +289,14 @@ _hash_checkpage(Relation rel, Buffer buf, int flags)
 bytea *
 hashoptions(Datum reloptions, bool validate)
 {
-	return default_reloptions(reloptions, validate, RELOPT_KIND_HASH);
+	static const relopt_parse_elt tab[] = {
+		{"fillfactor", RELOPT_TYPE_INT, offsetof(HashOptions, fillfactor)},
+	};
+
+	return (bytea *) build_reloptions(reloptions, validate,
+	  RELOPT_KIND_HASH,
+	  sizeof(HashOptions),
+	  tab, lengthof(tab));
 }
 
 /*
diff --git a/src/backend/access/nbtree/nbtree.c b/src/backend/access/nbtree/nbtree.c
index 4cfd528..8352882 100644
--- a/src/backend/access/nbtree/nbtree.c
+++ b/src/backend/access/nbtree/nbtree.c
@@ -816,7 +816,7 @@ _bt_vacuum_needs_cleanup(IndexVacuumInfo *info)
 	}
 	else
 	{
-		StdRdOptions *relopts;
+		BTOptions *relopts;
 		float8		cleanup_scale_factor;
 		float8		prev_num_heap_tuples;
 
@@ -827,7 +827,7 @@ _bt_vacuum_needs_cleanup(IndexVacuumInfo *info)
 		 * tuples exceeds vacuum_cleanup_index_scale_factor fraction of
 		 * original tuples count.
 		 */
-		relopts = (StdRdOptions *) info->index->rd_options;
+		relopts = (BTOptions *) info->index->rd_options;
 		cleanup_scale_factor = (relopts &&
 relopts->vacuum_cleanup_index_scale_factor >= 0)
 			? relopts->vacuum_cleanup_index_scale_factor
diff --git a/src/backend/access/nbtree/nbtsort.c b/src/backend/access/nbtree/nbtsort.c
index c11a3fb..9906c80 100644
--- a/src/backend/access/nbtree/nbtsort.c
+++ b/src/backend/access/nbtree/nbtsort.c
@@ -716,8 +716,9 @@ _bt_pagestate(BTWriteState *wstate, uint32 level)
 	if (level > 0)
 		state->btps_full = (BLCKSZ * (100 - BTREE_NONLEAF_FILLFACTOR) / 100);
 	else
-		state->btps_full = RelationGetTargetPageFreeSpace(wstate->index,
-		  BTREE_DEFAULT_FILLFACTOR);
+		state->btps_full = (BLCKSZ * (100 - BTGetFillFactor(wstate->index))
+			 / 100);
+
 	/* no parent level, yet */
 	state->btps_next = NULL;
 
diff --git a/src/backend/access/nbtree/nbtsplitloc.c b/src/backend/access/nbtree/nbtsplitloc.c
index a04d4e2..29167f1 100644
--- a/src/backend/access/nbtree/nbtsplitloc.c
+++ b/src/backend/access/nbtree/nbtsplitloc.c
@@ -167,7 +167,7 @@ _bt_findsplitloc(Relation rel,
 
 	/* Count up total space in data items before actually scanning 'em */
 	olddataitemstotal = rightspace - (int) PageGetExactFreeSpace(page);
-	leaffillfactor = RelationGetFillFactor(rel, 

Re: [PATCH] use separate PartitionedRelOptions structure to store partitioned table options

2019-11-13 Thread Nikolay Shaplov
В письме от среда, 13 ноября 2019 г. 16:30:29 MSK пользователь Michael Paquier 
написал:
> On Tue, Nov 12, 2019 at 01:50:03PM +0900, Michael Paquier wrote:
> > We have been through great length to have build_reloptions, so
> > wouldn't it be better to also have this code path do so?  Sure you
> > need to pass NULL for the parsing table..  But there is a point to
> > reduce the code paths using directly parseRelOptions() and the
> > follow-up, expected calls to allocate and to fill in the set of
> > reloptions.
> 
> So I have been looking at this one, and finished with the attached.
> It looks much better to use build_reloptions() IMO, taking advantage
> of the same sanity checks present for the other relkinds.
Thanks!

I did not read that thread yet, when I sent v3 patch.
build_reloptions is a good stuff and we should use it for sure.

I've looked at yours v4 version of the patch, it is exactly what we need here. 
Can we commit it as it is?


-- 
Software Developer: https://www.upwork.com/freelancers/~014a87e140ff02c0da
Body-oriented Therapist: https://vk.com/nataraj_rebalancing  (Russian)




Re: [PATCH] Do not use StdRdOptions in Access Methods

2019-11-14 Thread Nikolay Shaplov
В письме от четверг, 14 ноября 2019 г. 16:50:18 MSK пользователь Michael 
Paquier написал:

> > I've changed the patch to use build_reloptions function and again propose
> > it to the commitfest.
> 
> Thanks for the new patch.  I have not reviewed the patch in details,
> but I have a small comment.
> 
> > +#define SpGistGetFillFactor(relation) \
> > +   ((relation)->rd_options ? \
> > +   ((SpGistOptions *) (relation)->rd_options)->fillfactor : \
> > +   SPGIST_DEFAULT_FILLFACTOR)
> > +
> 
> Wouldn't it make sense to add assertions here to make sure that the
> relkind is an index?  You basically did that in commit 3967737.

For me there is no mush sense in it, as it does not prevent us from wrong type 
casting. Indexes can use all kinds of structures for reloptions, and checking 
that this is index, will not do much.

Do you know way how to distinguish one index from another? If we can check in 
assertion this is index, and this index is spgist, then assertion will make 
sense for 100%. I just have no idea how to do it. As far as I can see it is 
not possible now.


Another issue here is, that we should to it to all indexes, not only that have 
been using StdRdOptions, but to all indexes we have. (Damn code 
inconsistency). So I guess this should go as another patch to keep it step by 
step improvements.



-- 
Software Developer: https://www.upwork.com/freelancers/~014a87e140ff02c0da
Body-oriented Therapist: https://vk.com/nataraj_rebalancing  (Russian)




Re: [PATCH] Do not use StdRdOptions in Access Methods

2019-11-21 Thread Nikolay Shaplov
В письме от среда, 20 ноября 2019 г. 16:44:18 MSK пользователь Michael Paquier 
написал:

> > It seems to me that if the plan is to have one option structure for
> > each index AM, which has actually the advantage to reduce the bloat of
> > each relcache entry currently relying on StdRdOptions, then we could
> > have those extra assertion checks in the same patch, because the new
> > macros are introduced.
> I have looked at this patch, and did not like much having the
> calculations of the page free space around, so I have moved that into
> each AM's dedicated header.
Sounds as a good idea. I try not touch such things following the rule "is not 
broken do not fix" but this way it is definitely better. Thanks!

> > There is rd_rel->relam.  You can for example refer to pgstatindex.c
> > which has AM-related checks to make sure that the correct index AM is
> > being used.
> 
> We can do something similar for GIN and BRIN on top of the rest, so
> updated the patch with that.
That is what I've been trying to tell speaking about code consistency. But ok, 
this way is also good.

> Nikolay, I would be fine to commit this patch as-is.
Yeah. I've read the patch. I like it, actually I started doing same thing 
myself but you were faster. I have opportunity to pay attention to postgres 
once a week these days...

I like the patch, and also agree that it should be commited as is.

Though I have a notion to think about.

BRIN_AM_OID and friends are defined in catalog/pg_am_d.h so for core indexes 
we can do relation->rd_rel->relam == BRIN_AM_OID check. But for contrib 
indexes we can't do such a thing.
Bloom index does not need such check as it uses options only when index is 
created. At that point you can not choose wrong relation. But if in future we 
will have some contrib index that uses options when it some data is inserted 
(as it is done with fillfactor in core indexes) then index author will not be 
able to do such relam check. I would not call it a big problem, but  it is 
something to think about, for sure...

> Thanks for your patience on this stuff.
Thaks for joining this work, and sorry for late replies. Now I quite rarely 
have time for postgres :-(


-- 
Software Developer: https://www.upwork.com/freelancers/~014a87e140ff02c0da
Body-oriented Therapist: https://vk.com/nataraj_rebalancing  (Russian)




[PATCH] Finally split StdRdOptions into HeapOptions and ToastOptions

2019-12-06 Thread Nikolay Shaplov
In the thread 
https://www.postgresql.org/message-id/2620882.s52SJui4ql@x200m
I've suggested to split one big StdRdOption that is used for options storage 
into into Options structures individual for each relkind and each relam

That patch have been split into smaller parts, most of them were already 
commit:
https://commitfest.postgresql.org/25/2294/ - Remove StdRdOptions from AM
https://commitfest.postgresql.org/25/2297/ - Do not use StdRdOption for 
partitioned tables
https://commitfest.postgresql.org/25/2295/ - Some useful Asserts for view-
related macroses.

And here goes the last part of StrRdOptions removal patch, where StdRdOptions 
is replaced with HeapOptions and ToastOptions.

What did I do here.

- Added HeapOptions and ToastOptions structues
- Moved options building tab for autovacuum into AUTOVACUUM_RELOPTIONS macro, 
so it can be used in relopt_parse_elt tab both for heap and toast
- Changed everywhere in the code, where old heap_reloptions is used, to use 
new heap_reloptions or toast_reloptions
- Changed heap & toast option fetching macros to use HeapOptions and 
ToastOptions
- Added Asserts to heap and toast options macros. Now we finally can do it.

What I did not do

- I've split fillfactor related macros into heap and toast like 
RelationGetFillFactor will become HeapGetFillFactor and ToastGetFillFactor. I 
have to do it, because now they handle different structure.
but there are heap only option macros like RelationGetParallelWorkers that 
should be better called HeapGetParallelWorkers, as it is heap related. But I 
did not change the name, as somebody from core team (I think it was Alvaro, it 
was a while ago) asked me not to change macros names unless in is inavoidable. 
So I kept the names, though I still think that naming them with Heap prefix 
will make code more clear.

- vacuum_index_cleanup and vacuum_truncate options were added recently. They 
were added into StdRdOptions. I think their place is inside AutoVacOpts not in 
StdRdOptions, but did not dare to change it. If you see it the same way as I 
see, please let me know, I will move it to a proper place.

-- 
Software Developer: https://www.upwork.com/freelancers/~014a87e140ff02c0da
Body-oriented Therapist: https://vk.com/nataraj_rebalancing  (Russian)diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c
index 48377ac..8b18381 100644
--- a/src/backend/access/common/reloptions.c
+++ b/src/backend/access/common/reloptions.c
@@ -46,9 +46,8 @@
  * upper and lower bounds (if applicable); for strings, consider a validation
  * routine.
  * (ii) add a record below (or use add__reloption).
- * (iii) add it to the appropriate options struct (perhaps StdRdOptions)
- * (iv) add it to the appropriate handling routine (perhaps
- * default_reloptions)
+ * (iii) add it to the appropriate options struct
+ * (iv) add it to the appropriate handling routine
  * (v) make sure the lock level is set correctly for that operation
  * (vi) don't forget to document the option
  *
@@ -1106,9 +1105,11 @@ extractRelOptions(HeapTuple tuple, TupleDesc tupdesc,
 	switch (classForm->relkind)
 	{
 		case RELKIND_RELATION:
-		case RELKIND_TOASTVALUE:
 		case RELKIND_MATVIEW:
-			options = heap_reloptions(classForm->relkind, datum, false);
+			options = heap_reloptions(datum, false);
+			break;
+		case RELKIND_TOASTVALUE:
+			options = toast_reloptions(datum, false);
 			break;
 		case RELKIND_PARTITIONED_TABLE:
 			options = partitioned_table_reloptions(datum, false);
@@ -1480,55 +1481,62 @@ fillRelOptions(void *rdopts, Size basesize,
 
 
 /*
- * Option parser for anything that uses StdRdOptions.
+ * Option parsing definition for autovacuum. Used in toast and heap options.
+ */
+
+#define AUTOVACUUM_RELOPTIONS(OFFSET)\
+		{"autovacuum_enabled", RELOPT_TYPE_BOOL, \
+		OFFSET + offsetof(AutoVacOpts, enabled)},\
+		{"autovacuum_vacuum_threshold", RELOPT_TYPE_INT, \
+		OFFSET + offsetof(AutoVacOpts, vacuum_threshold)},   \
+		{"autovacuum_analyze_threshold", RELOPT_TYPE_INT,\
+		OFFSET + offsetof(AutoVacOpts, analyze_threshold)},  \
+		{"autovacuum_vacuum_cost_delay", RELOPT_TYPE_REAL,   \
+		OFFSET + offsetof(AutoVacOpts, vacuum_cost_delay)},  \
+		{"autovacuum_vacuum_cost_limit", RELOPT_TYPE_INT,\
+		OFFSET + offsetof(AutoVacOpts, vacuum_cost_limit)},  \
+		{"autovacuum_freeze_min_age", RELOPT_TYPE_INT,   \
+		OFFSET + offsetof(AutoVacOpts, freeze_min_age)}, \
+		{"autovacuum_freeze_max_age", RELOPT_TYPE_INT,   \
+		OFFSET + offsetof(AutoVacOpts, freeze_max_age)}, \
+		{"autovacuum_freeze_table_age", RELOPT_TYPE_INT, \
+		OFFSET + offsetof(AutoVacOpts, freeze_table_age)},   \
+		{"autovacuum_multixact_freeze_min_age", RELOPT_TYPE_INT, \
+		OFFSET + offsetof(AutoVacOpts, multixact_freeze_min_age)},   \
+		{

Re: [PATCH] src/test/modules/dummy_index -- way to test reloptions from inside of access method

2019-04-03 Thread Nikolay Shaplov
 shows a subset of values? 
I am afraid that we will get a mess that will work well, but it would be 
difficult for a human to find any logic in the output. And sooner or later we 
will need it, when something will go wrong and somebody will try to find out 
why.
So it is better to test one option at a time, and that's why mute test output 
for other options.

> Please note that these
> are visible directly via pg_class.reloptions.  So we could shave quite
> some code.
Values from pg_class are well tested in regression test. My point here is to 
check that they reach index internal as expected. And there is a long way 
between pg_class.reloptions and index internals.

> Please note that the compilation of the module fails.
> nodes/relation.h maybe is access/relation.h?  You may want to review
> all that.
Hm... I do not quite understand how it get there and why in worked for me 
before. But I changed it to nodes/pathnodes.h It was here because it is needed 
for PlannerInfo symbol. 

PS. Sorry for long delays. I do not always have much time to do postgres...
diff --git a/.gitignore b/.gitignore
index 794e35b..37331c2 100644
diff --git a/src/test/modules/Makefile b/src/test/modules/Makefile
index dfd0956..742078e 100644
--- a/src/test/modules/Makefile
+++ b/src/test/modules/Makefile
@@ -7,6 +7,7 @@ include $(top_builddir)/src/Makefile.global
 SUBDIRS = \
 		  brin \
 		  commit_ts \
+		  dummy_index_am \
 		  dummy_seclabel \
 		  snapshot_too_old \
 		  test_bloomfilter \
diff --git a/src/test/modules/dummy_index_am/.gitignore b/src/test/modules/dummy_index_am/.gitignore
new file mode 100644
index 000..5dcb3ff
--- /dev/null
+++ b/src/test/modules/dummy_index_am/.gitignore
@@ -0,0 +1,4 @@
+# Generated subdirectories
+/log/
+/results/
+/tmp_check/
diff --git a/src/test/modules/dummy_index_am/Makefile b/src/test/modules/dummy_index_am/Makefile
new file mode 100644
index 000..695941b
--- /dev/null
+++ b/src/test/modules/dummy_index_am/Makefile
@@ -0,0 +1,21 @@
+# contrib/bloom/Makefile
+
+MODULE_big = dummy_index_am
+OBJS = dummy_index.o direloptions.o $(WIN32RES)
+
+EXTENSION = dummy_index_am
+DATA = dummy_index_am--1.0.sql
+PGFILEDESC = "dummy index access method - needed for all kinds of tests"
+
+REGRESS = reloptions
+
+ifdef USE_PGXS
+PG_CONFIG = pg_config
+PGXS := $(shell $(PG_CONFIG) --pgxs)
+include $(PGXS)
+else
+subdir = src/test/modules/dummy_index_am
+top_builddir = ../../../..
+include $(top_builddir)/src/Makefile.global
+include $(top_srcdir)/contrib/contrib-global.mk
+endif
diff --git a/src/test/modules/dummy_index_am/README b/src/test/modules/dummy_index_am/README
new file mode 100644
index 000..61f80d3
--- /dev/null
+++ b/src/test/modules/dummy_index_am/README
@@ -0,0 +1,45 @@
+Dummy index AM
+==
+
+Dummy index, an index module for testing am-related internal calls that can't be
+properly tested inside production indexes, but better to be tested inside actual
+access method module.
+
+Guidelines:
+1. Keep this index as simple as as possible. It should not do any real indexing
+(unless you need it for your tests), if you need it make it as simple as
+possible;
+2. Keep all code related to feature you test inside id[name_of_a_feature].c
+file. dummy_index.c file should contain code that is needed for everyone, and
+make calls to feature-related code;
+3. Code related to your feature tests should be enabled and disabled by GUC
+variables. Create as many boolean GUC variables as you need and set them on so
+your test will know when it is time to do test output. Thus output from
+different features tests are not interfered;
+4. Add section to this README file that describes the general idea of what your
+tests do.
+
+Reloptions tests
+
+
+Some relotions testing are done in regression tests. There we can check if new
+option value properly reaches pg_class, minimum/maximum checks, etc. But we
+can't check if option value successfully reached index internal code when we are
+dealing with production indexes. But  we can do it here in Dummy index.
+Here we check that values of reloptions properly reaches am-internals, and that
+all reloption-related code works as expected. Several GUC variables are defined
+to control test's output. do_test_reloptions turns on and off any
+reloptions-related output. You will also get some test output in the case when
+no relation options is set at all. do_test_reloption_int,
+do_test_reloption_real, do_test_reloption_bool and do_test_reloption_string
+allows to enable test output for int, real, boolean and string options.
+do_test_reloption_string2 enables test output for another string option. We need
+second string option, because a) string reloption implementation is a bit
+tricky, and it is better to check that second value works as well; b) better to
+check both cases: string option with validation function and without one, so we
+need two string 

Re: Ltree syntax improvement

2019-04-06 Thread Nikolay Shaplov
В письме от воскресенье, 24 февраля 2019 г. 14:31:55 MSK пользователь Dmitry 
Belyavsky написал:

Hi! Am back here again.

I've been thinking about this patch a while... Come to some conclusions and 
wrote some examples...

First I came to idea that the best way to simplify the code is change the 
state machine from if to switch/case. Because in your code a lot of repetition 
is done just because you can't say "Thats all, let's go to next symbol" in any 
place in the code. Now it should follow all the branches of if-else tree that 
is inside the state-machine "node" to get to the next symbol.

To show how simpler the things would be I changed the state machine processing 
in lquery_in form if to switch/case, and changed the code for LQPRS_WAITLEVEL 
state processing, removing duplicate code, using "break" wherever it is 
possible

(The indention in this example is unproper to make diff more clear)

so from that much of code
=
if (state == LQPRS_WAITLEVEL)
{
if (t_isspace(ptr))
{
ptr += charlen;
pos++;
continue;
}

escaped_count = 0;
real_levels++;
if (charlen == 1)
{
if (t_iseq(ptr, '!'))
{
GETVAR(curqlevel) = lptr = (nodeitem *) 
palloc0(sizeof(nodeitem) * numOR);
lptr->start = ptr + 1;
state = LQPRS_WAITDELIM;
curqlevel->numvar = 1;
curqlevel->flag |= LQL_NOT;
hasnot = true;
}
else if (t_iseq(ptr, '*'))
state = LQPRS_WAITOPEN;
else if (t_iseq(ptr, '\\'))
{
GETVAR(curqlevel) = lptr = (nodeitem *) 
palloc0(sizeof(nodeitem) * numOR);
lptr->start = ptr;
curqlevel->numvar = 1;
state = LQPRS_WAITESCAPED;
}
else if (strchr(".|@%{}", *ptr))
{
UNCHAR;
}
else
{
GETVAR(curqlevel) = lptr = (nodeitem *) 
palloc0(sizeof(nodeitem) * numOR);
lptr->start = ptr;
state = LQPRS_WAITDELIM;
curqlevel->numvar = 1;
if (t_iseq(ptr, '"'))
{
lptr->flag |= LVAR_QUOTEDPART;
}
}
}
else
{
GETVAR(curqlevel) = lptr = (nodeitem *) 
palloc0(sizeof(nodeitem) * 
numOR);
lptr->start = ptr;
state = LQPRS_WAITDELIM;
curqlevel->numvar = 1;
}
}
=
I came to this
=
 case LQPRS_WAITLEVEL:
if (t_isspace(ptr))
break; /* Just go to next symbol */
escaped_count = 0;
real_levels++;

if (charlen == 1)
{
if (strchr(".|@%{}", *ptr))
UNCHAR;
if (t_iseq(ptr, '*'))
{
state = LQPRS_WAITOPEN;
break;
}
}
GETVAR(curqlevel) = lptr = (nodeitem *) 
palloc0(sizeof(nodeitem) * 
numOR);
lptr->start = ptr;
curqlevel->numvar = 1;
state = LQPRS_WAITDELIM;
if (charlen == 1)
{
if (t_iseq(ptr, '\\'))
{
state = LQPRS_WAITESCAPED;
break;
}
   

Re: pageinspect: add tuple_data_record()

2018-10-17 Thread Nikolay Shaplov
В письме от 16 октября 2018 19:17:20 пользователь Andres Freund написал:
> Hi,
> 
> On 2018-10-16 22:05:28 -0400, James Coleman wrote:
> > > I don't think it's entirely safe to do so for invisible rows.  The toast
> > > references could be reused, constraints be violated, etc.  So while I
> > > could have used this several times before, it's also very likely a good
> > > way to cause trouble.  It'd probably be ok to just fetch the binary
> > > value of the columns, but detoasting sure ain't ok.

> > Wouldn’t that be equally true for the already existing toast option to
> > tuple_data_split()?

> Yes. Whoever added that didn't think far enough.  Teodor, Nikolay?

I did compleatly got the question... The question is it safe to split tuple 
record into array of raw bytea? It is quite safe from my point of view.  We 
use only data that is inside the tuple, and info from pg_catalog that 
describes the tuple structure. So we are not affected if for example toast 
table were cleaned by vacuum. If you try to deTOAST data when TOAST table were 
already overwritten by new data, you can get some trouble...

> > Is “unsafe” here something that would lead to a crash? Or just returning
> > invalid data?

I think that you should try and see. Find a way to make postgres vacuum toast 
table, and overwrite it with some new data, but keep tuple in heap page 
untouched. Then try to deTOAST old data and see what happened. (Hint: it is 
good to turn off compression for your data to be TOASTed, so you can just look 
into toast-file in binary mode and get an idea what in it now)


==
>> Summary:
>> The new function tuple_data_record() parallels the existing
>> tuple_data_split() function, but instead of returning a bytea array of raw
>> attribute heap values, it returns a row type of the relation being
>> examined.

I find this approach a bit wrong. pageinspect is about viewing data in raw 
mode, not about looking at the tuples that were deleted. It can be used for 
this task, but it has other main purpose.

I would suggest instead of automatically detoast and uncompress actual data, I 
would add functions that: 

1. Checks if TOAST id is valid, and data can be fetched
2. Fetches that data and print it in raw mode
3. Says if binary data is compressed varlen data
4. Uncompress binary data and return it as another binary data
5. Convert binary data into string.

or something like that. This would be more according to the pageinspect 
spirit, as I see it.

Than using these functions you can write pure sql wrapper that do what you 
really want.

-- 
Do code for fun.

signature.asc
Description: This is a digitally signed message part.


Re: pageinspect: add tuple_data_record()

2018-10-17 Thread Nikolay Shaplov
В письме от 17 октября 2018 12:36:54 пользователь James Coleman написал:
> > I did compleatly got the question... The question is it safe to split
> > tuple
> > record into array of raw bytea? It is quite safe from my point of view.
> > We
> > use only data that is inside the tuple, and info from pg_catalog that
> > describes the tuple structure. So we are not affected if for example toast
> > table were cleaned by vacuum. If you try to deTOAST data when TOAST table
> > were
> > already overwritten by new data, you can get some trouble...

> The existing tuple_data_split() method already explicitly allows deTOASTing
> data,
> so if this is a problem, the problem already exists in pageinspect.

Oh. that's true... I do not remember writing it, but it seems I did it. After 
Andreas notion, I am sure this should be fixed by removing de_toast option for 
tuple_data_split... O_o


-- 
Do code for fun.

signature.asc
Description: This is a digitally signed message part.


Re: [PATCH][PROPOSAL] Add enum releation option type

2018-10-31 Thread Nikolay Shaplov
В письме от 12 сентября 2018 21:40:49 пользователь Nikolay Shaplov написал:
> > As you mentioned in previous mail, you prefer to keep enum and
> > relopt_enum_element_definition array in the same .h file. I'm not sure,
> > but I think it is done to keep everything related to enum in one place
> > to avoid inconsistency in case of changes in some part (e.g. change of
> > enum without change of array). On the other hand, array content created
> > without array creation itself in .h file. Can we move actual array
> > creation into same .h file? What is the point to separate array content
> > definition and array definition?
> 
> Hm... This would be good. We really can do it? ;-) I am not C-expert, some
> aspects of C-development is still mysterious for me. So if it is really ok
> to create array in .h file, I would be happy to move it there  (This patch
> does not include this change, I still want to be sure we can do it)
I've discussed this issue with a colleague, who IS C-expert, and his advice 
was not to include this static const into .h file. Because copy of this const 
would be created in all objective files where this .h were included. And it is 
not the best way... 

-- 
Do code for fun.

signature.asc
Description: This is a digitally signed message part.


Re: [PATCH][PROPOSAL] Add enum releation option type

2018-11-01 Thread Nikolay Shaplov
В письме от 1 ноября 2018 11:10:14 пользователь Tom Lane написал:

> >>> I see you lost the Oxford comma:
> >>> 
> >>> -DETAIL:  Valid values are "on", "off", and "auto".
> >>> +DETAIL:  Valid values are "auto", "on" and "off".
> >>> 
> >>> Please put these back.
> >> 
> >> Actually that's me who have lost it. The code with  oxford comma would be
> >> a
> >> bit more complicated. We should put such coma when we have 3+ items and
> >> do not put it when we have 2.
> >> 
> >> Does it worth it?
> > 
> > In my opinion, it is worth it.
> 
> Uh ... I've not been paying attention to this thread, but this exchange
> seems to be about somebody constructing a message like that piece-by-piece
> in code.  This has got to be a complete failure from the translatability
> standpoint.  See
> 
> https://www.postgresql.org/docs/devel/static/nls-programmer.html#NLS-GUIDELI
> NES

It's a very good reason...

In this case the only solution I can see is 

DETAIL:  Valid values are: "value1", "value2", "value3".

Where list '"value1", "value2", "value3"' is built in runtime but have no any 
bindnings to any specific language. And the rest of the message is
'DETAIL:  Valid values are: %s' which can be properly translated.


-- 
Do code for fun.

signature.asc
Description: This is a digitally signed message part.


Re: [PATCH][PROPOSAL] Add enum releation option type

2018-11-02 Thread Nikolay Shaplov
В письме от 1 ноября 2018 18:26:20 пользователь Nikolay Shaplov написал:

> In this case the only solution I can see is
>
> DETAIL:  Valid values are: "value1", "value2", "value3".
>
> Where list '"value1", "value2", "value3"' is built in runtime but have no
> any bindnings to any specific language. And the rest of the message is
> 'DETAIL:  Valid values are: %s' which can be properly translated.

I've fiex the patch. Now it does not add "and" at all.

--
Do code for fun.diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c
index db84da0..b266c86 100644
--- a/src/backend/access/common/reloptions.c
+++ b/src/backend/access/common/reloptions.c
@@ -422,7 +422,11 @@ static relopt_real realRelOpts[]  	{{NULL}}
 };

-static relopt_string stringRelOpts[] +static relopt_enum_element_definition gist_buffering_enum_def[] +		GIST_OPTION_BUFFERING_ENUM_DEF;
+static relopt_enum_element_definition view_check_option_enum_def[] +		VIEW_OPTION_CHECK_OPTION_ENUM_DEF;
+static relopt_enum enumRelOpts[]  {
 	{
 		{
@@ -431,10 +435,8 @@ static relopt_string stringRelOpts[]  			RELOPT_KIND_GIST,
 			AccessExclusiveLock
 		},
-		4,
-		false,
-		gistValidateBufferingOption,
-		"auto"
+		gist_buffering_enum_def,
+		GIST_OPTION_BUFFERING_AUTO
 	},
 	{
 		{
@@ -443,11 +445,14 @@ static relopt_string stringRelOpts[]  			RELOPT_KIND_VIEW,
 			AccessExclusiveLock
 		},
-		0,
-		true,
-		validateWithCheckOption,
-		NULL
+		view_check_option_enum_def,
+		VIEW_OPTION_CHECK_OPTION_NOT_SET
 	},
+	{{NULL}}
+};
+
+static relopt_string stringRelOpts[] +{
 	/* list terminator */
 	{{NULL}}
 };
@@ -494,6 +499,12 @@ initialize_reloptions(void)
    realRelOpts[i].gen.lockmode));
 		j++;
 	}
+	for (i = 0; enumRelOpts[i].gen.name; i++)
+	{
+		Assert(DoLockModesConflict(enumRelOpts[i].gen.lockmode,
+   enumRelOpts[i].gen.lockmode));
+		j++;
+	}
 	for (i = 0; stringRelOpts[i].gen.name; i++)
 	{
 		Assert(DoLockModesConflict(stringRelOpts[i].gen.lockmode,
@@ -532,6 +543,14 @@ initialize_reloptions(void)
 		j++;
 	}

+	for (i = 0; enumRelOpts[i].gen.name; i++)
+	{
+		relOpts[j] = &enumRelOpts[i].gen;
+		relOpts[j]->type = RELOPT_TYPE_ENUM;
+		relOpts[j]->namelen = strlen(relOpts[j]->name);
+		j++;
+	}
+
 	for (i = 0; stringRelOpts[i].gen.name; i++)
 	{
 		relOpts[j] = &stringRelOpts[i].gen;
@@ -629,6 +648,9 @@ allocate_reloption(bits32 kinds, int type, const char *name, const char *desc)
 		case RELOPT_TYPE_REAL:
 			size = sizeof(relopt_real);
 			break;
+		case RELOPT_TYPE_ENUM:
+			size = sizeof(relopt_enum);
+			break;
 		case RELOPT_TYPE_STRING:
 			size = sizeof(relopt_string);
 			break;
@@ -708,6 +730,24 @@ add_real_reloption(bits32 kinds, const char *name, const char *desc, double defa
 }

 /*
+ * add_enuum_reloption
+ *		Add a new enum reloption
+ */
+void
+add_enum_reloption(bits32 kinds, const char *name, const char *desc,
+	 relopt_enum_element_definition *enum_def, int default_val)
+{
+	relopt_enum *newoption;
+
+	newoption = (relopt_enum *) allocate_reloption(kinds, RELOPT_TYPE_ENUM,
+   name, desc);
+	newoption->enum_def = enum_def;
+	newoption->default_val = default_val;
+
+	add_reloption((relopt_gen *) newoption);
+}
+
+/*
  * add_string_reloption
  *		Add a new string reloption
  *
@@ -1208,6 +1248,51 @@ parse_one_reloption(relopt_value *option, char *text_str, int text_len,
 	   optreal->min, optreal->max)));
 			}
 			break;
+		case RELOPT_TYPE_ENUM:
+			{
+relopt_enum *optenum = (relopt_enum *) option->gen;
+relopt_enum_element_definition *el_def;
+
+parsed = false;
+for(el_def = optenum->enum_def; el_def->text_value; el_def++)
+{
+	if (pg_strcasecmp(value, el_def->text_value) == 0)
+	{
+		option->values.enum_val = el_def->numeric_value;
+		parsed = true;
+		break;
+	}
+}
+if (!parsed)
+{
+	/*
+	 * If value is not among allowed enum text values, but we
+	 * are not up to validating, just use default numeric value,
+	 * otherwise we raise an error
+	 */
+	if (!validate)
+		option->values.enum_val = optenum->default_val;
+	else
+	{
+		StringInfoData buf;
+		initStringInfo(&buf);
+		for(el_def = optenum->enum_def; el_def->text_value;
+	 el_def++)
+		{
+			appendStringInfo(&buf,"\"%s\"",el_def->text_value);
+			if (el_def[1].text_value)
+appendStringInfo(&buf,", ");
+		}
+		ereport(ERROR,
+(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("invalid value for \"%s\" option",
+		option->gen->name),
+ errdetail("Valid values are: %s.", buf.data)));
+		pfree(buf.data);
+	}
+}
+			}
+			break;
 	

Re: [PATCH] Opclass parameters

2018-11-16 Thread Nikolay Shaplov
В письме от 15 ноября 2018 18:26:43 пользователь Nikita Glukhov написал:

> >> But since it is now "Rejected with feedback", let's wait till autumn.
> > 
> > We don't want to wait that long.  But now we only need to сome to an
> > agreement
> > about CREATE INDEX syntax and where to store the opclass parameters.
> 
> Attached 2nd version of the patches. Nothing has changed since March,
> this is just a rebased version.
> 
> CREATE INDEX syntax and parameters storage method still need discussion.

Hi! I'd like to review your patch if you do  not mind. Since I am familiar 
with the subject. I'll add it to the TOP 3 of my IT TODO list :-)

But even without carefully reading the code I have several important 
questions:

1. I am sure that this patch should contain code for opclass praram generic 
implementation, and _one_ example of how it is used for certain opclass.
From my point of view, we should not add all hardcoded constant as opclass 
params just because we can. It should be done only when it is really needed. 
And each case needs special consideration. This is not only about code 
complexity, this worries me less, but also about documentation complexity. 
Once option is added, it should be documented. This will make documentation 
more hard to understand (and completely unexperienced users reads 
documentation too). If this option is needed, this is price we all pay. But if 
nobody really use it, I see no reason to make things more complex for 
everyone.

2. The second question, is why you create new column in one of the table of 
pg_catalog, when we have attopitions in attribute description. And each 
indexed column in index is technically a relation attribute. Options of index 
column should be stored there, from my point of view (yes I know it is a 
hassle to pass it there, but I did in in my preview, it can be done)
2.1. I did not read the code, I'll do it some time late, but the main question 
I have is, how you will manage case, when you set different values for same 
options of different columns. like:

CREATE INDEX ON arrays USING gist (
   arr1 gist__intbig_ops (siglen = 32),
   arr2 gist__intbig_ops (siglen = 64)
);

It is easitly solved when you store them in attoptions. But my question how do 
you manage it... (I'll get the answer from the code soon, I hope)




-- 
Do code for fun.

signature.asc
Description: This is a digitally signed message part.


Re: [PATCH] get rid of StdRdOptions, use individual binary reloptions representation for each relation kind instead

2018-11-19 Thread Nikolay Shaplov
В письме от 2 октября 2018 13:46:13 пользователь Michael Paquier написал:
> On Fri, Sep 14, 2018 at 09:30:25PM +0300, Nikolay Shaplov wrote:
> > BTW this commit shows why do this patch is important: 857f9c36 adds new
> > option for b-tree indexes. But thanks to the StdRdOptions this option
> > will exist for no practical use in all heaps that has just any option set
> > to non-default value, and in indexes that use StdRdOptions (and also has
> > any option set) And there will be more. StdRdOptions is long outdated
> > solution and it needs to be replaced.
>
> This patch does not apply anymore, so this is moved to next CF, waiting
> for author.
Oup...It seems to me that I've fogot to rebase it when it is needed...
Did it now



--
Do code for fun.diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c
index db84da0..e7e2392 100644
--- a/src/backend/access/common/reloptions.c
+++ b/src/backend/access/common/reloptions.c
@@ -22,7 +22,7 @@
 #include "access/htup_details.h"
 #include "access/nbtree.h"
 #include "access/reloptions.h"
-#include "access/spgist.h"
+#include "access/spgist_private.h"
 #include "access/tuptoaster.h"
 #include "catalog/pg_type.h"
 #include "commands/defrem.h"
@@ -46,9 +46,8 @@
  * upper and lower bounds (if applicable); for strings, consider a validation
  * routine.
  * (ii) add a record below (or use add__reloption).
- * (iii) add it to the appropriate options struct (perhaps StdRdOptions)
- * (iv) add it to the appropriate handling routine (perhaps
- * default_reloptions)
+ * (iii) add it to the appropriate options struct
+ * (iv) add it to the appropriate handling routine
  * (v) make sure the lock level is set correctly for that operation
  * (vi) don't forget to document the option
  *
@@ -1004,7 +1003,7 @@ extractRelOptions(HeapTuple tuple, TupleDesc tupdesc,
 		case RELKIND_TOASTVALUE:
 		case RELKIND_MATVIEW:
 		case RELKIND_PARTITIONED_TABLE:
-			options = heap_reloptions(classForm->relkind, datum, false);
+			options = relation_reloptions(classForm->relkind, datum, false);
 			break;
 		case RELKIND_VIEW:
 			options = view_reloptions(datum, false);
@@ -1337,63 +1336,133 @@ fillRelOptions(void *rdopts, Size basesize,


 /*
- * Option parser for anything that uses StdRdOptions.
+ * Option parsing definition for autovacuum. Used in toast and heap options.
+ */
+
+#define AUTOVACUUM_RELOPTIONS(OFFSET)\
+		{"autovacuum_enabled", RELOPT_TYPE_BOOL, \
+		OFFSET + offsetof(AutoVacOpts, enabled)},\
+		{"autovacuum_vacuum_threshold", RELOPT_TYPE_INT, \
+		OFFSET + offsetof(AutoVacOpts, vacuum_threshold)},   \
+		{"autovacuum_analyze_threshold", RELOPT_TYPE_INT,\
+		OFFSET + offsetof(AutoVacOpts, analyze_threshold)},  \
+		{"autovacuum_vacuum_cost_delay", RELOPT_TYPE_INT,\
+		OFFSET + offsetof(AutoVacOpts, vacuum_cost_delay)},  \
+		{"autovacuum_vacuum_cost_limit", RELOPT_TYPE_INT,\
+		OFFSET + offsetof(AutoVacOpts, vacuum_cost_limit)},  \
+		{"autovacuum_freeze_min_age", RELOPT_TYPE_INT,   \
+		OFFSET + offsetof(AutoVacOpts, freeze_min_age)}, \
+		{"autovacuum_freeze_max_age", RELOPT_TYPE_INT,   \
+		OFFSET + offsetof(AutoVacOpts, freeze_max_age)}, \
+		{"autovacuum_freeze_table_age", RELOPT_TYPE_INT, \
+		OFFSET + offsetof(AutoVacOpts, freeze_table_age)},   \
+		{"autovacuum_multixact_freeze_min_age", RELOPT_TYPE_INT, \
+		OFFSET + offsetof(AutoVacOpts, multixact_freeze_min_age)},   \
+		{"autovacuum_multixact_freeze_max_age", RELOPT_TYPE_INT, \
+		OFFSET + offsetof(AutoVacOpts, multixact_freeze_max_age)},   \
+		{"autovacuum_multixact_freeze_table_age", RELOPT_TYPE_INT,   \
+		OFFSET + offsetof(AutoVacOpts, multixact_freeze_table_age)}, \
+		{"log_autovacuum_min_duration", RELOPT_TYPE_INT, \
+		OFFSET + offsetof(AutoVacOpts, log_min_duration)},   \
+		{"autovacuum_vacuum_scale_factor", RELOPT_TYPE_REAL, \
+		OFFSET + offsetof(AutoVacOpts, vacuum_scale_factor)},\
+		{"autovacuum_analyze_scale_factor", RELOPT_TYPE_REAL,\
+		OFFSET + offsetof(AutoVacOpts, analyze_scale_factor)}
+
+/*
+ * Option parser for heap
  */
 bytea *
-default_reloptions(Datum reloptions, bool validate, relopt_kind kind)
+heap_reloptions(Datum reloptions, bool validate)
 {
 	relopt_value *options;
-	StdRdOptions *rdopts;
+	HeapRelOptions *rdopts;
 	int			numoptions;
 	static const relopt_parse_elt tab[] = {
-		{"fillfactor", RELOPT_TYPE_INT, offsetof(StdRdOptions, fillfactor)},
-		{"autovacuum_enabled"

Re: [PATCH] Opclass parameters

2018-11-20 Thread Nikolay Shaplov
В письме от 15 ноября 2018 18:26:43 пользователь Nikita Glukhov написал:

> Attached 2nd version of the patches. Nothing has changed since March,
> this is just a rebased version.
> 
> CREATE INDEX syntax and parameters storage method still need discussion.
I've played around a bit with you patch and come to some conclusions, I'd like 
to share. They are almost same as those before, but now there are more 
details.

Again some issues about storing opclass options in pg_inedx:

1. Having both indoption and indoptions column in pg_index will make someone's 
brain explode for sure. If not, it will bring troubles when people start 
confusing them.

2. Now I found out how do you store option values for each opclass: text[] of 
indoptions in pg_index is not the same as text[] in 
reloptions in pg_catalog (and it brings more confusion). In reloption each 
member of the array is a single option. 

reloptions  | {fillfactor=90,autovacuum_enabled=false}

In indoptions, is a whole string of options for one of the indexed attributes, 
each array item has all options for one indexed attribute. And this string 
needs furthermore parsing, that differs from reloption parsing.

indoptions | {"{numranges=150}","{numranges=160}"}


This brings us to the following issues:

2a. pg_index stores properties of index in general. Properties of each indexed 
attributes is stored in pg_attribute table. If we follow this philosophy
it is wrong to add any kind of per-attribute array values into pg_index. These 
values should be added to pg_attribute one per each pg_attribute entry.

2b. Since you've chosen method of storage that differs from one that is used 
in reloptions, that will lead to two verstions of code that processes the 
attributes. And from now on, if we accept this, we should support both of them 
and keep them in sync. (I see that you tried to reuse as much code as 
possible, but still you added some more that duplicate current reloptions 
functionality.)

I know that relotions code is not really suitable for reusing. This was the 
reason why I started solving oplcass option task with rewriting reloptions 
code,to make it 100% reusable for any kind of options. So I would offer you 
again to join me as a reviewer of that code. This will make opclass code more 
simple and more sensible, if my option code is used... 

3. Speaking of sensible code

Datum
g_int_options(PG_FUNCTION_ARGS)
{
   Datum   raw_options = PG_GETARG_DATUM(0);
   boolvalidate = PG_GETARG_BOOL(1);
   relopt_int  siglen =
   { {"numranges", "number of ranges for compression", 0, 0, 9, 
RELOPT_TYPE_INT },
   G_INT_NUMRANGES_DEFAULT, 1, G_INT_NUMRANGES_MAX };
   relopt_gen *optgen[] = { &siglen.gen };
   int offsets[] = { offsetof(IntArrayOptions, num_ranges) };
   IntArrayOptions *options =
   parseAndFillLocalRelOptions(raw_options, optgen, offsets, 1,
   sizeof(IntArrayOptions), validate);

   PG_RETURN_POINTER(options);
}

It seems to be not a very nice hack.
What would you do if you would like to have both int, real and boolean options 
for one opclass? I do not know how to implement it using this code.
We have only int opclass options for now, but more will come and we should be 
ready for it.

4. Now getting back to not adding opclass options wherever we can, just 
because we can:

4a. For inrarray there were no opclass options tests added. I am sure there 
should be one, at least just to make sure it still does not segfault when you 
try to set one. And in some cases more tests can be needed. To add and review 
them one should be familiar with this opclass internals. So it is good when 
different people do it for different opclasses

4b. When you add opclass options instead of hardcoded values, it comes to 
setting minimum and maximum value. Why do you choose 1000 as maximum 
for num_ranges in gist_int_ops in intarray? Why 1 as minimum? All these 
decisions needs careful considerations and can't be done for bunch of 
opclasses just in one review. 

4c. Patch usually take a long path from prototype to final commit. Do you 
really want to update all these opclasses code each time when some changes 
in the main opclass option code is made? ;-)

So I would suggest to work only with intarray and add other opclasses later.

5. You've been asking about SQL grammar

> CREATE INDEX idx ON tab USING am (
>{expr {opclass | DEFAULT} ({name=value} [,...])} [,...]
> );

As for me I do not really care about it. For me all the solutions is 
acceptable. But looking at is i came to one notion:

I've never seen before DEFAULT keyword to be used in this way. There is logic 
in such usage, but I did not remember any practical usage case.
If there are such usages (I can easily missed it) or if it is somehow 
recommended in SQL standard -- let it be. But if none above, I would suggest 
to use WITH keyword instead. As it is already used for reloptions. As far as I 
remember in my prototype 

Re: Add extension options to control TAP and isolation tests

2018-11-20 Thread Nikolay Shaplov
В письме от 10 ноября 2018 09:14:19 пользователь Michael Paquier написал:

> > Nice cleanup. Also, I like the ability to enable/control more types of
> > tests easily from the Makefile. What are the next steps for this
> > patch?
> 
> Thanks.  It seems to me that a complete review is still in order,
> particularly regarding the new makefile option names.  And then, if
> everybody caring about the topic is happy with the way the patch is
> shaped, it can be carried over to being committed, which would be most
> likely something I'll do.

Is it ok, if I join the reviewing? I like test, especially TAP one, you know 
;-)
Since you are much more experienced in postgres then me, I'd try to understand 
how does the patch work, try to use if for writing more TAP test, and will 
report problems and thoughts I came across while doing that.

So far while first reading the patch I came to following two

1. 
--- a/src/test/modules/brin/.gitignore
+++ b/src/test/modules/brin/.gitignore
@@ -1,3 +1,3 @@
 # Generated subdirectories
-/isolation_output/
+/output_iso/
 /tmp_check/

For me name "output_iso" means nothing. iso is something about CD/DVD or about 
standards. I would not guess that iso stands for isolation if I did not know 
it already. isolation_output is more sensible: I have heard that there are 
some isolation tests, this must be something about it. May be it would be 
better to change it to isolation_output everywhere instead of changing to 
output_iso

2.

--- a/doc/src/sgml/extend.sgml
+++ b/doc/src/sgml/extend.sgml
@@ -1293,6 +1293,34 @@ include $(PGXS)
   
  
.
+ 
+  ISOLATION
+  
+   
+list of isolation test cases
+   
+  
+ 
+
+ 
+  ISOLATION_OPTS
+  
+   
+additional switches to pass to
+pg_isolation_regress
+   
+  
+ 
+
+ 
+  TAP_TESTS
+  
+   
+switch defining if TAP tests need to be run
+   
+  
+ 
+
  
   NO_INSTALLCHECK
   

I tried to find definition in documentation what does "isolation test" exactly 
means, but did not find. There is some general words about TAP tests in main 
postgres documentation 
https://www.postgresql.org/docs/11/regress-tap.html,
but I would not understand anything from it if I did not already know how it 
works.

In current extend-pgxs documentation there is some explanation about 
regression test, it sensible enough. Since TAP and isolation tests are 
introduced now, there should be same short explanation for both of them.

And also it would be good to add links from extend-pgxs to regress-tap and 
regress saying that for more info about these tests one can look at postgres 
doc, because they work in a similar way.

That's all so far. I'll look more into it later...

-- 
Do code for fun.

signature.asc
Description: This is a digitally signed message part.


Re: Add extension options to control TAP and isolation tests

2018-11-22 Thread Nikolay Shaplov
В письме от 21 ноября 2018 09:39:53 пользователь Michael Paquier написал:

> > For me name "output_iso" means nothing. iso is something about CD/DVD or
> > about standards. I would not guess that iso stands for isolation if I did
> > not know it already. isolation_output is more sensible: I have heard that
> > there are some isolation tests, this must be something about it. May be
> > it would be better to change it to isolation_output everywhere instead of
> > changing to output_iso
> That's just a default configuration used by the isolation tester.
> That's not much bothering with in my opinion for this patch, as the
> patch is here to make sure that the default configuration gets used
> where it had better be used.  Changing this default value would be of
> course doable technically, but that's around for years to changing it
> does not seem like good idea.

Ok. If it is long time tradition, let it be :-)
 
> > I tried to find definition in documentation what does "isolation test"
> > exactly means, but did not find. There is some general words about TAP
> > tests in main postgres documentation
> > https://www.postgresql.org/docs/11/regress-tap.html,
> > but I would not understand anything from it if I did not already know how
> > it works.
> 
> Those are mentioned here as part of the additional test suites:
> https://www.postgresql.org/docs/11/regress-run.html#id-1.6.20.5.5

Oh thanks (I feel urge to start editing documentation right now. I will 
surpress it, and do it, I hope, later.)
May I also ask a question, I came across. It is not part of the patch, but 
nevertheless...
If I look in the code, regression test are sql files with expected output that 
are in src/test/regress. If I look in the documentation, all the tests are 
regression tests including TAP tests. 
https://www.postgresql.org/docs/11/regress.html 

what is the right way to look at it?

> > In current extend-pgxs documentation there is some explanation about
> > regression test, it sensible enough. Since TAP and isolation tests are
> > introduced now, there should be same short explanation for both of
> > them.
> 
> I see your point here, and it is true that documentation ought to be
> better.  So I have written out a new set of paragraphs which explain the
> whereabouts of the new variables a bit more in depth in the section of 
> extend-pgxs.

Oh thanks! Now it is much more clear.

So, I continued exploring your patch. First I carefully read changes in 
pgxs.mk. The only part of it I did not understand is

 .PHONY: submake
-submake:
 ifndef PGXS
+submake:
+ifdef REGRESS
$(MAKE) -C $(top_builddir)/src/test/regress pg_regress$(X)
 endif
+ifdef ISOLATION
+   $(MAKE) -C $(top_builddir)/src/test/isolation all
+endif
+endif # PGXS

I suppose it is because the purpose of PGXS is never explained, not in the 
documentation, not in the code comments, and PGXS := $(shell $(PG_CONFIG) --
pgxs) sounds like some strange magic spell, that explains nothing. In what 
cases it is defined? In what cases it is not defined? What exactly does it 
store? Can we make things more easy to understand here? 

2. As far as you said that TAP tests for bloom were never executed, 
I guess I should just ignore

-
-wal-check: temp-install
-   (prove_check)

as a part of wrong way to execute TAP tests. (I fond no traces of "wal-check" 
string in the code, so I guess this build target is  an invention of bloom 
authors)

3. The rest are trivial, except changes for contrib/test_decoding/ and
src/test/modules/brin I will explore them in my next postgres-dev time slot 
and then my review work will be done :-)

-- 
Do code for fun.

signature.asc
Description: This is a digitally signed message part.


Re: Add extension options to control TAP and isolation tests

2018-11-25 Thread Nikolay Shaplov
В письме от 23 ноября 2018 09:43:45 пользователь Michael Paquier написал:

> > So, I continued exploring your patch. First I carefully read changes in
> > pgxs.mk. The only part of it I did not understand is
> > 
> >  .PHONY: submake
> > 
> > -submake:
> >  ifndef PGXS
> > 
> > +submake:
> > +ifdef REGRESS
> > 
> > $(MAKE) -C $(top_builddir)/src/test/regress pg_regress$(X)
> >  
> >  endif
> > 
> > +ifdef ISOLATION
> > +   $(MAKE) -C $(top_builddir)/src/test/isolation all
> > +endif
> > +endif # PGXS
> 
> This is to make sure that the necessary tools are compiled before
> running the related tests.  "submake:" needs to be moved out actually.
> Thinking about it a bit more, we should also remove the "ifdef REGRESS"
> and "ifdef ISOLATION" because there are some dependencies here.  For
> example TAP tests call pg_regress to initialize connection policy.  TAP
> tests may also use isolation_tester or such.

Can you add some comments in this part of pgxs.mk that explains this thing 
about pre-building needed tools? This will make understanding it more easy...

> 
> > I suppose it is because the purpose of PGXS is never explained, not in the
> > documentation, not in the code comments, and PGXS := $(shell $(PG_CONFIG)
> > -- pgxs) sounds like some strange magic spell, that explains nothing. In
> > what cases it is defined? In what cases it is not defined? What exactly
> > does it store? Can we make things more easy to understand here?
> 
> That's part of a larger scope which is here:
> https://www.postgresql.org/docs/11/extend-pgxs.html

I've carefully read this documentation. And did not get clear explanation of 
what is the true purpose of PGXS environment variable. Only  

"The last three lines should always be the same. Earlier in the file, you 
assign variables or add custom make rules." 

May be it should bot be discussed in the doc, but it should be mentioned in 
pgxs.mk . I guess both PGXS nad NO_PGXS should be explicitly described,  in 
order to make the rest of the code more readable. (As for me I now have some 
intuitive understanding of it's nature, but it would be better to have strict 
explanation)


So about test_decoding 

contrib/test_decoding/Makefile: 

EXTRA_INSTALL=contrib/test_decoding

This sounds a bit strange to me. Why in make file for  we 
should explicitly specify that this   is needed for tests. It 
is obviously needed! Man, we are testing it!! ;-)

I would suspect that is should be added somewhere in pgxs.mk code, when it is 
needed. Or this is not as obvious and trivial as I see it?

I guess it came from
-submake-test_decoding:
-$(MAKE) -C $(top_builddir)/contrib/test_decoding

but still there is no logic in it.


+REGRESS_OPTS = --temp-config $(top_srcdir)/contrib/test_decoding/logical.conf
+ISOLATION_OPTS = --temp-config 
$(top_srcdir)/contrib/test_decoding/logical.conf

When I read these lines an idea about ISOLATION_CONF and REGRESS_CONF 
variables came into my mind. That are transformed into proper _OPTS in pgxs.mk 
? Since there is only one use case, may be it do not worth it. So I just speak 
this thought aloud without any intention to make it reality.



-$(MAKE) -C $(top_builddir)/src/test/regress all
is replaced with
$(MAKE) -C $(top_builddir)/src/test/regress pg_regress$(X)
in pgxs.mk. I hope changing "all" to "pg_regress$(X)" is ok, because I do not 
understand it.



I've also greped for "pg_isolation_regress_check" and found that it is also 
used in src/test/modules/snapshot_too_old  that also uses PGXS (at least as an 
option) should not we include it in your patch too?


So I think that is it. Since Artur said, he successfully used your TAP patch 
in other extensions, I will not do it, considering it is already checked. If 
you think it is good to recheck, I can do it too :-)



signature.asc
Description: This is a digitally signed message part.


Re: Add extension options to control TAP and isolation tests

2018-11-25 Thread Nikolay Shaplov
В письме от 26 ноября 2018 08:53:20 Вы написали:

> > I've carefully read this documentation. And did not get clear explanation
> > of what is the true purpose of PGXS environment variable. Only
> > 
> > "The last three lines should always be the same. Earlier in the file, you
> > assign variables or add custom make rules."
> 
> The definition of PGXS is here:
> https://www.postgresql.org/docs/11/extend-pgxs.html
Can you please provide the quotation? I see there PGXS mentioned several times 
as "a build infrastructure for extensions" and as an environment variable it 
is mentioned only in code sample 

 
PGXS := $(shell $(PG_CONFIG) --pgxs)
include $(PGXS)

So for me there is no explanation. Or it is hard to find (that is also bad)

If we are done with your patch, can we still finish this line of discussion in 
order to create another small patch concerning PGXS-env-var comment?



signature.asc
Description: This is a digitally signed message part.


[PATCH] get rid of StdRdOptions, use individual binary reloptions representation for each relation kind instead

2018-02-22 Thread Nikolay Shaplov

This is part or my bigger patch 
https://www.postgresql.org/message-id/flat/2146419.veIEZdk4E4@x200m#2146419.veIEZdk4E4@x200m
 we've decided to
commit by smaller parts.

Now in postgres an StdRdOptions structure is used as binary represenations of
reloptions for heap, toast, and some indexes. It has a number of fields, and
only heap relation uses them all. Toast relations uses only autovacuum
options, and indexes uses only fillfactor option.

So for example if you set custom fillfactor value for some index, then it will
lead to allocating 84 bytes of memory (sizeof StdRdOptions on i386) and only 8
bytes will be actually used (varlena header and fillfactor value). 74 bytes is
not much, but allocating them for each index for no particular reason is bad
idea, as I think.

Moreover when I wrote my big reloption refactoring patch, I came to "one
reloption kind - one binary representation" philosophy. It allows to write
code with more logic in it.

This patch replaces StdRdOptions with HeapRelOptions, ToastRelOptions,
BTRelOptions, HashRelOptions, SpGistRelOptions and PartitionedRelOptions

one for each relation kind that were using StdRdOptions before.

The second thing I've done, I've renamed Relation* macroses from
src/include/utils/rel.h, that were working with reloptions. I've renamed them
into Heap*, Toast* and View* (depend on what relation options they were
actually using)

I did it because there names were misleading. For example
RelationHasCheckOption can be called only for View relation, and will give
wrong result for other relation types. It just takes binary representation of
reloptions, cast is to (ViewOptions *) and then returns some value from it.
Naming it as ViewHasCheckOption would better reflect what it actually do, and
strictly specify that it is applicable only to View relations.


Possible flaws:

I replaced

saveFreeSpace = RelationGetTargetPageFreeSpace(state->rs_new_rel,

HEAP_DEFAULT_FILLFACTOR);

with

if (IsToastRelation(state->rs_new_rel))
  saveFreeSpace = ToastGetTargetPageFreeSpace();
else
  saveFreeSpace = HeapGetTargetPageFreeSpace(state->rs_new_rel);

wherever I met it (and other cases like that), but I am not sure if in some
cases that part of code is used for heap only or not. So may be this "ifs" is
not needed and should be removed, and only Heap-case should be left. But I am
not that much familiar with postgres internals to see it for sure... I need
advice of more experienced developers here.

--
Do code for fun.diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c
index 46276ce..bf7441e 100644
--- a/src/backend/access/common/reloptions.c
+++ b/src/backend/access/common/reloptions.c
@@ -22,7 +22,7 @@
 #include "access/htup_details.h"
 #include "access/nbtree.h"
 #include "access/reloptions.h"
-#include "access/spgist.h"
+#include "access/spgist_private.h"
 #include "access/tuptoaster.h"
 #include "catalog/pg_type.h"
 #include "commands/defrem.h"
@@ -46,9 +46,8 @@
  * upper and lower bounds (if applicable); for strings, consider a validation
  * routine.
  * (ii) add a record below (or use add__reloption).
- * (iii) add it to the appropriate options struct (perhaps StdRdOptions)
- * (iv) add it to the appropriate handling routine (perhaps
- * default_reloptions)
+ * (iii) add it to the appropriate options struct
+ * (iv) add it to the appropriate handling routine
  * (v) make sure the lock level is set correctly for that operation
  * (vi) don't forget to document the option
  *
@@ -986,7 +985,7 @@ extractRelOptions(HeapTuple tuple, TupleDesc tupdesc,
 		case RELKIND_TOASTVALUE:
 		case RELKIND_MATVIEW:
 		case RELKIND_PARTITIONED_TABLE:
-			options = heap_reloptions(classForm->relkind, datum, false);
+			options = relation_reloptions(classForm->relkind, datum, false);
 			break;
 		case RELKIND_VIEW:
 			options = view_reloptions(datum, false);
@@ -1319,61 +1318,133 @@ fillRelOptions(void *rdopts, Size basesize,


 /*
- * Option parser for anything that uses StdRdOptions.
+ * Option parsing definition for autovacuum. Used in toast and heap options.
+ */
+
+#define AUTOVACUUM_RELOPTIONS(OFFSET)\
+		{"autovacuum_enabled", RELOPT_TYPE_BOOL, \
+		OFFSET + offsetof(AutoVacOpts, enabled)},\
+		{"autovacuum_vacuum_threshold", RELOPT_TYPE_INT, \
+		OFFSET + offsetof(AutoVacOpts, vacuum_threshold)},   \
+		{"autovacuum_analyze_threshold", RELOPT_TYPE_INT,\
+		OFFSET + offsetof(AutoVacOpts, analyze_threshold)},  \
+		{"autovacuum_vacuum_cost_delay", RELOPT_TYPE_INT,\
+		OFFSET + offsetof(AutoVacOpts, vacuum_cost_delay)},  \
+		{"autovacuum_vacuum_cost_limit", RELOPT_TYPE_INT,\
+		OFFSET + offsetof(AutoVacOpts, vacuum_cost_limit)},  \
+		{"autovacuum_freeze_min_age", RELOPT_TYPE_INT,   \
+		OFFSET + offse

Re: [HACKERS] [PATCH] Move all am-related reloption code into src/backend/access/[am-name] and get rid of relopt_kind for custom AM

2018-02-22 Thread Nikolay Shaplov
В письме от 3 сентября 2017 11:45:43 пользователь Alvaro Herrera написал:
> I think we should split this in at least two commits,
I've added a third part of this patch to commitfest:
https://www.postgresql.org/message-id/flat/2083183.Rn7qOxG4Ov@x200m#2083183.Rn7qOxG4Ov@x200m

To finally commit the rest of the path (the main part of it at least) I need 
this, and enum-options patches to be commited. Hope it will be done in march 
and I will offer the last part in next commitfest.

-- 
Do code for fun.

signature.asc
Description: This is a digitally signed message part.


Re: [PATCH] Opclass parameters

2018-02-28 Thread Nikolay Shaplov
В письме от 28 февраля 2018 00:46:36 пользователь Nikita Glukhov написал:

> I would like to present patch set implementing opclass parameters.
> 
> This feature was recently presented at pgconf.ru:
> http://www.sai.msu.su/~megera/postgres/talks/opclass_pgconf.ru-2018.pdf
> 
> A analogous work was already done by Nikolay Shaplov two years ago:
> https://www.postgresql.org/message-id/5213596.TqFRiqmCTe%40nataraj-amd64
> But this patches are not based on it, although they are very similar.
Hi!

You know, I am still working on this issue.

When I started to work on it, I found out that option code is not flexible at 
all, and you can' reuse it for options that are not relOptions.

I gave your patch just a short glance for now, but as far as I can you start 
deviding options into global and local one. I am afraid it will create grater 
mess than it is now.

What I am doing right now, I am creating a new reloption internal API, that 
will allow to create any option in any place using the very same code.

I think it should be done first, and then use it for opclass parameters and 
any kind of options you like.

The big patch is here https://commitfest.postgresql.org/14/992/ (I am afraid 
it will not apply to current master as it is, It is quite old. But you can get 
the idea)

The smaller parts of the patch that in current commitfest are

https://commitfest.postgresql.org/17/1536/
https://commitfest.postgresql.org/17/1489/

You can help reviewing them. Then the whole thing will go faster. The second 
patch is quite trivial. The first will also need attention of someone who is 
really good in understanding postgres internals.

---

Concerning the patch that you've provided. I've just have a short look. But I 
already have some question.

1. I've seen you've added a new attribute into pg_index. Why??!!
As far as I can get, if have index built on several columns (A1, A2, A3) you 
can set, own opclass for each column. And set individual options for each 
opclass if we are speaking about options. So I would expect to have these 
options not in pg_index, but in pg_attribute. And we already have one there: 
attoptions.I just do not get how you have come to per-index options. May be I 
should read code more attentively...


2. Your patch does not provide any example of your new tool usage. In my 
prototype patch I've shown the implementation of opclass options for intarray. 
May be you should do the same. (Use my example it will be more easy then do it 
from scratch). It will give more understanding of how this improvement can be 
used.

3. 

--- a/src/test/regress/expected/btree_index.out
+++ b/src/test/regress/expected/btree_index.out
@@ -150,3 +150,8 @@ vacuum btree_tall_tbl;
 -- need to insert some rows to cause the fast root page to split.
 insert into btree_tall_tbl (id, t)
   select g, repeat('x', 100) from generate_series(1, 500) g;
+-- Test unsupported btree opclass parameters
+create index on btree_tall_tbl (id int4_ops(foo=1));
+ERROR:  access method "btree" does not support opclass options 
+create index on btree_tall_tbl (id default(foo=1));
+ERROR:  access method "btree" does not support opclass options 

Are you sure we really need these in postgres???

-

So my proposal is the following:
let's commit 

https://commitfest.postgresql.org/17/1536/
https://commitfest.postgresql.org/17/1489/

I will provide a final patch for option engine refactoring in commit fest, and 
you will write you implementation of opclass options on top of it. We can to 
it simultaneously. Or I will write opclass options myself... I do not care who 
will do oplcass options as long it is done using refactored options engine. If 
you do it, I can review it.

> 
> 
> Opclass parameters can give user ability to:
>   * Define the values of the constants that are hardcoded now in the
> opclasses depending on the indexed data.
>   * Specify what to index for non-atomic data types (arrays, json[b],
> tsvector). Partial index can only filter whole rows.
>   * Specify what indexing algorithm to use depending on the indexed data.
> 
> 
> Description of patches:
> 
> 1. Infrastructure for opclass parameters.
> 
> SQL grammar is changed only for CREATE INDEX statement: parenthesized
> parameters in reloptions format are added after column's opclass name. 
> Default opclass can be specified with DEFAULT keyword:
> 
> CREATE INDEX idx ON tab USING am (
> {expr {opclass | DEFAULT} ({name=value} [,...])} [,...]
> );
> 
> Example for contrib/intarray:
> 
> CREATE INDEX ON arrays USING gist (
>arr gist__intbig_ops (siglen = 32),
>arr DEFAULT (numranges = 100)
> );
> 
> \d arrays
>  Table "public.arrays"
>   Column |   Type| Collation | Nullable | Default
> +---

Re: [PATCH] Opclass parameters

2018-03-02 Thread Nikolay Shaplov
В письме от 1 марта 2018 23:02:20 пользователь Oleg Bartunov написал:

> > 2. Your patch does not provide any example of your new tool usage. In my
> > prototype patch I've shown the implementation of opclass options for
> > intarray. May be you should do the same. (Use my example it will be more
> > easy then do it from scratch). It will give more understanding of how
> > this improvement can be used.
> 
> Hey, look on patches, there are many examples  !
Oups...Sorry. I've looked at the patch from commitfest 
https://commitfest.postgresql.org/17/1559/ and it have shown only the first 
file. And When I read the letter I did not pay attention to attachments at 
all. So I was sure there is only one there.

Yes. Now I see seven examples. But I think seven it is too many.
For each case a reviewer should make consideration if this parameter worth 
moving to opclass options, or fixed definition in the C code is quite ok. 
Doing it for whole bunch, may make it messy. I think, it would be good to 
commit an implementation of opclass options, with a good example of usage. And 
then commit patches for all cases where these options can be used. 

But since it is now "Rejected with feedback", let's wait till autumn. 

-- 
Do code for fun.

signature.asc
Description: This is a digitally signed message part.


Re: [PATCH] get rid of StdRdOptions, use individual binary reloptions representation for each relation kind instead

2018-03-02 Thread Nikolay Shaplov
В письме от 1 марта 2018 16:15:32 пользователь Andres Freund написал:

> > This is part or my bigger patch
> > https://www.postgresql.org/message-id/flat/2146419.veIEZdk4E4@x200m#21464
> > 19.veIEZdk4E4@x200m we've decided to commit by smaller parts.
> 
> I've not read that thread. Is this supposed to be a first step towards
> something larger?

I've started from the idea of opclass options. Same as here 
https://commitfest.postgresql.org/17/1559/
And found out that current reloptions code is not flexible at all, and could 
not be easily reused for other kind of options (that are not reloptions).

So I tried to change reloptions code to make universal, and then use it for 
any option purposes.

In the patch https://commitfest.postgresql.org/14/992/ I created a new file 
options.c, that works with options as with an abstraction. It has some option 
definition structure, that has all information about how this options should 
be parsed and transformed into binary representation, I called this structure 
OptionsCatalog, but name can be changed. And it also have all kind of 
functions that do all needed tranformation with options.

Then reloptions.c uses functions from options options.c for all options 
transformations, and takes care about relation specificity of reloptions.

While doing all of these, I first of all had to adjust code that was written 
around reloptions, so that there code would stay in tune with new reloptions 
code. And second, I met places where current reloption related code were 
imperfect, and I decided to change it too...

Since I get a really big patch as a result, it was decided to commit it in 
parts.

This patch is the adjusting of reloption related code. It does not change a 
great deal, but when you first commit it, the main reloptions refactoring 
patch will no longer look like a big mess, it will became much more logical.

Enum options patch is more about making coder a little bit more perfect. It is 
not really needed for the main patch, but it is more easy to introduce it 
before, then after.
https://commitfest.postgresql.org/17/1489/

There is one more patch, that deals with toast.* options for tables with no 
TOAST, but we can set it aside, it is independent enough, to deal with it 
later... 
https://commitfest.postgresql.org/17/1486/

The patch with reloptions tests I've written while working on this patch, were 
already commited
https://commitfest.postgresql.org/15/1314/


> > So for example if you set custom fillfactor value for some index, then it
> > will lead to allocating 84 bytes of memory (sizeof StdRdOptions on i386)
> > and only 8 bytes will be actually used (varlena header and fillfactor
> > value). 74 bytes is not much, but allocating them for each index for no
> > particular reason is bad idea, as I think.
> I'm not sure this is a particularly strong motivator though?  Does the
> patch have a goal besides saving a few bytes?

My real motivation for this patch is to make code more uniform. So the patch 
over it will be much clearer. And to make result code more clear and uniform 
too.

I guess long time ago, the StdRdOptions were the way to make code uniform. 
There were only one binary representation of options, and all relation were 
using it. Quite uniform.

But now, some relation kinds uses it's own options binary representations. 
Some still uses StdRdOptions, but only some elements from it. It is not 
uniform enough for me.

If start using individual binary representation for each relation kind, then 
code will be uniform and homogeneous again, and my next patch over it will be 
more easy to read and understand. 

> > Moreover when I wrote my big reloption refactoring patch, I came to "one
> > reloption kind - one binary representation" philosophy. It allows to write
> > code with more logic in it.
> I have no idea what this means?
I hope I managed to explain it above... May be I am not good enough with 
explaining, or with English. Or with explaining in English. If it is not clear 
enough, please tell me, what points are not clear, I'll try to explain more...


> Are you aiming this for v11 or v12?
I hope to commit StdRdOptions and Enum_Options patches before v11. 
Hope it does not go against any rules, since there patches does not change any 
big functionality, just do some refactoring and optimization, of the code that 
already exists.

As for main reloptions refactoring patch, if there is a chance to get commited 
before v11 release, it would be great. If not, I hope to post it to 
commitfest, right after v11 were released, so it would be possible to commit 
opclass options upon it before v12 release. 


-- 
Do code for fun.

signature.asc
Description: This is a digitally signed message part.


Re: [PATCH][PROPOSAL] Add enum releation option type

2018-03-07 Thread Nikolay Shaplov
В письме от 1 марта 2018 19:11:05 пользователь Nikita Glukhov написал:
> Hi.
>
> I have refactored patch by introducing new struct relop_enum_element to make
> it possible to use existing C-enum values in option's definition.  So,
> additional enum GIST_OPTION_BUFFERING_XXX was removed.

Hi! I've imported yours relopt_enum_element solution. Since Alvaro liked it,
and I like it to. But I called it relopt_enum_element_definition, as it is not
an element itself, but a description of possibilities.

But I do not want to import the rest of it.

> #define RELOPT_ENUM_DEFAULT ((const char *) -1)   /* pseudo-name for 
> default
> value */

I've discussed this solution with my C-experienced friends, and each of them
said, that it will work, but it is better not to use ((const char *) -1) as it
will stop working without any warning, because it is not standard C solution
and newer C-compiler can stop accepting such thing without further notice.

I would avoid using of such thing if possible.

> Also default option value should be placed now in the first element of
> allowed_values[].  This helps not to expose default values definitions (like
> GIST_BUFFERING_AUTO defined in gistbuild.c).

For all other reloption types, default value is a part of relopt_* structure.
I see no reason to do otherwise for enum.

As for exposing GIST_BUFFERING_AUTO. We do the same for default fillfactor
value. I see no reason why we should do otherwise here...

And if we keep default value on relopt_enum, we will not need
RELOPT_ENUM_DEFAULT that, as I said above, I found dubious.


> for (elem = opt_enum->allowed_values; elem->name; elem++)
It is better then I did. I imported that too.

> if (validate && !parsed)
Oh, yes... There was my mistake. I did not consider validate == false case.
I should do it. Thank you for pointing this out.

But I think that we should return default value if the data in pg_class is
brocken.

May be I later should write an additional patch, that throw WARNING if
reloptions from pg_class can't be parsed. DB admin should know about it, I
think...


The rest I've kept as I do before. If you think that something else should be
changed, I'd like to see, not only the changes, but also some explanations. I
am not sure, for example that we should use same enum for reloptions and
metapage buffering mode representation for example. This seems to be logical,
but it may also confuse. I wan to hear all opinions before doing it, for
example.

May be

typedef enum gist_option_buffering_numeric_values
{
GIST_OPTION_BUFFERING_ON = GIST_BUFFERING_STATS,
GIST_OPTION_BUFFERING_OFF = GIST_BUFFERING_DISABLED,
GIST_OPTION_BUFFERING_AUTO = GIST_BUFFERING_AUTO,
} gist_option_buffering_value_numbers;

will do, and then we can assign one enum to another, keeping the traditional
variable naming?

I also would prefer to keep all enum definition in an .h file, not enum part
in .h file, and array part in .c.

--
Do code for fun.diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c
index 46276ce..4b775ab 100644
--- a/src/backend/access/common/reloptions.c
+++ b/src/backend/access/common/reloptions.c
@@ -404,7 +404,11 @@ static relopt_real realRelOpts[]  	{{NULL}}
 };

-static relopt_string stringRelOpts[] +static relopt_enum_element_definition gist_buffering_enum_def[] +		GIST_OPTION_BUFFERING_ENUM_DEF;
+static relopt_enum_element_definition view_check_option_enum_def[] +		VIEW_OPTION_CHECK_OPTION_ENUM_DEF;
+static relopt_enum enumRelOpts[]  {
 	{
 		{
@@ -413,10 +417,8 @@ static relopt_string stringRelOpts[]  			RELOPT_KIND_GIST,
 			AccessExclusiveLock
 		},
-		4,
-		false,
-		gistValidateBufferingOption,
-		"auto"
+		gist_buffering_enum_def,
+		GIST_OPTION_BUFFERING_AUTO
 	},
 	{
 		{
@@ -425,11 +427,14 @@ static relopt_string stringRelOpts[]  			RELOPT_KIND_VIEW,
 			AccessExclusiveLock
 		},
-		0,
-		true,
-		validateWithCheckOption,
-		NULL
+		view_check_option_enum_def,
+		VIEW_OPTION_CHECK_OPTION_NOT_SET
 	},
+	{{NULL}}
+};
+
+static relopt_string stringRelOpts[] +{
 	/* list terminator */
 	{{NULL}}
 };
@@ -476,6 +481,12 @@ initialize_reloptions(void)
    realRelOpts[i].gen.lockmode));
 		j++;
 	}
+	for (i = 0; enumRelOpts[i].gen.name; i++)
+	{
+		Assert(DoLockModesConflict(enumRelOpts[i].gen.lockmode,
+   enumRelOpts[i].gen.lockmode));
+		j++;
+	}
 	for (i = 0; stringRelOpts[i].gen.name; i++)
 	{
 		Assert(DoLockModesConflict(stringRelOpts[i].gen.lockmode,
@@ -514,6 +525,14 @@ initialize_reloptions(void)
 		j++;
 	}

+	for (i = 0; enumRelOpts[i].gen.name; i++)
+	{
+		relOpts[j] = &enumRelOpts[i].gen;
+		relOpts[j]->type = RELOPT_TYPE_ENUM;
+		relOpts[j]->namelen = strlen(relOpts[j]->name);
+		j++;
+	}
+
 	for (i = 0; stringRelOpts[i].gen.name; i++)
 	{
 		relOpts[j] = &stringRelOpts[i].gen;
@@ -611,6 +630,9 @@ allocate_reloption(bits32 kinds, int type, const char *name, const char *desc)
 		case RELOPT_TYPE_REAL:
 			size = sizeof(relo

Re: [PATCH][PROPOSAL] Add enum releation option type

2018-03-07 Thread Nikolay Shaplov
В письме от 1 марта 2018 14:47:35 пользователь Alvaro Herrera написал:

> I see you lost the Oxford comma:
> 
> -DETAIL:  Valid values are "on", "off", and "auto".
> +DETAIL:  Valid values are "auto", "on" and "off".
> 
> Please put these back.
Actually that's me who have lost it. The code with  oxford comma would be a 
bit more complicated. We should put such coma when we have 3+ items and do not 
put it when we have 2.

Does it worth it?

As I've read oxford using of comma is not mandatory and used to avoid 
ambiguity.
"XXX, YYY and ZZZ" can be read as "XXX, YYY, ZZZ" or as "XXX, (YYY and ZZZ)".
oxford comma is used to make sure that YYY and ZZZ are separate items of the 
list, not an expression inside one item.

But here we hardly have such ambiguity.

So I'll ask again, do you really think it worth it?


-- 
Do code for fun.

signature.asc
Description: This is a digitally signed message part.


Re: [PATCH] get rid of StdRdOptions, use individual binary reloptions representation for each relation kind instead

2018-03-07 Thread Nikolay Shaplov
В письме от 2 марта 2018 11:27:49 пользователь Andres Freund написал:

> > Since I get a really big patch as a result, it was decided to commit it in
> > parts.
> 
> I get that, but I strongly suggest not creating 10 loosely related
> threads, but keeping it as a patch series in one thread. It's really
> hard to follow for people not continually paying otherwise. 

Oups. Sorry I thought I should do other way round and create a new thread for 
new patch. And tried to post a link to other threads for connectivity wherever 
I can.

Will do it as you say from now on. 

But I am still confused what should I do if I am commiting two patch from the 
patch series in simultaneously... 

-- 
Do code for fun.

signature.asc
Description: This is a digitally signed message part.


Bug in jsonb_in function (14 & 15 version are affected)

2023-03-13 Thread Nikolay Shaplov
Hi!

I found a bug in jsonb_in function (it converts json from sting representation
 into jsonb internal representation).

To reproduce this bug (the way I found it) you should get 8bit instance of 
postgres db:

1. add en_US locale (dpkg-reconfigure locales in debian)
2. initdb with latin1 encoding: 

LANG=en_US ./initdb --encoding=LATIN1 -D my_pg_data

3. run database and execute the query:

SELECT 
E'{\x0a"\x5cb\x5c"\x5c\x5c\x5c/\x5cb\x5cf\x5cn\x5cr\x5ct\x5c"\x5c\x5c\x5c\x5crZt\x5c"\x5c\x5c\x5c/\x5cb\x5c"\x5c\x5c\x5c/\x5cb\x5c"\x5cu000f0\x5cu000f000\x5cuDFFF"000\x5cu000\xb4\x5cuDBFF\x5cuDFFF0002000\x5cuDBFF'::jsonb;

In postgres 14 and 15, the backend will crash.

The packtrace produce with ASan is in the attached file.

This bug was found while fuzzing postgres input functions, using AFL++.
For now we are using lightweight wrapper around input functions that 
create minimal environment for these functions to run conversion, and run the, 
in fuzzer.


My colleagues (they will come here shortly) have narrowed down this query to 

SELECT E'\n"\\u0"'::jsonb;

and says that is crashes even in utf8 locale.

They also have a preliminary version of patch to fix it. They will tell about 
it soon, I hope.

-- 
Nikolay Shaplov aka Nataraj
Fuzzing Engineer at Postgres Professional
Matrix IM: @dhyan:nataraj.su
=
==90012==ERROR: AddressSanitizer: negative-size-param: (size=-1)
#0 0x533f04 in __asan_memcpy 
(/home/nataraj/dev/.install/default/bin/postgres+0x533f04)
#1 0x102145a in report_json_context 
/home/nataraj/dev/postgrespro/src/backend/utils/adt/jsonfuncs.c:685:2
#2 0x1020a32 in json_ereport_error 
/home/nataraj/dev/postgrespro/src/backend/utils/adt/jsonfuncs.c:631:3
#3 0x1020976 in pg_parse_json_or_ereport 
/home/nataraj/dev/postgrespro/src/backend/utils/adt/jsonfuncs.c:511:3
#4 0x1009176 in jsonb_from_cstring 
/home/nataraj/dev/postgrespro/src/backend/utils/adt/jsonb.c:265:2
#5 0x1008f3b in jsonb_in 
/home/nataraj/dev/postgrespro/src/backend/utils/adt/jsonb.c:81:9
#6 0x121d547 in InputFunctionCall 
/home/nataraj/dev/postgrespro/src/backend/utils/fmgr/fmgr.c:1533:11
#7 0x121dd10 in OidInputFunctionCall 
/home/nataraj/dev/postgrespro/src/backend/utils/fmgr/fmgr.c:1636:9
#8 0x8cbd0e in stringTypeDatum 
/home/nataraj/dev/postgrespro/src/backend/parser/parse_type.c:662:9
#9 0x87eb68 in coerce_type 
/home/nataraj/dev/postgrespro/src/backend/parser/parse_coerce.c
#10 0x87dec1 in coerce_to_target_type 
/home/nataraj/dev/postgrespro/src/backend/parser/parse_coerce.c:105:11
#11 0x891b40 in transformTypeCast 
/home/nataraj/dev/postgrespro/src/backend/parser/parse_expr.c:2717:11
#12 0x88f0b8 in transformExprRecurse 
/home/nataraj/dev/postgrespro/src/backend/parser/parse_expr.c:168:13
#13 0x88efb1 in transformExpr 
/home/nataraj/dev/postgrespro/src/backend/parser/parse_expr.c:126:11
#14 0x8c358b in transformTargetEntry 
/home/nataraj/dev/postgrespro/src/backend/parser/parse_target.c:96:11
#15 0x8c37c2 in transformTargetList 
/home/nataraj/dev/postgrespro/src/backend/parser/parse_target.c:184:10
#16 0x83a583 in transformSelectStmt 
/home/nataraj/dev/postgrespro/src/backend/parser/analyze.c:1317:20
#17 0x836ad4 in transformStmt 
/home/nataraj/dev/postgrespro/src/backend/parser/analyze.c:366:15
#18 0x836d5e in transformOptionalSelectInto 
/home/nataraj/dev/postgrespro/src/backend/parser/analyze.c:306:9
#19 0x8364d4 in transformTopLevelStmt 
/home/nataraj/dev/postgrespro/src/backend/parser/analyze.c:256:11
#20 0x83640e in parse_analyze_fixedparams 
/home/nataraj/dev/postgrespro/src/backend/parser/analyze.c:124:10
#21 0xef9c4b in pg_analyze_and_rewrite_fixedparams 
/home/nataraj/dev/postgrespro/src/backend/tcop/postgres.c:659:10
#22 0xefe818 in exec_simple_query 
/home/nataraj/dev/postgrespro/src/backend/tcop/postgres.c:1169:20
#23 0xefd92d in PostgresMain 
/home/nataraj/dev/postgrespro/src/backend/tcop/postgres.c
#24 0xd837f0 in BackendRun 
/home/nataraj/dev/postgrespro/src/backend/postmaster/postmaster.c:4538:2
#25 0xd82e6f in BackendStartup 
/home/nataraj/dev/postgrespro/src/backend/postmaster/postmaster.c:4266:3
#26 0xd816b3 in ServerLoop 
/home/nataraj/dev/postgrespro/src/backend/postmaster/postmaster.c:1833:7
#27 0xd7e8e0 in PostmasterMain 
/home/nataraj/dev/postgrespro/src/backend/postmaster/postmaster.c:1505:11
#28 0xb7ddc2 in main 
/home/nataraj/dev/postgrespro/src/backend/main/main.c:209:3
#29 0x77190d09 in __libc_start_main csu/../csu/libc-start.c:308:16
#30 0x4baa99 in _start 
(/home/nataraj/dev/.install/default/bin/postgres+0

Build problem with square brackets in build path

2023-04-28 Thread Nikolay Shaplov
I am not sure it is really a bug, but nevertheless

If you do

mkdir [source]
git clone git://git.postgresql.org/git/postgresql.git [source]
mkdir build; cd build
../\[source\]/configure 
make

you will get

make[1]: *** No rule to make target 'generated-headers'.  Stop.

If there are no "[]" in the path to the source, everything is OK.

It would be OK for me, if it still does not work. But I would appreciate at 
least proper error message there (or at configure step), this would save time, 
for figuring out, why it suddenly stopped working.


-- 
Nikolay Shaplov aka Nataraj
Fuzzing Engineer at Postgres Professional
Matrix IM: @dhyan:nataraj.su


signature.asc
Description: This is a digitally signed message part.


Re: [PATCH] New [relation] option engine

2023-12-08 Thread Nikolay Shaplov
В письме от пятница, 8 декабря 2023 г. 08:59:41 MSK пользователь Michael 
Paquier написал:

> > I've rebased patch, so it could be add to commitfest again.
> 
> This is a 270kB patch with quite a few changes, and a lot of code
> 
> moved around:
> >  47 files changed, 2592 insertions(+), 2326 deletions(-)
> 
> Could it be possible to split that into more successive steps to ease
> its review?

Theoretically I can create patch with full options.c as it is in the patch 
now, and use that code only in index AM, and keep reloption.c mostly 
unchanged.

This will be total mess with two different options mechanisms working in the 
same time, but this might be much more easy to review.  When we are done with 
the first step, we can change the rest.
If this will help to finally include patch into postgres, I can do it. Will 
that help you to review?


-- 
Nikolay Shaplov aka Nataraj
Fuzzing Engineer at Postgres Professional
Matrix IM: @dhyan:nataraj.su


signature.asc
Description: This is a digitally signed message part.


Re: [PATCH] New [relation] option engine

2023-12-08 Thread Nikolay Shaplov
В письме от пятница, 8 декабря 2023 г. 15:59:09 MSK пользователь Alvaro 
Herrera написал:

> > Theoretically I can create patch with full options.c as it is in the patch
> > now, and use that code only in index AM, and keep reloption.c mostly
> > unchanged.
> > 
> > This will be total mess with two different options mechanisms working in
> > the same time, but this might be much more easy to review.  When we are
> > done with the first step, we can change the rest.
> > If this will help to finally include patch into postgres, I can do it.
> > Will
> > that help you to review?
> 
> I don't think that's better, because we could create slight
> inconsistencies between the code used for index AMs and the users of
> reloptions.
I've written quite good regression tests for it, there should be no 
inconsistency.
 
> I'm not seeing any reasonable way to split this patch in smaller ones.
Actually me neither. Not a good one anyway.

But if somebody really need it to be split, it can be done that way.

-- 
Nikolay Shaplov aka Nataraj
Fuzzing Engineer at Postgres Professional
Matrix IM: @dhyan:nataraj.su


signature.asc
Description: This is a digitally signed message part.


Re: [PATCH] Finally split StdRdOptions into HeapOptions and ToastOptions

2020-03-28 Thread Nikolay Shaplov
A new version of the patch.
Autovacuum options were extended in b07642db

So I added that options to the current patch.diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c
index e136116..55bd1ec 100644
--- a/src/backend/access/common/reloptions.c
+++ b/src/backend/access/common/reloptions.c
@@ -46,9 +46,8 @@
  * upper and lower bounds (if applicable); for strings, consider a validation
  * routine.
  * (ii) add a record below (or use add__reloption).
- * (iii) add it to the appropriate options struct (perhaps StdRdOptions)
- * (iv) add it to the appropriate handling routine (perhaps
- * default_reloptions)
+ * (iii) add it to the appropriate options struct
+ * (iv) add it to the appropriate handling routine
  * (v) make sure the lock level is set correctly for that operation
  * (vi) don't forget to document the option
  *
@@ -1147,9 +1146,11 @@ extractRelOptions(HeapTuple tuple, TupleDesc tupdesc,
 	switch (classForm->relkind)
 	{
 		case RELKIND_RELATION:
-		case RELKIND_TOASTVALUE:
 		case RELKIND_MATVIEW:
-			options = heap_reloptions(classForm->relkind, datum, false);
+			options = heap_reloptions(datum, false);
+			break;
+		case RELKIND_TOASTVALUE:
+			options = toast_reloptions(datum, false);
 			break;
 		case RELKIND_PARTITIONED_TABLE:
 			options = partitioned_table_reloptions(datum, false);
@@ -1521,59 +1522,66 @@ fillRelOptions(void *rdopts, Size basesize,
 
 
 /*
- * Option parser for anything that uses StdRdOptions.
+ * Option parsing definition for autovacuum. Used in toast and heap options.
+ */
+
+#define AUTOVACUUM_RELOPTIONS(OFFSET)\
+		{"autovacuum_enabled", RELOPT_TYPE_BOOL, \
+		OFFSET + offsetof(AutoVacOpts, enabled)},\
+		{"autovacuum_vacuum_threshold", RELOPT_TYPE_INT, \
+		OFFSET + offsetof(AutoVacOpts, vacuum_threshold)},   \
+		{"autovacuum_vacuum_insert_threshold", RELOPT_TYPE_INT,  \
+		OFFSET + offsetof(AutoVacOpts, vacuum_ins_threshold)},   \
+		{"autovacuum_analyze_threshold", RELOPT_TYPE_INT,\
+		OFFSET + offsetof(AutoVacOpts, analyze_threshold)},  \
+		{"autovacuum_vacuum_cost_delay", RELOPT_TYPE_REAL,   \
+		OFFSET + offsetof(AutoVacOpts, vacuum_cost_delay)},  \
+		{"autovacuum_vacuum_cost_limit", RELOPT_TYPE_INT,\
+		OFFSET + offsetof(AutoVacOpts, vacuum_cost_limit)},  \
+		{"autovacuum_freeze_min_age", RELOPT_TYPE_INT,   \
+		OFFSET + offsetof(AutoVacOpts, freeze_min_age)}, \
+		{"autovacuum_freeze_max_age", RELOPT_TYPE_INT,   \
+		OFFSET + offsetof(AutoVacOpts, freeze_max_age)}, \
+		{"autovacuum_freeze_table_age", RELOPT_TYPE_INT, \
+		OFFSET + offsetof(AutoVacOpts, freeze_table_age)},   \
+		{"autovacuum_multixact_freeze_min_age", RELOPT_TYPE_INT, \
+		OFFSET + offsetof(AutoVacOpts, multixact_freeze_min_age)},   \
+		{"autovacuum_multixact_freeze_max_age", RELOPT_TYPE_INT, \
+		OFFSET + offsetof(AutoVacOpts, multixact_freeze_max_age)},   \
+		{"autovacuum_multixact_freeze_table_age", RELOPT_TYPE_INT,   \
+		OFFSET + offsetof(AutoVacOpts, multixact_freeze_table_age)}, \
+		{"log_autovacuum_min_duration", RELOPT_TYPE_INT, \
+		OFFSET + offsetof(AutoVacOpts, log_min_duration)},   \
+		{"autovacuum_vacuum_scale_factor", RELOPT_TYPE_REAL, \
+		OFFSET + offsetof(AutoVacOpts, vacuum_scale_factor)},\
+		{"autovacuum_vacuum_insert_scale_factor", RELOPT_TYPE_REAL,  \
+		OFFSET  + offsetof(AutoVacOpts, vacuum_ins_scale_factor)},   \
+		{"autovacuum_analyze_scale_factor", RELOPT_TYPE_REAL,\
+		OFFSET + offsetof(AutoVacOpts, analyze_scale_factor)}
+/*
+ * Option parser for heap
  */
 bytea *
-default_reloptions(Datum reloptions, bool validate, relopt_kind kind)
+heap_reloptions(Datum reloptions, bool validate)
 {
 	static const relopt_parse_elt tab[] = {
-		{"fillfactor", RELOPT_TYPE_INT, offsetof(StdRdOptions, fillfactor)},
-		{"autovacuum_enabled", RELOPT_TYPE_BOOL,
-		offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, enabled)},
-		{"autovacuum_vacuum_threshold", RELOPT_TYPE_INT,
-		offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, vacuum_threshold)},
-		{"autovacuum_vacuum_insert_threshold", RELOPT_TYPE_INT,
-		offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, vacuum_ins_threshold)},
-		{"autovacuum_analyze_threshold", RELOPT_TYPE_INT,
-		offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, analyze_threshold)},
-		{"autovacuum_vacuum_cost_limit", RELOPT_TYPE_INT,
-		offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, vacuum_cost_limit)},
-		{"autovacuum_freeze_min_age", RELOPT_TYPE_INT,
-		offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, freeze_min_age)},
-		{"autovacuum_freeze_max_age", RELOPT_TYPE_INT,
-		offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, freeze_max_age)},
-		{"autovacuum_freeze_table_age"

[PATCH] minor reloption regression tests improvement

2022-02-11 Thread Nikolay Shaplov
I'd like to suggest a patch for reloption regression tests.

This patch tests case, that can be rarely met in actual life: when reloptions 
have some illegal option set (as a result of malfunction or extension 
downgrade or something), and user tries to remove this option by using RESET.
Current postgres behaviour is to actually remove this option.

Like:

UPDATE pg_class  SET reloptions = '{illegal_option=4}' 
   WHERE oid = 'reloptions_test'::regclass;

ALTER TABLE reloptions_test RESET (illegal_option);

Why this should be tested:
1. It is what postgres actually do now.
2. This behaviour is reasonable. DB User can fix problem without updating 
pg_class, having rights to change his own table.
3. Better to get test alarm, if this behavior is accidentally changed.  

-- 
Nikolay Shaplov aka Nataraj
Fuzzing Engineer at Postgres Professional
Matrix IM: @dhyan:nataraj.su
diff --git a/src/test/regress/expected/reloptions.out b/src/test/regress/expected/reloptions.out
index b6aef6f654..9f460a7e60 100644
--- a/src/test/regress/expected/reloptions.out
+++ b/src/test/regress/expected/reloptions.out
@@ -183,6 +183,17 @@ SELECT reloptions FROM pg_class WHERE oid = (
  {autovacuum_vacuum_cost_delay=23}
 (1 row)
 
+-- Can reset option that is not allowed, but for some reason is already set
+UPDATE pg_class
+	SET reloptions = '{fillfactor=13,autovacuum_enabled=false,illegal_option=4}'
+	WHERE oid = 'reloptions_test'::regclass;
+ALTER TABLE reloptions_test RESET (illegal_option);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+reloptions
+--
+ {fillfactor=13,autovacuum_enabled=false}
+(1 row)
+
 --
 -- CREATE INDEX, ALTER INDEX for btrees
 --
diff --git a/src/test/regress/sql/reloptions.sql b/src/test/regress/sql/reloptions.sql
index 4252b0202f..fadce3384d 100644
--- a/src/test/regress/sql/reloptions.sql
+++ b/src/test/regress/sql/reloptions.sql
@@ -105,6 +105,13 @@ SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
 SELECT reloptions FROM pg_class WHERE oid = (
 	SELECT reltoastrelid FROM pg_class WHERE oid = 'reloptions_test'::regclass);
 
+-- Can reset option that is not allowed, but for some reason is already set
+UPDATE pg_class
+	SET reloptions = '{fillfactor=13,autovacuum_enabled=false,illegal_option=4}'
+	WHERE oid = 'reloptions_test'::regclass;
+ALTER TABLE reloptions_test RESET (illegal_option);
+SELECT reloptions FROM pg_class WHERE oid = 'reloptions_test'::regclass;
+
 --
 -- CREATE INDEX, ALTER INDEX for btrees
 --


Re: TAP output format in pg_regress

2022-11-10 Thread Nikolay Shaplov
Hi! Do this patch still need reviewer, or reviewer field in commit-fest have 
been left empty by mistake?

I am fan of TAP-tests, so I am quite happy that pg_regress output changed to 
TAP tests...

I've checked new output, if is conform TAP specification. Checked that prove 
consumes new pg_regress output well.

Did not found quick way to include prove TAP harness right into Makefile, so I 
check dumped output, but it is not really important for now, I guess.

As for the code, I gave it a quick readthrough... And main issue I've stumbled 
was here:

--
 indent = 36 - (parallel ? 8 : 0) - floor(log10(testnumber) + 1);

status("ok %-5i %s%-*s %8.0f ms",
   testnumber, (parallel ? "" : ""), indent,
   testname,
   runtime);
--

This peace of code has non-obvious logic (I can solve it without taking time 
for deep thinking) and this code (almost similar) is repeated three times. 
This is hard to support, and error prone solution. 

I would suggest to add one _print_test_status function, that also accepts 
status string and do this complex calculations and formatting only once (
"# SKIP (ignored)" should also added as %s, so we have only one print with 
complex format string).

Then you will have to read check and fix it only once.  

And may be it would be good to make this calculations more human-readable...


If this patch really needs reviewer and my way of thinking is acceptable, 
please let me know, I will set myself as a reviewer and will dig further into 
the code.

-- 
Nikolay Shaplov aka Nataraj
Fuzzing Engineer at Postgres Professional
Matrix IM: @dhyan:nataraj.su


signature.asc
Description: This is a digitally signed message part.


Re: TAP output format in pg_regress

2022-11-24 Thread Nikolay Shaplov
You guys are really fast... I only think about problem, it is already 
mentioned here... Most issues I've noticed are already fixed before I was able 
to say something. 

Nevertheless...

 /* 
 
  * Bailing out is for unrecoverable errors which prevents further testing to   
 
  * occur and after which the test run should be aborted. By passing non_rec
 
  * as true the process will exit with _exit(2) and skipping registered exit
 
  * handlers.   
 
  */
 
 static void
 
 bail_out(bool non_rec, const char *fmt,...)
 
 {   

In original code, where _exit were called, there were mention about recursion 
(whatever it is) as a reason for using _exit() instead of exit(). Now this 
mention is gone:

-   _exit(2);   /* not exit(), that could be recursive */
+   /* Not using the normal bail() as we want _exit */
+   _bail(_("could not stop postmaster: exit code was %d\n"), r);

The only remaining part of recursion is _rec suffix.

I guess we should keep mention of recursion in comments, and for me _rec 
stands for "record", not "recursion", I will not guess original meaning by 
_rec suffix. I would suggest to change it to _recurs or _recursive to keep 
things clear

-

+#define _bail(...) bail_out(true, __VA_ARGS__)
+#define bail(...)  bail_out(false, __VA_ARGS__)

I will never guess what the difference between bail, _bail and bail_out. We 
need really good explanation here, or better to use self-explanatory names 
here... 

I would start bail_out with _ as it is "internal", not used in the code.
And for _bail I would try to find some name that shows it's nature. Like 
bail_in_recursion or something.

-

+   if (ok || ignore)
{
-   va_start(ap, fmt);
-   vfprintf(logfile, fmt, ap);
-   va_end(ap);
+   emit_tap_output(TEST_STATUS, "ok %-5i %s%-*s %8.0f ms%s\n",
+   testnumber,
+   (parallel ? PARALLEL_INDENT : ""),
+   padding, testname,
+   runtime,
+   (ignore ? " # SKIP (ignored)" : ""));
+   }
+   else
+   {
+   emit_tap_output(TEST_STATUS, "not ok %-5i %s%-*s %8.0f ms\n",
+   testnumber,
+   (parallel ? PARALLEL_INDENT : ""),
+   padding, testname,
+   runtime);
}

This magic spell "...%-5i %s%-*s %8.0f ms\n" is too dark to repeat it even two 
times. I understand problems with spaces... But may be it would be better 
somehow narrow it to one ugly print... Print "ok %-5i"|"not ok %-5i" to 
buffer first, and then have one "%s%-*s %8.0f ms%s\n" print or something like 
that...

I am not strongly insisting on that, but I feel strong urge to remove code 
duplication here...


-- 
Nikolay Shaplov aka Nataraj
Fuzzing Engineer at Postgres Professional
Matrix IM: @dhyan:nataraj.su


signature.asc
Description: This is a digitally signed message part.


Re: TAP output format in pg_regress

2022-11-26 Thread Nikolay Shaplov
В письме от пятница, 25 ноября 2022 г. 00:20:01 MSK пользователь Daniel 
Gustafsson написал:

+ /*
  
+  * The width of the testname field when printing to ensure vertical 
alignment   
+  * of test runtimes. Thius number is somewhat arbitrarily chosen to match 
the   
+  * older pre-TAP output format.   
  
+  */

"Thius" seems to be a typo :-)

-

+ #define bail_noatexit(...)  bail_out(true, __VA_ARGS__)

BTW what does "noat" stands for? I thought it is typo too :-) and originally 
meant to be "not". 

-

-   snprintf(buf, sizeof(buf),
-_(" All %d tests passed. "),
-success_count);
-   else if (fail_count == 0)   /* fail_count=0, fail_ignore_count>0 */
-   snprintf(buf, sizeof(buf),
-_(" %d of %d tests passed, %d failed test(s) ignored. "),
-success_count,
-success_count + fail_ignore_count,
-fail_ignore_count);
-   else if (fail_ignore_count == 0)/* fail_count>0 && fail_ignore_count=0 
*/
-   snprintf(buf, sizeof(buf),
-_(" %d of %d tests failed. "),
-fail_count,
-success_count + fail_count);
+   note(_("All %d tests passed.\n"), success_count);
+   /* fail_count=0, fail_ignore_count>0 */
+   else if (fail_count == 0)
+   note(_("%d of %d tests passed, %d failed test(s) ignored.\n"),
+success_count,
+success_count + fail_ignore_count,
+fail_ignore_count);
+   /* fail_count>0 && fail_ignore_count=0 */
+   else if (fail_ignore_count == 0)
+   diag(_("%d of %d tests failed.\n"),
+fail_count,
+success_count + fail_count);
+   /* fail_count>0 && fail_ignore_count>0 */

Just out of overaccuracy:  Logic here have not changed. Can we keep ifs, elses 
and may be indent offsets of lines that did not change as they were to have 
nicer diff? Would make understanding this changeset more easy... Or this is 
work of pg_indent that spoils it?



While looking at the my output I am getting wrong offset for 
sanity_check:

ok 84   hash_func  121 ms
ok 85   errors  68 ms
ok 86   infinite_recurse   233 ms
ok 87sanity_check  144 ms
# parallel group (20 tests):  select_into delete random select_having 
select_distinct_on namespace select_implicit case prepared_xacts subselect 
transactions portals select_distinct union arrays update hash_index join 
aggregates btree_index
ok 88   select_into134 ms
ok 89   select_distinct812 ms

(also for select_parallel write_parallel vacuum_parallel and fast_default)

I guess the intention was to align them too...



As for the rest: I see no other problems in the code, and consider it should 
be passed to commiter (or may be more experienced reviewer)


> > On 24 Nov 2022, at 20:32, Andres Freund  wrote:
> > 
> > On November 24, 2022 11:07:43 AM PST, Daniel Gustafsson  
wrote:
> >>> On 24 Nov 2022, at 18:07, Nikolay Shaplov  wrote:
> >> One option could be to redefine bail() to take the exit function as a
> >> parameter and have the caller pass the preferred exit handler.
> >> 
> >> -bail_out(bool non_rec, const char *fmt,...)
> >> +bail(void (*exit_func)(int), const char *fmt,...)
> >> 
> >> The callsites would then look like the below, which puts a reference to
> >> the
> >> actual exit handler used in the code where it is called.
> > 
> > I'd just rename _bail to bail_noatexit().
> 
> That's probably the best option, done in the attached along with the comment
> fixup to mention the recursion issue.
> 
> >>> This magic spell "...%-5i %s%-*s %8.0f ms\n" is too dark to repeat it
> >>> even two times. I understand problems with spaces... But may be it
> >>> would be better somehow narrow it to one ugly print... Print "ok %-5i  
> >>>  "|"not ok %-5i" to buffer first, and then have one "%s%-*s %8.0f
> >>> ms%s\n" print or something like that...
> >> 
> >> I'm not convinced that this printf format is that hard to read (which may
> >> well be attributed to Stockholm Syndrome), and I do think that breaking
> >> it up and adding more code to print the line will make it less readable
> >> instead.> 
> > I don't think it's terrible either. I do think it'd also be ok to switch
> >

Re: TAP output format in pg_regress

2022-11-27 Thread Nikolay Shaplov
 91 ms
ok 11   types.oid 47 ms
ok 12   types.float4  88 ms
ok 13   types.float8 139 ms
ok 14   types.bit165 ms
ok 15   types.numeric   1065 ms


but this does not seems very realistic in the current code base and the scope 
of this path.

Theoretically TAP 14 has subtests and this parallel tests looks like 
subtests... but TAP 14 is not supported by modern harnesses..

So I have no idea...
May be leaving it as it is for now, is good enough...

-- 
Nikolay Shaplov aka Nataraj
Fuzzing Engineer at Postgres Professional
Matrix IM: @dhyan:nataraj.su


signature.asc
Description: This is a digitally signed message part.


Re: TAP output format in pg_regress

2022-11-28 Thread Nikolay Shaplov
В письме от понедельник, 28 ноября 2022 г. 21:28:48 MSK пользователь Andres 
Freund написал:
> On 2022-11-28 14:13:16 +0100, Daniel Gustafsson wrote:
> > > On 27 Nov 2022, at 11:22, Nikolay Shaplov  wrote:
> > > В письме от суббота, 26 ноября 2022 г. 23:35:45 MSK пользователь Daniel
> > > Gustafsson написал:
> > > 
> > > I wold suggest to use word immediate instead of noatexit. This will do
> > > the
> > > code much more sensible for me.
> > 
> > I think noatexit is clearer since the codepath is specifically to avoid
> > any
> > registered atexit functions.  The point of this function is to be able to
> > call bail while in a function registered with atexit() so I think the
> > current name is better.
> 
> +1

Ok, then I would not insist on it.

> > So this extra offset indicates that test is being included into parallel
> > group? Guess it not really obvious...
> 
> Grouping parallel tests via an initial list of test and then indenting each
> test with whitespace was committed 22 years ago.  While there might be
> better
> ways to do this, the lack of complaints so far at least seems to indicate
> that it isn't all too terrible.

Ok, it was there for 22 years, it will do no harm if it is left this way for 
some time :-)

----

From my reviewer's point of view patch is ready for commit.

Thank you for your patience :-)


PS Should I change commitfest status?

-- 
Nikolay Shaplov aka Nataraj
Fuzzing Engineer at Postgres Professional
Matrix IM: @dhyan:nataraj.su


signature.asc
Description: This is a digitally signed message part.


Re: [PATCH] New [relation] option engine

2023-02-01 Thread Nikolay Shaplov
В письме от среда, 1 февраля 2023 г. 12:04:26 MSK пользователь Alvaro Herrera 
написал:
> On 2023-Jan-31, vignesh C wrote:
> > On Tue, 3 Jan 2023 at 18:38, vignesh C  wrote:
> > > The patch does not apply on top of HEAD as in [1], please post a rebased
> > > patch: === Applying patches on top of PostgreSQL commit ID
> > > 92957ed98c5c565362ce665266132a7f08f6b0c0 ===
> > > === applying patch ./new_options_take_two_v03f.patch
> > > patching file src/include/access/reloptions.h
> > > Hunk #1 FAILED at 1.
> > > 1 out of 4 hunks FAILED -- saving rejects to file
> > > src/include/access/reloptions.h.rej
> > 
> > There has been no updates on this thread for some time, so this has
> > been switched as Returned with Feedback. Feel free to open it in the
> > next commitfest if you plan to continue on this.
> 
> Well, no feedback has been given, so I'm not sure this is a great
> outcome.  In the interest of keeping it alive, I've rebased it.  It
> turns out that the only conflict is with the 2022 -> 2023 copyright line
> update.
> 
> I have not reviewed it.
Guys sorry, I am totally unable to do just anything this month... Do not have 
spare resources to switch my attention to anything even this simple...

Hope, next month will be better... And I will try to do some more reviewing of 
other patches...

-- 
Nikolay Shaplov aka Nataraj
Fuzzing Engineer at Postgres Professional
Matrix IM: @dhyan:nataraj.su


signature.asc
Description: This is a digitally signed message part.


Re: [PATCH] Finally split StdRdOptions into HeapOptions and ToastOptions

2021-06-20 Thread Nikolay Shaplov
В письме от пятница, 4 июня 2021 г. 3:19:09 MSK пользователь Jeff Davis 
написал:

> > Moving reloptions to AM code is the goal I am slowly moving to. I've
> > started
> > some time ago with big patch
> > https://commitfest.postgresql.org/14/992/ and
> > have been told to split it into smaller parts. So I did, and this
> > patch is
> > last step that cleans options related things up, and then actual
> > moving can be
> > done.
> 
> Thank you for working on this.
Welcome!
Sorry for slow reply, I am on summer vacations now, no chance for fast replies 
now :-)

> Can you outline the plan for moving these options to the table AM to
> make sure this patch is a step in the right direction?

Yes, I can.  First you can see the whole patch, the way it was several years 
ago: https://commitfest.postgresql.org/15/992/, reloptions8a.diff
The things I would say is accurate for postgres ~11, it may have been changed 
since I last payed attention to them.

So, there are three general places where options can be stored:
1. Global boolRelOpts, intRelOpts, realRelOpts, stringRelOpts in src/backend/
access/common/reloptions.c for in-core access methods. 

2. custom_options array of  accessable via add_bool_reloption, 
add_int_reloption, add_real_reloption, add_string_reloption for access methods 
from contribs. (See reloptions.c too)

3. And also each access method has an array of relopt_parse_elt[]  that is 
also about reloptions. 

1 and 2 are technically arrays of relopt_get, and store information what kind 
of options do we have.

3 is array of relopt_parse_elt[] that store information how options should be 
stored into binary representation.

My idea was to merge relopt_get and relopt_parse_elt into one structure (in my 
patch it is "option_definition_basic"), each access method, that needs options, 
should have a set of option_definition_basic for their options (called 
option_definition_basic in my patch, may be should be renamed)

and this set of option_definitions is the only data that is needed to parse 
option into binary representation.

So in access method instead of am_option function we will have 
amrelopt_catalog function that returns "options defenition set" for this am, 
and this definition set is used by option parser to parse options.

So, it my explanation is not quite clear, please ask questions, I will try to 
answer them.

> I was trying to work through this problem as well[1], and there are a
> few complications.
> 
> * Which options apply to any relation (of any table AM), and which
> apply to only heaps? As far as I can tell, the only one that seems
> heap-specific is "fillfactor".

From my point of view, each relation kind has it's own set of options.
The fact, that almost every kind has a fillfactor is just a coincidence.
If we try to do some optimization here, we will be buried under the complexity 
of it soon.  So they are _different_ options just having the same name.

> * Toast tables can be any AM, as well, so if we accept new reloptions
> for a custom AM, we also need to accept options for toast tables of
> that AM.

When I wrote this patch, AM was introduced only to index relations. 
I do not how it is implemented for heap now, but there should be some logic in 
it. If toast tables has it's own AM, then option definition set should be 
stored there, and we should find a way to work with it, somehow.

> * Implementation-wise, the bytea representation of the options is not
> very easy to extend. Should we have a new text field in the catalog to
> hold the custom options?

I am not really understanding this question.

Normally all options can be well represented as binary structure stored at 
bytea. I see no problem here. If we need some unusual behaviour, we can use 
string option with custom validation function. This should cover almost all 
needs I can imagine.

===

So it you are interested in having better option implementation, and has no 
ideas of your own, I would suggest to revive my patch and try to commit it.
What I need first of all is a reviewer. Testing and coauthoring will also be 
apriciated.

My original big patch, I gave you link to, have been split into several parts.
The last minor part, that should be commit in advance, and have not been 
commit yet is https://commitfest.postgresql.org/33/2370/
If you join as a reviewer this would be splendid! :-)

-- 
Nikolay Shaplov 
dh...@nataraj.su (e-mail, jabber)  
@dhyan:nataraj.su (matrix)






Re: Zstandard support for toast compression

2022-05-19 Thread Nikolay Shaplov
В письме от вторник, 17 мая 2022 г. 23:01:07 MSK пользователь Tom Lane 
написал:

Hi! I came to this branch looking for a patch to review, but I guess I would 
join the discussion instead of reading the code.

> >> Yeah - I think we had better reserve the fourth bit pattern for
> >> something extensible e.g. another byte or several to specify the
> >> actual method, so that we don't have a hard limit of 4 methods. But
> >> even with such a system, the first 3 methods will always and forever
> >> be privileged over all others, so we'd better not make the mistake of
> >> adding something silly as our third algorithm.
> > 
> > In such a situation, would they really end up being properly distinct
> > when it comes to what our users see..?  I wouldn't really think so.
> 
> It should be transparent to users, sure, but the point is that the
> first three methods will have a storage space advantage over others.
> Plus we'd have to do some actual work to create that extension mechanism.

Postgres is well known for extensiblility. One can write your own 
implementation of almost everything and make it an extension.
Though one would hardly need more than one (or two) additional compression 
methods, but which method one will really need is hard to say. 

So I guess it would be much better to create and API for creating and 
registering own compression method and create build in Zstd compression method 
that can be used (or optionally not used) via that API.

Moreover I guess this API (may be with some modification) can be used for 
seamless data encryption, for example. 

So I guess it would be better to make it extensible from the start and use 
this precious bit for compression method chosen by user, and may be later 
extend it with another byte of compression method bits, if it is needed.

-- 
Nikolay Shaplov aka Nataraj
Fuzzing Engineer at Postgres Professional
Matrix IM: @dhyan:nataraj.su


signature.asc
Description: This is a digitally signed message part.


Re: Zstandard support for toast compression

2022-05-24 Thread Nikolay Shaplov
В письме от пятница, 20 мая 2022 г. 23:17:42 MSK пользователь Stephen Frost 
написал:

> While I generally agree that we want to provide extensibility in this
> area, given that we already have zstd as a compile-time option and it
> exists in other parts of the system, I don't think it makes sense to
> require users to install an extension to use it.
I mean that there can be Compression Method Provider, either built in postgres 
core, or implemented in extension. And one will need to create Compression 
method using desired Compression Method Provider. Like (it is just pure 
imagination) CREATE COMPRESSION METHOD MY_COMPRESSION USING 
'my_compression_provider'; This will assign certain bits combination to that 
method, and later one can use that method for TOAST compression...

> > Moreover I guess this API (may be with some modification) can be used for
> > seamless data encryption, for example.
> 
> Perhaps.. but this kind of encryption wouldn't allow indexing
Yes, this will require some more efforts. But for encrypting pure storage that 
API can be quite useful.

> and  certainly lots of other metadata would still be unencrypted (the entire
> system catalog being a good example..).
In many it is enough to encrypt only sensible information itself, not whole 
metadata.
My point was not to discuss DB encryption, it is quite complex issue, my point 
was to point out that API that allows custom compression methods may became 
useful for other solutions. Encryption was just first example that came in my 
mind. Robert Haas has another example for compression method optimized for 
certain data type. So it is good if you can have method of your own.


-- 
Nikolay Shaplov aka Nataraj
Fuzzing Engineer at Postgres Professional
Matrix IM: @dhyan:nataraj.su


signature.asc
Description: This is a digitally signed message part.


Re: [PATCH] minor reloption regression tests improvement

2022-06-29 Thread Nikolay Shaplov
В письме от четверг, 30 июня 2022 г. 00:38:48 MSK пользователь Jacob Champion 
написал:
> This patch is hanging open in the March commitfest. There was a bit of
> back-and-forth on whether it should be rejected, but no clear statement on
> the issue, so I'm going to mark it Returned with Feedback. If you still
> feel strongly about this patch, please feel free to re-register it in the
> July commitfest.

Hi! I am surely feel this patch is important. I have bigger patch 
https://commitfest.postgresql.org/38/3536/ and this test makes sense as a part 
of big work of options refactoring,

I am also was strongly advised to commit things chopped into smaller parts, 
when possible. This test can be commit separately so I am doing it.


-- 
Nikolay Shaplov aka Nataraj
Fuzzing Engineer at Postgres Professional
Matrix IM: @dhyan:nataraj.su


signature.asc
Description: This is a digitally signed message part.


Re: [PATCH] minor reloption regression tests improvement

2022-06-29 Thread Nikolay Shaplov
В письме от четверг, 30 июня 2022 г. 06:47:48 MSK пользователь Nikolay Shaplov 
написал:
 
> Hi! I am surely feel this patch is important. I have bigger patch
> https://commitfest.postgresql.org/38/3536/ and this test makes sense as a
> part of big work of options refactoring,
> 
> I am also was strongly advised to commit things chopped into smaller parts,
> when possible. This test can be commit separately so I am doing it.

Let me again explain why this test is importaint, so potential reviewers can 
easily find this information.

Tests are for developers. You change the code and see that something does not 
work anymore, as it worked before.
When you change the code, you should keep both documented and undocumented 
behaviour. Because user's code can intentionally  or accidentally use it. 

So known undocumented behavior is better to be tested as well as documented 
one. If you as developer want to change undocumented behavior, it is better to 
do it consciously. This test insures that.

I, personally hit this problem while working with reloption code. Older 
version of my new patch changed this behaviour, and I even did not notice 
that. So I decided to write this test to ensure, that nobody ever meet same 
problem. 

And as I said before, I was strongly advised to commit in small parts, when 
possible. This test can be commit separately.  

-- 
Nikolay Shaplov aka Nataraj
Fuzzing Engineer at Postgres Professional
Matrix IM: @dhyan:nataraj.su


signature.asc
Description: This is a digitally signed message part.


Re: [PATCH] New [relation] option engine

2022-07-11 Thread Nikolay Shaplov
В письме от понедельник, 11 июля 2022 г. 23:03:55 MSK пользователь Jeff Davis 
написал:

> > For index access methods "amoptions" member function that preformed
> > option
> > processing, were replaced with "amreloptspecset" member function that
> > provided
> > an SpecSet for reloptions for this AM, so caller can trigger option
> > processing
> > himself.
> 
> What about table access methods? There have been a couple attempts to
> allow custom reloptions for table AMs. Does this patch help that use
> case?

This patch does not add custom reloptions for table AM. It is already huge 
enough, with no extra functionality. But new option engine will make adding 
custom options for table AM more easy task, as main goal of this patch is to 
simplify adding options everywhere they needed. And yes, adding custom table 
AM options is one of my next goals, as soon as this patch is commit.

-- 
Nikolay Shaplov aka Nataraj
Fuzzing Engineer at Postgres Professional
Matrix IM: @dhyan:nataraj.su


signature.asc
Description: This is a digitally signed message part.


Re: Bug: Reading from single byte character column type may cause out of bounds memory reads.

2022-07-14 Thread Nikolay Shaplov
В письме от среда, 13 июля 2022 г. 16:14:39 MSK пользователь Aleksander 
Alekseev написал:

Hi! Let me join the review process. Postgres data types is field of expertise I 
am interested in.

0. Though it looks like a steady bug, I can't reproduce it. Not using 
valgrind, not using ASan (address sanitizer should catch reading out of bounds 
too). I am running Debian Bullseye, and tried to build both postgresl 14.4 and 
current master.

Never the less I would dig into this issue. And start with the parts that is 
not covered by the patch, but seems to be important for me.

1. typename "char" (with quotes) is very-very-very confusing. it is described 
in documentation, but you need to be postgres expert or careful documentation 
reader, to notice important difference between "char" and char. 
What is the history if "char" type? Is it specified by some standard? May be it 
is good point to create more understandable alias, like byte_char, ascii_char 
or something for usage in practice, and keep "char" for backward compatibility 
only.

2. I would totally agree with  Tom Lane and Isaac Morland, that problem should 
be also fixed  on the side of type conversion.  There is whole big thread about 
it. Guess we should come to some conclusion there

3.Fixing out of bound reading for broken unicode is also important.  Though 
for now I am not quite sure it is possible.


> - p += pg_mblen(p);
> + {
> + int t = pg_mblen(p);
> + p += t;
> + max_copy_bytes -= t;
> + }

Minor issue: Here I would change variable name from "t" to "char_len" or 
something, to make code more easy to understand.

Major issue: is pg_mblen function safe to call with broken encoding at the end 
of buffer? What if last byte of the buffer is 0xF0 and you call pg_mblen for it?


>+  copy_bytes = p - s;
>+  if(copy_bytes > max_copy_bytes)
>+  copy_bytes = max_copy_bytes;

Here I would suggest to add comment about broken utf encoding case. That would 
explain why we might come to situation when we can try to copy more than we 
have.

I would also suggest to issue a warning here. I guess person that uses 
postgres would prefer to know that he managed to stuff into postgres a string 
with broken utf encoding, before it comes to some terrible consequences.  

> Hi Spyridon,
> 
> > The column "single_byte_col" is supposed to store only 1 byte.
> > Nevertheless, the INSERT command implicitly casts the '🀆' text into
> > "char". This means that only the first byte of '🀆' ends up stored in the
> > column. gdb reports that "pg_mblen(p) = 4" (line 1046), which is expected
> > since the pg_mblen('🀆') is indeed 4. Later at line 1050, the memcpy will
> > copy 4 bytes instead of 1, hence an out of bounds memory read happens for
> > pointer 's', which effectively copies random bytes.
> Many thanks for reporting this!
> 
> > - OS: Ubuntu 20.04
> > - PSQL version 14.4
> 
> I can confirm the bug exists in the `master` branch as well and
> doesn't depend on the platform.
> 
> Although the bug is easy to fix for this particular case (see the
> patch) I'm not sure if this solution is general enough. E.g. is there
> something that generally prevents pg_mblen() from doing out of bound
> reading in cases similar to this one? Should we prevent such an INSERT
> from happening instead?


-- 
Nikolay Shaplov aka Nataraj
Fuzzing Engineer at Postgres Professional
Matrix IM: @dhyan:nataraj.su


signature.asc
Description: This is a digitally signed message part.


Re: The "char" type versus non-ASCII characters

2022-07-16 Thread Nikolay Shaplov
В письме от пятница, 3 декабря 2021 г. 22:12:10 MSK пользователь Tom Lane 
написал:
> which
> is that the "char" type is not very encoding-safe.  charout() for
> example just regurgitates the single byte as-is.  I think we deemed
> that okay the last time anyone thought about it, but that was when
> single-byte encodings were the mainstream usage for non-ASCII data.
> If you're using UTF8 or another multi-byte server encoding, it's
> quite easy to get an invalidly-encoded string this way, which at
> minimum is going to break dump/restore scenarios.

As I've mentioned in another thread I've been very surprised when I first  saw 
"char" type name. And I was also very confused.

This leads me to an idea that may be as we fix "char" behaviour, we should also 
change it's name to something more speaking for itself. Like ascii_char or 
something like that.
Or better to add ascii_char with behaviour we need, update system tables with 
it, and keep "char" with old behaviour in "deprecated" status in the case 
somebody still using it. To give them time to change it to something more 
decent: ascii_char or char(1).

I've also talked to a guy who knows postgres history very well, he told me 
that "char" existed at least from portgres version 3.1, it also had "char16", 
and in v.4  "char2", "char4", "char8" were added. But later on they was all 
removed, and we have only "char".

Aslo "char" has nothing in common with SQL standard. Actually it looks very 
unnaturally.  May be it is time to get rid of it too, if we are changing this 
part of code...

> I can think of at least three ways we might address this:
> 
> * Forbid all non-ASCII values for type "char".  This results in
> simple and portable semantics, but it might break usages that
> work okay today.
> 
> * Allow such values only in single-byte server encodings.  This
> is a bit messy, but it wouldn't break any cases that are not
> problematic already.
> 
> * Continue to allow non-ASCII values, but change charin/charout,
> char_text, etc so that the external representation is encoding-safe
> (perhaps make it an octal or decimal number).

This will give us steady #1 for ascii_char, and deprecation and removal of 
"char" later on.

-- 
Nikolay Shaplov aka Nataraj
Fuzzing Engineer at Postgres Professional
Matrix IM: @dhyan:nataraj.su


signature.asc
Description: This is a digitally signed message part.


Re: [PATCH] Finally split StdRdOptions into HeapOptions and ToastOptions

2021-07-22 Thread Nikolay Shaplov
В письме от среда, 14 июля 2021 г. 15:09:12 MSK пользователь vignesh C 
написал:
> The patch does not apply on Head anymore, could you rebase and post a
> patch. I'm changing the status to "Waiting for Author".

Thank you for notification. 

I've tried to rebase it and found out that some options have been added to 
partitioned table.
Handling this needs careful approach, and I will fix it two weeks later, when I 
am back from vacations.


Meanwhile I would strongly suggest to change

{"vacuum_index_cleanup", RELOPT_TYPE_BOOL,

to 

{"vacuum_index_cleanup", RELOPT_TYPE_ENUM,

in src/backend/access/common/reloptions.c

This change should be done in 3499df0d
But current implementation of reloptions is very error prone , and it is very 
easy to miss this part.



-- 
Nikolay Shaplov 
dh...@nataraj.su (e-mail, jabber)  
@dhyan:nataraj.su (matrix)






Re: POC, WIP: OR-clause support for indexes

2024-06-24 Thread Nikolay Shaplov
Hi!

Let me join the review process.

I am no expert in execution plans, so there would not be much help in doing 
even better optimization. But I can read the code, as a person who is not 
familiar 
with this area and help making it clear even to a person like me.

So, I am reading v25-0001-Transform-OR-clauses-to-ANY-expression.patch that 
have been posted some time ago, and especially transform_or_to_any function.

> @@ -38,7 +45,6 @@
>  int  from_collapse_limit;
>  int  join_collapse_limit;
>
> - 
>  /*
>   * deconstruct_jointree requires multiple passes over the join tree,  
> because we 
>   * need to finish computing JoinDomains before we start  distributing quals.

Do not think that removing empty line should be part of the patch

> + /*
> +  * If the const node's (right side of operator 
> expression) type
> +  * don't have “true” array type, then we cannnot do 
> the
> +  * transformation. We simply concatenate the expression 
> node.
> +  */
Guess using unicode double quotes is not the best idea here... 
   
Now to the first part of  `transform_or_to_any`


signature.asc
Description: This is a digitally signed message part.


Re: POC, WIP: OR-clause support for indexes

2024-06-24 Thread Nikolay Shaplov
Hi!

Let me join the review process.

I am no expert in execution plans, so there would not be much help in doing 
even better optimization. But I can read the code, as a person who is not 
familiar 
with this area and help making it clear even to a person like me.

So, I am reading v25-0001-Transform-OR-clauses-to-ANY-expression.patch that 
have been posted some time ago, and especially transform_or_to_any function.

> @@ -38,7 +45,6 @@
>  int  from_collapse_limit;
>  int  join_collapse_limit;
>
> - 
>  /*
>   * deconstruct_jointree requires multiple passes over the join tree,  
because we 
>   * need to finish computing JoinDomains before we start  distributing quals.

Do not think that removing empty line should be part of the patch

> + /*
> +  * If the const node's (right side of operator 
expression) type
> +  * don't have “true” array type, then we cannnot 
do the
> +  * transformation. We simply concatenate the 
expression node.
> +  */
Guess using unicode double quotes is not the best idea here... 
   
Now to the first part of  `transform_or_to_any`:

> + List   *entries = NIL;
I guess the idea of entries should be explained from the start. What kind of 
entries are accomulated there... I see they are added there all around the 
code, but what is the purpose of that is not quite clear when you read it.

At the first part of `transform_or_to_any` function, you costanly repeat two 
lines, like a mantra:

> + entries = lappend(entries, rinfo);
> + continue;

"If something is wrong -- do that mantra"

From my perspective, if you have to repeat same code again and again, then 
most probably you have some issues with architecture of the code. If you 
repeat some code again and again, you need to try to rewrite the code, the 
way, that part is repeated only once.

In that case I would try to move the most of the first loop of 
`transform_or_to_any`  to a separate function (let's say its name is 
prepare_single_or), that will do all the checks, if this or is good for us; 
return NULL if it does not suits our purposes (and in this case we do "entries 
= lappend(entries, rinfo); continue" in the main code, but only once) or 
return pointer to some useful data if this or clause is good for our purposes. 

This, I guess will make that part more clear and easy to read, without 
repeating same "lappend mantra" again and again.

Will continue digging into the code tomorrow.

P.S. Sorry for sending partly finished email. Pressed Ctrl+Enter 
accidentally... With no way to make it back :-((( 

signature.asc
Description: This is a digitally signed message part.


Re: POC, WIP: OR-clause support for indexes

2024-06-26 Thread Nikolay Shaplov
В письме от понедельник, 24 июня 2024 г. 23:51:56 MSK пользователь Nikolay 
Shaplov написал:

So,  I continue reading the patch.

I see there is `entries` variable in the code, that is the list of 
`RestrictInfo` objects and `entry` that is `OrClauseGroup` object.

This naming is quite misguiding (at least for me).

 `entries` variable name can be used, as we deal only with RestrictInfo 
entries here. It is kind of "generic" type. Though naming it 
`restric_info_entry` might make te code more readable.

But when we come to an `entry` variable, it is very specific entry, it should 
be `OrClauseGroup` entry, not just any entry. So I would suggest to name this 
variable `or_clause_group_entry`, or even `or_clause_group` , so when we meet 
this variable in the middle of the code, we can get the idea what we are 
dealing with, without scrolling code up.

Variable naming is very important thing. It can drastically improve (or ruin) 
code readability.



Also I see some changes in the tests int this patch. There are should be tests 
that check that this new feature works well. And there are test whose behavior 
have been just accidentally affected.

I whould suggest to split these tests into two patches, as they should be 
reviewed in different ways. Functionality tests should be thoroughly checked 
that all stuff we added is properly tested, and affected tests should be 
checked 
that nothing important is not broken. It would be more easy to check if these 
are two different patches.

I would also suggest to add to the commit message of affected tests changes 
some explanation why this changes does not really breaks anything. This will 
do the checking more simple.

To be continued.

-- 
Nikolay Shaplov aka Nataraj
Fuzzing Engineer at Postgres Professional
Matrix IM: @dhyan:nataraj.su


signature.asc
Description: This is a digitally signed message part.


Re: POC, WIP: OR-clause support for indexes

2024-07-21 Thread Nikolay Shaplov
В письме от среда, 17 июля 2024 г. 22:36:19 MSK пользователь Alexander 
Korotkov написал:

Hi All!

I am continue reading the patch, now it's newer version

First main question:

As far a I can get, the entry point for OR->ANY convertation have been moved 
to match_clause_to_indexcol funtion, that checks if some restriction can use 
index for performance.

The thing I do not understand what match_clause_to_indexcol actually received 
as arguments. Should this be set of expressions  with OR in between grouped by 
one of the expression argument?

If not I do not understand how this ever should work.

The rest is about code readability

> + if (bms_is_member(index->rel->relid, rinfo->right_relids))
> + return NULL;

This check it totally not obvious for person who is not deep into postgres 
code. There should go comment explaining what are we checking for, and why it 
does not suit our purposes


> + foreach(lc, orclause->args)
> + {
Being no great expert in postgres code, I am confused what are we iterating on 
here? Two arguments of OR statement? (a>1) OR (b>2) those in brackets? Or 
what? Comment explaining that would be a great help here.


> +if (sub_rinfo->is_pushed_down != rinfo->is_pushed_down ||
> + sub_rinfo->is_clone != rinfo->is_clone ||
> + sub_rinfo->security_level != rinfo->security_level ||
> + !bms_equal(sub_rinfo->required_relids, rinfo->required_relids) ||
> + !bms_equal(sub_rinfo->incompatible_relids, rinfo- 
incompatible_relids) ||
> + !bms_equal(sub_rinfo->outer_relids, rinfo->outer_relids))
> + { 

This check it totally mind-blowing... What in the name of existence is going 
on here?

I would suggest  to split these checks into parts (compiler optimizer should 
take care about overhead)  and give each part a sane explanation.

-- 
Nikolay Shaplov aka Nataraj
Fuzzing Engineer at Postgres Professional
Matrix IM: @dhyan:nataraj.su


signature.asc
Description: This is a digitally signed message part.


Re: [PATCH] Finally split StdRdOptions into HeapOptions and ToastOptions

2020-07-03 Thread Nikolay Shaplov
В письме от четверг, 2 июля 2020 г. 17:15:13 MSK пользователь Daniel 
Gustafsson написал:

> > A new version of the patch.
> > Autovacuum options were extended in b07642db
> > 
> > So I added that options to the current patch.
> 
> The heapam.c hunk in this version fails to apply to HEAD, can you please
> submit a rebased version?  
Thanks for reminding about it.

Here goes a rebased version.


-- 
Software Developer: https://www.upwork.com/freelancers/~014a87e140ff02c0da
Body-oriented Therapist: https://vk.com/nataraj_rebalancing  (Russian)diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c
index 8ccc228..6118b55 100644
--- a/src/backend/access/common/reloptions.c
+++ b/src/backend/access/common/reloptions.c
@@ -46,9 +46,8 @@
  * upper and lower bounds (if applicable); for strings, consider a validation
  * routine.
  * (ii) add a record below (or use add__reloption).
- * (iii) add it to the appropriate options struct (perhaps StdRdOptions)
- * (iv) add it to the appropriate handling routine (perhaps
- * default_reloptions)
+ * (iii) add it to the appropriate options struct
+ * (iv) add it to the appropriate handling routine
  * (v) make sure the lock level is set correctly for that operation
  * (vi) don't forget to document the option
  *
@@ -1375,9 +1374,11 @@ extractRelOptions(HeapTuple tuple, TupleDesc tupdesc,
 	switch (classForm->relkind)
 	{
 		case RELKIND_RELATION:
-		case RELKIND_TOASTVALUE:
 		case RELKIND_MATVIEW:
-			options = heap_reloptions(classForm->relkind, datum, false);
+			options = heap_reloptions(datum, false);
+			break;
+		case RELKIND_TOASTVALUE:
+			options = toast_reloptions(datum, false);
 			break;
 		case RELKIND_PARTITIONED_TABLE:
 			options = partitioned_table_reloptions(datum, false);
@@ -1811,59 +1812,66 @@ fillRelOptions(void *rdopts, Size basesize,
 
 
 /*
- * Option parser for anything that uses StdRdOptions.
+ * Option parsing definition for autovacuum. Used in toast and heap options.
+ */
+
+#define AUTOVACUUM_RELOPTIONS(OFFSET)\
+		{"autovacuum_enabled", RELOPT_TYPE_BOOL, \
+		OFFSET + offsetof(AutoVacOpts, enabled)},\
+		{"autovacuum_vacuum_threshold", RELOPT_TYPE_INT, \
+		OFFSET + offsetof(AutoVacOpts, vacuum_threshold)},   \
+		{"autovacuum_vacuum_insert_threshold", RELOPT_TYPE_INT,  \
+		OFFSET + offsetof(AutoVacOpts, vacuum_ins_threshold)},   \
+		{"autovacuum_analyze_threshold", RELOPT_TYPE_INT,\
+		OFFSET + offsetof(AutoVacOpts, analyze_threshold)},  \
+		{"autovacuum_vacuum_cost_delay", RELOPT_TYPE_REAL,   \
+		OFFSET + offsetof(AutoVacOpts, vacuum_cost_delay)},  \
+		{"autovacuum_vacuum_cost_limit", RELOPT_TYPE_INT,\
+		OFFSET + offsetof(AutoVacOpts, vacuum_cost_limit)},  \
+		{"autovacuum_freeze_min_age", RELOPT_TYPE_INT,   \
+		OFFSET + offsetof(AutoVacOpts, freeze_min_age)}, \
+		{"autovacuum_freeze_max_age", RELOPT_TYPE_INT,   \
+		OFFSET + offsetof(AutoVacOpts, freeze_max_age)}, \
+		{"autovacuum_freeze_table_age", RELOPT_TYPE_INT, \
+		OFFSET + offsetof(AutoVacOpts, freeze_table_age)},   \
+		{"autovacuum_multixact_freeze_min_age", RELOPT_TYPE_INT, \
+		OFFSET + offsetof(AutoVacOpts, multixact_freeze_min_age)},   \
+		{"autovacuum_multixact_freeze_max_age", RELOPT_TYPE_INT, \
+		OFFSET + offsetof(AutoVacOpts, multixact_freeze_max_age)},   \
+		{"autovacuum_multixact_freeze_table_age", RELOPT_TYPE_INT,   \
+		OFFSET + offsetof(AutoVacOpts, multixact_freeze_table_age)}, \
+		{"log_autovacuum_min_duration", RELOPT_TYPE_INT, \
+		OFFSET + offsetof(AutoVacOpts, log_min_duration)},   \
+		{"autovacuum_vacuum_scale_factor", RELOPT_TYPE_REAL, \
+		OFFSET + offsetof(AutoVacOpts, vacuum_scale_factor)},\
+		{"autovacuum_vacuum_insert_scale_factor", RELOPT_TYPE_REAL,  \
+		OFFSET  + offsetof(AutoVacOpts, vacuum_ins_scale_factor)},   \
+		{"autovacuum_analyze_scale_factor", RELOPT_TYPE_REAL,\
+		OFFSET + offsetof(AutoVacOpts, analyze_scale_factor)}
+/*
+ * Option parser for heap
  */
 bytea *
-default_reloptions(Datum reloptions, bool validate, relopt_kind kind)
+heap_reloptions(Datum reloptions, bool validate)
 {
 	static const relopt_parse_elt tab[] = {
-		{"fillfactor", RELOPT_TYPE_INT, offsetof(StdRdOptions, fillfactor)},
-		{"autovacuum_enabled", RELOPT_TYPE_BOOL,
-		offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, enabled)},
-		{"autovacuum_vacuum_threshold", RELOPT_TYPE_INT,
-		offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, vacuum_threshold)},
-		{"autovacuum_vacuum_insert_threshold", RELOPT_TYPE_INT,
-		offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, vacuum_ins_threshold)},
-		{"autovacuum_analyze_threshold", RELOPT_TYPE_INT,
-		offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, analyze_threshold)},
-

Re: [PATCH] get rid of StdRdOptions, use individual binary reloptions representation for each relation kind instead

2019-01-20 Thread Nikolay Shaplov
В письме от четверг, 17 января 2019 г. 20:33:06 MSK пользователь Alvaro 
Herrera написал:

> You introduced new macros IsHeapRelation and IsViewRelation, but I don't
> want to introduce such API.  Such things have been heavily contested and
> I don't to have one more thing to worry about for this patch, so please
> just put the relkind directly in the code.
Sorry.
I've been trying to avoid repeating

   (AssertMacro(relation->rd_rel->relkind == RELKIND_RELATION ||   \   
relation->rd_rel->relkind == RELKIND_MATVIEW), \  
all the time.

Fixed.

Also I make more relaxed parallel_workers behavior in get_relation_info as we 
discussed in another thread.diff --git a/src/backend/access/common/reloptions.c b/src/backend/access/common/reloptions.c
index cdf1f4a..b1fd67c 100644
--- a/src/backend/access/common/reloptions.c
+++ b/src/backend/access/common/reloptions.c
@@ -22,7 +22,7 @@
 #include "access/htup_details.h"
 #include "access/nbtree.h"
 #include "access/reloptions.h"
-#include "access/spgist.h"
+#include "access/spgist_private.h"
 #include "access/tuptoaster.h"
 #include "catalog/pg_type.h"
 #include "commands/defrem.h"
@@ -46,9 +46,8 @@
  * upper and lower bounds (if applicable); for strings, consider a validation
  * routine.
  * (ii) add a record below (or use add__reloption).
- * (iii) add it to the appropriate options struct (perhaps StdRdOptions)
- * (iv) add it to the appropriate handling routine (perhaps
- * default_reloptions)
+ * (iii) add it to the appropriate options struct
+ * (iv) add it to the appropriate handling routine
  * (v) make sure the lock level is set correctly for that operation
  * (vi) don't forget to document the option
  *
@@ -1010,7 +1009,7 @@ extractRelOptions(HeapTuple tuple, TupleDesc tupdesc,
 		case RELKIND_TOASTVALUE:
 		case RELKIND_MATVIEW:
 		case RELKIND_PARTITIONED_TABLE:
-			options = heap_reloptions(classForm->relkind, datum, false);
+			options = relation_reloptions(classForm->relkind, datum, false);
 			break;
 		case RELKIND_VIEW:
 			options = view_reloptions(datum, false);
@@ -1343,63 +1342,69 @@ fillRelOptions(void *rdopts, Size basesize,
 
 
 /*
- * Option parser for anything that uses StdRdOptions.
+ * Option parsing definition for autovacuum. Used in toast and heap options.
+ */
+
+#define AUTOVACUUM_RELOPTIONS(OFFSET)\
+		{"autovacuum_enabled", RELOPT_TYPE_BOOL, \
+		OFFSET + offsetof(AutoVacOpts, enabled)},\
+		{"autovacuum_vacuum_threshold", RELOPT_TYPE_INT, \
+		OFFSET + offsetof(AutoVacOpts, vacuum_threshold)},   \
+		{"autovacuum_analyze_threshold", RELOPT_TYPE_INT,\
+		OFFSET + offsetof(AutoVacOpts, analyze_threshold)},  \
+		{"autovacuum_vacuum_cost_delay", RELOPT_TYPE_INT,\
+		OFFSET + offsetof(AutoVacOpts, vacuum_cost_delay)},  \
+		{"autovacuum_vacuum_cost_limit", RELOPT_TYPE_INT,\
+		OFFSET + offsetof(AutoVacOpts, vacuum_cost_limit)},  \
+		{"autovacuum_freeze_min_age", RELOPT_TYPE_INT,   \
+		OFFSET + offsetof(AutoVacOpts, freeze_min_age)}, \
+		{"autovacuum_freeze_max_age", RELOPT_TYPE_INT,   \
+		OFFSET + offsetof(AutoVacOpts, freeze_max_age)}, \
+		{"autovacuum_freeze_table_age", RELOPT_TYPE_INT, \
+		OFFSET + offsetof(AutoVacOpts, freeze_table_age)},   \
+		{"autovacuum_multixact_freeze_min_age", RELOPT_TYPE_INT, \
+		OFFSET + offsetof(AutoVacOpts, multixact_freeze_min_age)},   \
+		{"autovacuum_multixact_freeze_max_age", RELOPT_TYPE_INT, \
+		OFFSET + offsetof(AutoVacOpts, multixact_freeze_max_age)},   \
+		{"autovacuum_multixact_freeze_table_age", RELOPT_TYPE_INT,   \
+		OFFSET + offsetof(AutoVacOpts, multixact_freeze_table_age)}, \
+		{"log_autovacuum_min_duration", RELOPT_TYPE_INT, \
+		OFFSET + offsetof(AutoVacOpts, log_min_duration)},   \
+		{"autovacuum_vacuum_scale_factor", RELOPT_TYPE_REAL, \
+		OFFSET + offsetof(AutoVacOpts, vacuum_scale_factor)},\
+		{"autovacuum_analyze_scale_factor", RELOPT_TYPE_REAL,\
+		OFFSET + offsetof(AutoVacOpts, analyze_scale_factor)}
+
+/*
+ * Option parser for heap
  */
 bytea *
-default_reloptions(Datum reloptions, bool validate, relopt_kind kind)
+heap_reloptions(Datum reloptions, bool validate)
 {
 	relopt_value *options;
-	StdRdOptions *rdopts;
+	HeapRelOptions *rdopts;
 	int			numoptions;
 	static const relopt_parse_elt tab[] = {
-		{"fillfactor", RELOPT_TYPE_INT, offsetof(StdRdOptions, fillfactor)},
-		{"autovacuum_enabled", RELOPT_TYPE_BOOL,
-		offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, enabled)},
-		{"autovacuum_vacuum_threshold", RELOPT_TYPE_INT,
-		offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, vacuum_threshold)},
-		{"autovacuum_analyze_threshold", RELOPT_TYPE_INT,
-		offsetof(StdRdOptions, autovacuum) + offsetof(AutoVacOpts, analyze_threshold)},
-		{"autovacuum_

Re: Ltree syntax improvement

2019-02-05 Thread Nikolay Shaplov
В письме от вторник, 29 января 2019 г. 20:43:07 MSK пользователь Dmitry 
Belyavsky написал:

> Please find attached the patch extending the sets of symbols allowed in
> ltree labels. The patch introduces 2 variants of escaping symbols, via
> backslashing separate symbols and via quoting the labels in whole for
> ltree, lquery and ltxtquery datatypes.

Hi!

Let's me join the review process...

I've just give a superficial look to the patch, read it through, and try  here 
and there, so first I'll give feedback about exterior features of the patch.

So, the first question: why do we need all this? The answer seems to be 
obvious, but it would be good say it explicitly. What problems would it solve? 
Do these problems really exists? 

The second question is about coding style. As far as I can see you've passed 
your code through pg_indent, but it does not solve all problems.

As far as I know, postgres commiters are quite strict about code width, the 
code should not be wider that 80 col, except places were string constants are 
introduced (There you can legally exceed 80 col). So I would advice to use vim 
with  tabstop=4  and colorcolumn=80 and make sure that new code text does not 
cross red vertical line. 

Comments. There is no fixed coding style for comments in postgres. Usually this 
means that it is better to follow coding in the code around. But ltree does 
not have much comments, so I would suggest to use the best style I've seen in 
the code
/*
 * [function name]
 * < tab > [Short description, what does it do]
 * 
 * [long explanation how it works, several subparagraph if needed
 */
(Seen this in src/include/utils/rel.h)
or something like that.
At least it would be good to have explicit separation between descriptions and 
explanation of how it works.

And about comment
/*
 * Function calculating bytes to escape
 * to_escape is an array of "special" 1-byte symbols
 * Behvaiour:
 * If there is no "special" symbols, return 0
 * If there are any special symbol, we need initial and final quote, so return 
2
 * If there are any quotes, we need to escape all of them and also initial and 
final quote, so
 * return 2 + number of quotes
 */

It has some formatting. But it should not.  As far as I understand this 
comment should be treated as single paragraph by reformatter, and refomatted. 
I do not understand why pg_indent have not done it. Documentation (https://
www.postgresql.org/docs/11/source-format.html) claims that if you want to 
avoid reformatting, you should add "-" at the beginning and at the 
end of the comment. So it would be good either remove this formatting, or add 
"" if you are sure you want to keep it.

Third part is about error messages.
First I've seen errors like elog(ERROR, "internal error during splitting 
levels");. I've never seen error like that in postgres. May be if this error 
is in the part of the code, that should never be reached in real live, may be 
it would be good to change it to Assert? Or if this code can be normally 
reached, add some more explanation of what had happened...

About other error messages.

There are messages like 
errmsg("syntax error"),
errdetail("Unexpected end of line.")));

or

errmsg("escaping syntax error")));


In postgres there is error message style guide 
https://www.postgresql.org/docs/11/error-style-guide.html

Here I would expect messages like that

Primary:Error parsing ltree path
Detail: Curly quote is opened and not closed

Or something like that, I am not expert in English, but this way it would be 
better for sure. Key points are: Primary message should point to general area 
where error occurred (there can be a large SQL with a lot of things in it, so 
it is good to point that problem is with ltree staff). And is is better to 
word from the point of view of a user. What for you (and me) is unexpected end 
of line, for him it is unclosed curly quote. 

Also I am not sure, if it is easy, but if it is possible, it would be good to 
move "^" symbol that points to the place of the error, to the place inside ' ' 
where unclosed curly quote is located. As a user I would appreciate that.

So that's what I've seen while giving it superficial look...




Re: [PATCH][PROPOSAL] Add enum releation option type

2019-02-19 Thread Nikolay Shaplov
В письме от среда, 20 февраля 2019 г. 15:08:32 MSK пользователь Michael 
Paquier написал:
> On Sun, Jan 06, 2019 at 06:28:11PM +0300, Nikolay Shaplov wrote:
> > Actually I am not satisfied with it too... That is why I started that
> > bigger reloptions refactoring work. So for now I would offer to keep
> > initialization as it was for other types: in initialize_reloptions  using
> > [type]RelOpts[] arrays. And then I will offer patch that changes it for
> > all types and remove difference between biult-in reloptions and
> > reloptions in extensions.
> Should this be switched as waiting on author or just marked as
> returned with feedback then?
Actually I would prefer "Commited" ;-)

And speaking seriously... Anyway, this test module in src/test/modules should 
be a separate patch, as it would test that all types of options are properly 
reaching index extension, not only enum.

From my point of view, it can be committed without any dependency with enum 
reloption. Either we first commit this patch, and then that test module will 
test that enum support, or first we commit that test moudule without testing 
enum support, and add tests into this enum patch.

I would prefer to commit enum first, and I would promise that I will add thus 
module to the top of my dev TODO list. If it is not ok for you, then please 
tell me about it and set this patch as "Waiting for author" and I will do the 
test patch first.

> > 2.5  May be this src/test/modules dummy index is subject to another patch.
> > So I will start working on it right now, but we will do this work not
> > dependent to any other patches. And just add there what we need when it
> > is ready. I would actually add there some code that checks all types of
> > options, because we actually never check that option value from reloptons
> > successfully reaches extension code. I did this checks manually, when I
> > wrote that bigger reloption patch, but there is no facilities to do
> > regularly check is via test suit. Creating dummy index will create such
> > facilities.
> 
> bloom is a user-facing extension, while src/test/modules are normally
> not installed (there is an exception for MSVC anyway..), so stressing
> add_enum_reloption in src/test/modules looks more appropriate to me,
> except if you can define an option which is useful for the user and is
> an enum.
Thank you for pointing me right direction. 've been waiting for it. Now I can 
go on :)) So let's it be src/test/modules module...





Re: Ltree syntax improvement

2019-02-20 Thread Nikolay Shaplov
В письме от вторник, 29 января 2019 г. 20:43:07 MSK пользователь Dmitry 
Belyavsky написал:
> Dear all,
> 
> Please find attached the patch extending the sets of symbols allowed in
> ltree labels. The patch introduces 2 variants of escaping symbols, via
> backslashing separate symbols and via quoting the labels in whole for
> ltree, lquery and ltxtquery datatypes.

Sorry I still did not do full revision, I've stumbled up on other things in 
the code, which, as I think should be fixed before final checking through. (I 
guess that code do what is expected, since it passes tests and so on, it needs 
recheck, but I'd like to do this full recheck only once)

So my doubts about this code is that a lot parts of code is just a copy-paste 
of the same code that was written right above. And it can be rewritten in a 
way that the same lines (or parts of lines) is repeated only once...
This should make code more readable, and make code more similar to the code of 
postgres core, I've seen.

Here I will speak about lquery_in function from ltree_io.c.

1. May be it is better here to switch from else if (state == 
LQPRS_[something]) to switch (stat) { case LQPRS_[something]: }
because because here the main case is to determine what is the current state 
of your state machine, do something with it, and then go to the next step. 

Now after you've done what should be done in this step, you should make sure 
that no other code is executed writing more ifs... If you use switch/case you 
will be able to say break wherever you like, it will save you some ifs.

Theoretical example

(cl is for character length fc is for fist char)

if (cl==1 && fc =='1') {do_case1();}
else if (cl==1 && fc =='2') {do_case2();}
else if (cl==1 && fc =='3') {do_case3();}
else {do_otherwise();}

If it is wrapped in switch/case it will be like

if (cl==1)
{
  if (fc =='1') {do_case1(); break;}
  if (fc =='2') {do_case2(); break;}
  if (fc =='3') {do_case3(); break;}
}
/*if nothing is found */
do_otherwise();

This for example will allow you to get rid of multiply charlen == 1 checks in 

else if ((lptr->flag & LVAR_QUOTEDPART) == 0)   


{   


if (charlen == 1 && t_iseq(ptr, '@'))   


{   


if (lptr->start == ptr) 


UNCHAR; 


lptr->flag |= LVAR_INCASE;  


curqlevel->flag |= LVAR_INCASE; 


}   


else if (charlen == 1 && t_iseq(ptr, '*'))  


{   


if (lptr->start == ptr) 


UNCHAR; 


lptr->flag |= LVAR_ANYEND;  


curqlevel->flag |= LVAR_ANYEND; 


[PATCH] check for ctags utility in make_ctags

2018-12-31 Thread Nikolay Shaplov
Hi!

I'd like to propose a small patch for make_ctags script. It checks if ctags 
utility is intalled or not. If not it reports an error and advises to install 
ctags.

This will make life of a person that uses ctags first time in his life a bit 
easier.

I use command -v to detect if ctags command exists. It is POSIX standard and I 
hope it exist in all shells.diff --git a/src/tools/make_ctags b/src/tools/make_ctags
index 1609c07..edbcd82 100755
--- a/src/tools/make_ctags
+++ b/src/tools/make_ctags
@@ -2,6 +2,13 @@
 
 # src/tools/make_ctags
 
+if [ ! $(command -v ctags) ]
+then
+  echo "'ctags' utility is not found" &1>2
+  echo "Please install 'ctags' to run make_ctags" &1>2
+  exit 1
+fi
+
 trap "rm -f /tmp/$$" 0 1 2 3 15
 rm -f ./tags
 


  1   2   >