Hello Beena, Thanks for the updated patch. It passes the basic tests which I performed.
Few comments: 1. In check_new_partition_bound(), > /* Default case is not handled here */ > if (spec->is_default) > break; The default partition check here can be performed in common for both range and list partition. 2. RANGE_DATUM_FINITE = 0, /* actual datum stored elsewhere */ + RANGE_DATUM_DEFAULT, /* default */ More elaborative comment? 3. Inside make_one_range_bound(), >+ >+ /* datums are NULL for default */ >+ if (datums == NULL) >+ for (i = 0; i < key->partnatts; i++) >+ bound->content[i] = RANGE_DATUM_DEFAULT; >+ IMO, returning bound at this stage will make code clearer as further processing does not happen for default partition. 4. @@ -549,6 +568,7 @@ RelationBuildPartitionDesc(Relation rel) sizeof(RangeDatumContent *)); boundinfo->indexes = (int *) palloc((ndatums + 1) * sizeof(int)); + boundinfo->default_index = -1; This should also be done commonly for both default list and range partition. 5. if (!spec->is_default && partdesc->nparts > 0) { ListCell *cell; Assert(boundinfo && boundinfo->strategy == PARTITION_STRATEGY_LIST && (boundinfo->ndatums > 0 || partition_bound_accepts_nulls(boundinfo) || partition_bound_has_default(boundinfo))); The assertion condition partition_bound_has_default(boundinfo) is rendered useless because of if condition change and can be removed perhaps. 6. I think its better to have following regression tests coverage --Testing with inserting one NULL and other non NULL values for multicolumn range partitioned table. postgres=# CREATE TABLE range_parted ( postgres(# a int, postgres(# b int postgres(# ) PARTITION BY RANGE (a, b); CREATE TABLE postgres=# postgres=# CREATE TABLE part1 ( postgres(# a int NOT NULL CHECK (a = 1), postgres(# b int NOT NULL CHECK (b >= 1 AND b <= 10) postgres(# ); CREATE TABLE postgres=# ALTER TABLE range_parted ATTACH PARTITION part1 FOR VALUES FROM (1, 1) TO (1, 10); ALTER TABLE postgres=# CREATE TABLE partr_def1 PARTITION OF range_parted DEFAULT; CREATE TABLE postgres=# insert into range_parted values (1,NULL); INSERT 0 1 postgres=# insert into range_parted values (NULL,9); INSERT 0 1 --Testing the boundary conditions like in the above example following should pass. postgres=# insert into partr_def1 values (1,10); INSERT 0 1 Thank you, Rahila Syed On Mon, Jul 3, 2017 at 8:00 PM, Dilip Kumar <dilipbal...@gmail.com> wrote: > On Fri, Jun 30, 2017 at 11:56 AM, Beena Emerson <memissemer...@gmail.com> > wrote: > > Hello Dilip, > > > > On Wed, Jun 21, 2017 at 6:27 PM, Dilip Kumar <dilipbal...@gmail.com> > wrote: > >> On Tue, Jun 20, 2017 at 6:57 PM, Dilip Kumar <dilipbal...@gmail.com> > wrote: > >>> This is basically crashing in RelationBuildPartitionDesc, so I think > > > > > Thank you for your review and analysis. > > > > I have updated the patch. > > - bound->content is set to RANGE_DATUM_DEFAULT for each of the keys > > and not just the first one. > > - Improve the way of handling DEFAULT bounds in > RelationBuildPartitionDesc, > > > > There is a test for multiple column range in alter_table.sql > > Thanks for update patch, After this fix segmentation fault is solved. > > I have some more comments. > > 1. > > lower = make_one_range_bound(key, -1, spec->lowerdatums, true); > upper = make_one_range_bound(key, -1, spec->upperdatums, false); > > + /* Default case is not handled here */ > + if (spec->is_default) > + break; > + > > I think we can move default check just above the make range bound it > will avoid unnecessary processing. > > > 2. > RelationBuildPartitionDesc > { > .... > > /* > * If either of them has infinite element, we can't equate > * them. Even when both are infinite, they'd have > * opposite signs, because only one of cur and prev is a > * lower bound). > */ > if (cur->content[j] != RANGE_DATUM_FINITE || > prev->content[j] != RANGE_DATUM_FINITE) > { > is_distinct = true; > break; > } > After default range partitioning patch the above comment doesn't sound > very accurate and > can lead to the confusion, now here we are not only considering > infinite bounds but > there is also a possibility that prev bound can be DEFAULT, so > comments should clearly > mention that. > > 3. > > + bound->datums = datums ? (Datum *) palloc0(key->partnatts * > sizeof(Datum)) > + : NULL; > bound->content = (RangeDatumContent *) palloc0(key->partnatts * > sizeof(RangeDatumContent)); > bound->lower = lower; > > i = 0; > + > + /* datums are NULL for default */ > + if (datums == NULL) > + for (i = 0; i < key->partnatts; i++) > + bound->content[i] = RANGE_DATUM_DEFAULT; > > To me, it will look cleaner if we keep bound->content=NULL for > default, instead of allocating memory > and initializing each element, But it's just a suggestions and you > can decide whichever way > seems better to you. Then the other places e.g. > + if (cur->content[i] == RANGE_DATUM_DEFAULT) > + { > + /* > > will change like > > + if (cur->content == NULL) > + { > + /* > > -- > Regards, > Dilip Kumar > EnterpriseDB: http://www.enterprisedb.com >