From: | Paul Jungwirth <pj(at)illuminatedcomputing(dot)com> |
---|---|
To: | jian he <jian(dot)universality(at)gmail(dot)com> |
Cc: | Isaac Morland <isaac(dot)morland(at)gmail(dot)com>, Robert Haas <robertmhaas(at)gmail(dot)com>, Jeff Davis <pgsql(at)j-davis(dot)com>, Peter Eisentraut <peter(at)eisentraut(dot)org>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org> |
Subject: | Re: SQL:2011 application time |
Date: | 2024-08-07 20:54:52 |
Message-ID: | 081aa43c-3a97-4bd5-a498-ba02e0a7570d@illuminatedcomputing.com |
Views: | Raw Message | Whole Thread | Download mbox | Resend email |
Thread: | |
Lists: | pgsql-hackers |
Here are some fixes based on outstanding feedback (some old some new). Details below:
On 3/25/24 17:00, jian he wrote:
> hi.
> minor issues I found in v33-0003.
> there are 29 of {check_amproc_signature?.*false}
> only one {check_amproc_signature(procform->amproc, opcintype, true}
> is this refactoring really worth it?
I could add a separate function, for example check_amproc_retset_signature, but it would require
duplicating almost the whole existing function, so a param seems better here.
> We also need to refactor gistadjustmembers?
You're right, added the new support procs there.
> + <row>
> + <entry><function>intersect</function></entry>
> + <entry>computes intersection with <literal>FOR PORTION OF</literal>
> + bounds</entry>
> + <entry>13</entry>
> + </row>
> + <row>
> + <entry><function>without_portion</function></entry>
> + <entry>computes remaining duration(s) outside
> + <literal>FOR PORTION OF</literal> bounds</entry>
> + <entry>14</entry>
> + </row>
> needs to add "(optional)".
Added.
> +<programlisting>
> +Datum
> +my_range_intersect(PG_FUNCTION_ARGS)
> +{
> + RangeType *r1 = PG_GETARG_RANGE_P(0);
> + RangeType *r2 = PG_GETARG_RANGE_P(1);
> + TypeCacheEntry *typcache;
> +
> + /* Different types should be prevented by ANYRANGE matching rules */
> + if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
> elog(ERROR, "range
> types do not match");
> +
> + typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
> +
> + PG_RETURN_RANGE_P(range_intersect_internal(typcache, r1, r2));
> +}
> +</programlisting>
> the elog, ERROR indentation is wrong?
Fixed.
> +/*
> + * range_without_portion_internal - Sets outputs and outputn to the ranges
> + * remaining and their count (respectively) after subtracting r2 from r1.
> + * The array should never contain empty ranges.
> + * The outputs will be ordered. We expect that outputs is an array of
> + * RangeType pointers, already allocated with two slots.
> + */
> +void
> +range_without_portion_internal(TypeCacheEntry *typcache, RangeType *r1,
> + RangeType *r2, RangeType **outputs, int *outputn)
> the comments need to be refactored?
> there is nothing related to "slot"?
> not sure the "array" description is right.
> (my understanding is compute rangetype r1 and r2, and save the result to
> RangeType **outputs.
Changed "slots" to "elements". Everything else looks correct to me.
> select proisstrict, proname from pg_proc where proname =
> 'range_without_portion';
> range_without_portion is strict.
> but
> select range_without_portion(NULL::int4range, int4range(11, 20,'[]'));
> return zero rows.
> Is this the expected behavior?
Returning zero rows is correct if the function is never called (which is what strict does).
I see other strict retset functions, e.g. json_array_elements.
That also returns zero rows if you say SELECT json_array_elements(NULL);
On 4/14/24 17:00, jian he wrote:
> for unique index, primary key:
> ii_ExclusionOps, ii_UniqueOps is enough to distinguish this index
> support without overlaps,
> we don't need another ii_HasWithoutOverlaps?
> (i didn't test it though)
I think it is worth having something named. But also ii_Exclusion is not set in
index_concurrently_create_copy, so inferring when we have WITHOUT OVERLAPS will not work in that case.
> ON CONFLICT DO NOTHING
> ON CONFLICT (id, valid_at) DO NOTHING
> ON CONFLICT ON CONSTRAINT temporal_rng_pk DO NOTHING
> I am confused by the test.
> here temporal_rng only has one primary key, ON CONFLICT only deals with it.
> I thought these three are the same thing?
They all have somewhat different code paths in infer_arbiter_indexes, and they mean different
things. I recall when I first started dealing with empty ranges several of these test cases caught
different bugs (as well as the DO UPDATE cases).
On 8/5/24 19:02, jian he wrote:
> void
> ExecWithoutOverlapsNotEmpty(Relation rel, Datum attval, Oid typtype,
> Oid atttypid);
>
> should this just be a static function?
> I am not so sure.
Changed. In a previous version I was calling this from two places, but I'm not anymore.
> Oid typtype
> should be
> char typtype
> ?
Oops, you're right! Fixed.
> errmsg("new row for relation \"%s\" contains empty
> WITHOUT OVERLAPS value",
> we already have Form_pg_attribute via "TupleDesc tupdesc =
> RelationGetDescr(heap);"
> we can make the error message be:
> errmsg("cannot be empty range value for WITHOUT
> OVERLAPS column \"%s\" in relation \"%s\", colname,
> RelationGetRelationName(rel))
Yes, it's nicer to report the column name. Changed.
> elog(ERROR, "Got unknown type for WITHOUT OVERLAPS column: %d", atttypid);
> people will wonder if domain over range works or not. but currently
> not, better error message would be:
> elog(ERROR, "WITHOUT OVERLAPS column \"%s\" is not a range
> or multirange type ", colname);
> This part is unlikely to be reachable, so I don't have a strong opinion on it.
Likewise.
> + if (!found)
> + column = NULL;
> this part no need?
> because if not found, the column would be last element in ColumnDef
> type list columns
We can later set `found` to true from inheritance (or it being a system column), and then `column`
is set but wrong. So setting `column` to null seems generally clearer. But concretely, I use
`column` below to give me the type (which I otherwise don't have in CREATE TABLE), so I can forbid
types other than range and multirange.
> also the following change also make sense:
>
> + if (!OidIsValid(typid) && column)
> + typid = typenameTypeId(NULL, column->typeName);
This is because in CREATE TABLE I need to get the type from the `column` variable.
> I am confused with this change?
> you found out the typid,but didn't using this information, should it be
> + if (strcmp(attname, key) == 0)
> + {
> + typid = attr->atttypid;
> + found = true;
> + break;
> + }
Yes. Actually that is in the PERIOD patch file, but it should be in Forbid-empty-ranges. Moved.
> so the failing error message be same for the following two cases:
> CREATE TABLE t1 (id int4range,valid_at tsrange,b text,
> CONSTRAINT temporal_rng_pk PRIMARY KEY (id, b WITHOUT OVERLAPS)
> );
>
> CREATE TABLE t1 (id int4range,valid_at tsrange,b text);
> alter table t1 add CONSTRAINT temporal_rng_pk PRIMARY KEY (id, b
> WITHOUT OVERLAPS);
I think the same error message is the right thing to do here.
It looks like that's what we're doing.
If I've misunderstand what you want, can you clarify?
On 8/6/24 07:50, jian he wrote:
> in generateClonedIndexStmt
> index->iswithoutoverlaps = (idxrec->indisprimary ||
> idxrec->indisunique) && idxrec->indisexclusion;
> this case, the index accessMethod will be "gist" only?
>
> do you think it's necessary to:
> index->iswithoutoverlaps = (idxrec->indisprimary ||
> idxrec->indisunique) && idxrec->indisexclusion
> && strcmp(index->accessMethod, "gist") == 0);
This doesn't seem necessary, and maybe we'll support non-gist someday, when this condition would be
misleading.
> src/bin/pg_dump/pg_dump.c and src/bin/psql/describe.c
> should be "if (pset.sversion >= 180000)"?
Ah, thanks. Changing these from 170000 also landed in the wrong patch file. Fixed.
> + (This is sometimes called a
> + temporal key, if the column is a range of dates or timestamps, but
> + PostgreSQL allows ranges over any base type.)
>
> PostgreSQL should be decorated as
> <productname>PostgreSQL</productname>
Done.
> in DefineIndex we have:
> if (stmt->unique && !stmt->iswithoutoverlaps && !amRoutine->amcanunique)
> if (stmt->indexIncludingParams != NIL && !amRoutine->amcaninclude)
> if (numberOfKeyAttributes > 1 && !amRoutine->amcanmulticol)
> if (exclusion && amRoutine->amgettuple == NULL)
>
> maybe we can add:
> if (stmt->iswithoutoverlaps && strcmp(accessMethodName, "gist") != 0)
> ereport(ERROR,
> (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
> errmsg("access method \"%s\" does not support WITHOUT
> OVERLAPS constraints",
> accessMethodName)));
Okay.
> + /* exclusionOpNames can be non-NIL if we are creating a partition */
> + if (iswithoutoverlaps && exclusionOpNames == NIL)
> + {
> + indexInfo->ii_ExclusionOps = palloc_array(Oid, nkeycols);
> + indexInfo->ii_ExclusionProcs = palloc_array(Oid, nkeycols);
> + indexInfo->ii_ExclusionStrats = palloc_array(uint16, nkeycols);
> + }
> the comment is not 100% correct, i think.
> creating a partition, "create table like INCLUDING ALL", both will go
> through generateClonedIndexStmt.
> generateClonedIndexStmt will produce exclusionOpNames if this index
> supports exclusion constraint.
I think the comment is correct, but non-NIL is a confusing double negative, and it's not clear that
the comment is giving the motivation for the second half of the condition.
I re-wrote it to be more clear. I also adjusted the `if` to avoid parsing operator names when not
needed.
Rebased to e56ccc8e42.
Yours,
--
Paul ~{:-)
pj(at)illuminatedcomputing(dot)com
Attachment | Content-Type | Size |
---|---|---|
v39-0001-Add-stratnum-GiST-support-function.patch | text/x-patch | 20.7 KB |
v39-0002-Add-temporal-PRIMARY-KEY-and-UNIQUE-constraints.patch | text/x-patch | 148.1 KB |
v39-0003-Forbid-empty-ranges-multiranges-in-WITHOUT-OVERL.patch | text/x-patch | 29.4 KB |
v39-0004-Add-temporal-FOREIGN-KEY-contraints.patch | text/x-patch | 186.9 KB |
v39-0005-Add-support-funcs-for-FOR-PORTION-OF.patch | text/x-patch | 43.3 KB |
v39-0006-Add-UPDATE-DELETE-FOR-PORTION-OF.patch | text/x-patch | 160.3 KB |
v39-0007-Add-CASCADE-SET-NULL-SET-DEFAULT-for-temporal-fo.patch | text/x-patch | 225.1 KB |
v39-0008-Add-PERIODs.patch | text/x-patch | 334.3 KB |
From | Date | Subject | |
---|---|---|---|
Next Message | Sami Imseih | 2024-08-07 21:22:22 | Re: Restart pg_usleep when interrupted |
Previous Message | Thomas Munro | 2024-08-07 20:52:41 | Re: Remaining dependency on setlocale() |