Compare commits

...

7 Commits

Author SHA1 Message Date
David Rowley
673a17e312 Add missing include dir and references to libpq for MSVC build
66d6086cb adjusted pg_regress to require this but forgot to adjust the
Visual Studio build script.
2023-10-25 15:37:37 +13:00
Michael Paquier
cccfa08c39 doc: Fix some typos and grammar
Author: Ekaterina Kiryanova, Elena Indrupskaya, Oleg Sibiryakov, Maxim
Yablokov
Discussion: https://postgr.es/m/7aad518b-3e6d-47f3-9184-b1d69cb412e7@postgrespro.ru
Backpatch-through: 11
2023-10-25 09:40:55 +09:00
Michael Paquier
55a428a18d Log OpenSSL version in ./configure output
This information is useful to know when scanning buildfarm results, and
it is already displayed in Meson.  The output of `openssl version` is
logged, with the command retrieved from PATH.

This depends on c8e4030d1bdd, so backpatch down to 16.

Reviewed-by: Peter Eisentraut, Daniel Gustafsson, Tom Lane
Discussion: https://postgr.es/m/ZTW9yOlZaSVoFhTz@paquier.xyz
Backpatch-through: 16
2023-10-25 09:26:22 +09:00
Daniel Gustafsson
d8fd08efbc Reword memory terminology for PQresultMemorySize
Rather than using the generic word "space" we might as well use "memory"
since that's precisely what we're dealing with here.

This was extracted from a larger patch around terminology changes where
the remaining hunks were rejected.

Author: Gurjeet Singh <gurjeet@singh.im>
Reviewed-by: Daniel Gustafsson <daniel@yesql.se>
Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/CABwTF4UHO_NtcsOL6_XZfnpKg_0XBFKa7B-7_x5zs3MRZm3-Tg@mail.gmail.com
2023-10-24 22:18:19 +02:00
Daniel Gustafsson
66d6086cbc Speed up pg_regress server readiness testing.
Instead of connecting to the server with psql to check if it is ready
for running tests, this changes pg_regress to use PQPing which avoids
performing system() calls which are expensive on some platforms, like
Windows. The frequency of tests is also increased in order to connect
to the server faster.

This patch is part of a larger effort to make testing consume fewer
resources in order to be able to fit more tests into the available
CI system constraints.

Reviewed-by: Andres Freund <andres@anarazel.de>
Discussion: https://postgr.es/m/20230823192239.jxew5s3sjru63lio@awork3.anarazel.de
2023-10-24 21:37:35 +02:00
Tom Lane
387f9ed0a0 Fix problems when a plain-inheritance parent table is excluded.
When an UPDATE/DELETE/MERGE's target table is an old-style
inheritance tree, it's possible for the parent to get excluded
from the plan while some children are not.  (I believe this is
only possible if we can prove that a CHECK ... NO INHERIT
constraint on the parent contradicts the query WHERE clause,
so it's a very unusual case.)  In such a case, ExecInitModifyTable
mistakenly concluded that the first surviving child is the target
table, leading to at least two bugs:

1. The wrong table's statement-level triggers would get fired.

2. In v16 and up, it was possible to fail with "invalid perminfoindex
0 in RTE with relid nnnn" due to the child RTE not having permissions
data included in the query plan.  This was hard to reproduce reliably
because it did not occur unless the update triggered some non-HOT
index updates.

In v14 and up, this is easy to fix by defining ModifyTable.rootRelation
to be the parent RTE in plain inheritance as well as partitioned cases.

While the wrong-triggers bug also appears in older branches, the
relevant code in both the planner and executor is quite a bit
different, so it would take a good deal of effort to develop and
test a suitable patch.  Given the lack of field complaints about the
trigger issue, I'll desist for now.  (Patching v11 for this seems
unwise anyway, given that it will have no more releases after next
month.)

Per bug #18147 from Hans Buschmann.

Amit Langote and Tom Lane

Discussion: https://postgr.es/m/18147-6fc796538913ee88@postgresql.org
2023-10-24 14:48:33 -04:00
Peter Geoghegan
74e5ea1e00 Doc: indexUnchanged is strictly a hint.
Clearly spell out the limitations of aminsert()'s indexUnchanged hinting
mechanism in the index AM documentation.

Oversight in commit 9dc718bd, which added the "logically unchanged
index" hint (which is used to trigger bottom-up index deletion).

Author: Peter Geoghegan <pg@bowt.ie>
Reported-By: Tom Lane <tgl@sss.pgh.pa.us>
Reviewed-By: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: https://postgr.es/m/CAH2-WzmU_BQ=-H9L+bxTSMQBqHMjp1DSwGypvL0gKs+dTOfkKg@mail.gmail.com
Backpatch: 14-, where indexUnchanged hinting was introduced.
2023-10-24 09:27:27 -07:00
27 changed files with 151 additions and 70 deletions

3
configure vendored
View File

@ -14077,6 +14077,9 @@ $as_echo_n "checking for OPENSSL... " >&6; }
$as_echo "$OPENSSL" >&6; } $as_echo "$OPENSSL" >&6; }
fi fi
pgac_openssl_version="$($OPENSSL version 2> /dev/null || echo openssl not found)"
{ $as_echo "$as_me:${as_lineno-$LINENO}: using openssl: $pgac_openssl_version" >&5
$as_echo "$as_me: using openssl: $pgac_openssl_version" >&6;}
if test "$with_ssl" = openssl ; then if test "$with_ssl" = openssl ; then
ac_fn_c_check_header_mongrel "$LINENO" "openssl/ssl.h" "ac_cv_header_openssl_ssl_h" "$ac_includes_default" ac_fn_c_check_header_mongrel "$LINENO" "openssl/ssl.h" "ac_cv_header_openssl_ssl_h" "$ac_includes_default"
if test "x$ac_cv_header_openssl_ssl_h" = xyes; then : if test "x$ac_cv_header_openssl_ssl_h" = xyes; then :

View File

@ -1553,6 +1553,8 @@ if test "$with_gssapi" = yes ; then
fi fi
PGAC_PATH_PROGS(OPENSSL, openssl) PGAC_PATH_PROGS(OPENSSL, openssl)
pgac_openssl_version="$($OPENSSL version 2> /dev/null || echo openssl not found)"
AC_MSG_NOTICE([using openssl: $pgac_openssl_version])
if test "$with_ssl" = openssl ; then if test "$with_ssl" = openssl ; then
AC_CHECK_HEADER(openssl/ssl.h, [], [AC_MSG_ERROR([header file <openssl/ssl.h> is required for OpenSSL])]) AC_CHECK_HEADER(openssl/ssl.h, [], [AC_MSG_ERROR([header file <openssl/ssl.h> is required for OpenSSL])])
AC_CHECK_HEADER(openssl/err.h, [], [AC_MSG_ERROR([header file <openssl/err.h> is required for OpenSSL])]) AC_CHECK_HEADER(openssl/err.h, [], [AC_MSG_ERROR([header file <openssl/err.h> is required for OpenSSL])])

View File

@ -1158,7 +1158,7 @@ SELECT 'w;x*y-z' = 'wxyz' COLLATE num_ignore_punct; -- true
<para> <para>
<xref linkend="icu-collation-levels"/> shows which textual feature <xref linkend="icu-collation-levels"/> shows which textual feature
differences are considered significant when determining equality at the differences are considered significant when determining equality at the
given level. The unicode character <literal>U+2063</literal> is an given level. The Unicode character <literal>U+2063</literal> is an
invisible separator, and as seen in the table, is ignored for at all invisible separator, and as seen in the table, is ignored for at all
levels of comparison less than <literal>identic</literal>. levels of comparison less than <literal>identic</literal>.
</para> </para>

View File

@ -984,7 +984,7 @@ mymap /^(.*)@otherdomain\.com$ guest
a slash (<literal>/</literal>), the remainder of the field is treated a slash (<literal>/</literal>), the remainder of the field is treated
as a regular expression (see <xref linkend="posix-syntax-details"/> as a regular expression (see <xref linkend="posix-syntax-details"/>
for details of <productname>PostgreSQL</productname>'s regular for details of <productname>PostgreSQL</productname>'s regular
expression syntax. It is not possible to use <literal>\1</literal> expression syntax). It is not possible to use <literal>\1</literal>
to use a capture from regular expression on to use a capture from regular expression on
<replaceable>system-username</replaceable> for a regular expression <replaceable>system-username</replaceable> for a regular expression
on <replaceable>database-username</replaceable>. on <replaceable>database-username</replaceable>.

View File

@ -332,9 +332,13 @@ aminsert (Relation indexRelation,
modify any columns covered by the index, but nevertheless requires a modify any columns covered by the index, but nevertheless requires a
new version in the index. The index AM may use this hint to decide new version in the index. The index AM may use this hint to decide
to apply bottom-up index deletion in parts of the index where many to apply bottom-up index deletion in parts of the index where many
versions of the same logical row accumulate. Note that updating a versions of the same logical row accumulate. Note that updating a non-key
non-key column does not affect the value of column or a column that only appears in a partial index predicate does not
<literal>indexUnchanged</literal>. affect the value of <literal>indexUnchanged</literal>. The core code
determines each tuple's <literal>indexUnchanged</literal> value using a low
overhead approach that allows both false positives and false negatives.
Index AMs must not treat <literal>indexUnchanged</literal> as an
authoritative source of information about tuple visibility or versioning.
</para> </para>
<para> <para>

View File

@ -2090,9 +2090,9 @@ ninja
configure with the <option>--backend</option> option to select the one you configure with the <option>--backend</option> option to select the one you
want to use and then build using <literal>meson compile</literal>. To want to use and then build using <literal>meson compile</literal>. To
learn more about these backends and other arguments you can provide to learn more about these backends and other arguments you can provide to
ninja, you can refer to the meson <ulink ninja, you can refer to the <ulink
url="https://mesonbuild.com/Running-Meson.html#building-from-the-source"> url="https://mesonbuild.com/Running-Meson.html#building-from-the-source">
documentation</ulink>. Meson documentation</ulink>.
</para> </para>
</step> </step>

View File

@ -7323,7 +7323,7 @@ size_t PQresultMemorySize(const PGresult *res);
<para> <para>
This value is the sum of all <function>malloc</function> requests This value is the sum of all <function>malloc</function> requests
associated with the <structname>PGresult</structname> object, that is, associated with the <structname>PGresult</structname> object, that is,
all the space that will be freed by <xref linkend="libpq-PQclear"/>. all the memory that will be freed by <xref linkend="libpq-PQclear"/>.
This information can be useful for managing memory consumption. This information can be useful for managing memory consumption.
</para> </para>
</listitem> </listitem>

View File

@ -205,7 +205,7 @@ make update-po
<para> <para>
The PO files can be edited with a regular text editor. There are also The PO files can be edited with a regular text editor. There are also
several specialized editors for PO files which can help the process with several specialized editors for PO files which can help the process with
translation specific features. translation-specific features.
There is (unsurprisingly) a PO mode for Emacs, which can be quite There is (unsurprisingly) a PO mode for Emacs, which can be quite
useful. useful.
</para> </para>

View File

@ -209,7 +209,7 @@ block_fpi_data |
<para> <para>
The <function>pg_filenode_relation</function> function (see The <function>pg_filenode_relation</function> function (see
<xref linkend="functions-admin-dblocation"/>) can help you to <xref linkend="functions-admin-dblocation"/>) can help you to
determine which relation was modified during original execution determine which relation was modified during original execution.
</para> </para>
</tip> </tip>
<para> <para>

View File

@ -376,7 +376,7 @@ WITH ( MODULUS <replaceable class="parameter">numeric_literal</replaceable>, REM
an <command>UPDATE</command> that changes the partition key value can an <command>UPDATE</command> that changes the partition key value can
cause a row to be moved from a local partition to a foreign-table cause a row to be moved from a local partition to a foreign-table
partition, provided the foreign data wrapper supports tuple routing. partition, provided the foreign data wrapper supports tuple routing.
However it is not currently possible to move a row from a However, it is not currently possible to move a row from a
foreign-table partition to another partition. foreign-table partition to another partition.
An <command>UPDATE</command> that would require doing that will fail An <command>UPDATE</command> that would require doing that will fail
due to the partitioning constraint, assuming that that is properly due to the partitioning constraint, assuming that that is properly

View File

@ -1608,7 +1608,7 @@
<para> <para>
Apply transaction locks are used in parallel mode to apply the transaction Apply transaction locks are used in parallel mode to apply the transaction
in logical replication. The remote transaction id is displayed in the in logical replication. The remote transaction ID is displayed in the
<structfield>transactionid</structfield> column. The <structfield>objsubid</structfield> <structfield>transactionid</structfield> column. The <structfield>objsubid</structfield>
displays the lock subtype which is 0 for the lock used to synchronize the displays the lock subtype which is 0 for the lock used to synchronize the
set of changes, and 1 for the lock used to wait for the transaction to set of changes, and 1 for the lock used to wait for the transaction to

View File

@ -156,7 +156,7 @@
<para> <para>
When a top-level transaction with an xid commits, all of its When a top-level transaction with an xid commits, all of its
subcommitted child subtransactions are also persistently recorded subcommitted child subtransactions are also persistently recorded
as committed in the <filename>pg_xact</filename> directory. If the as committed in the <filename>pg_xact</filename> subdirectory. If the
top-level transaction aborts, all its subtransactions are also aborted, top-level transaction aborts, all its subtransactions are also aborted,
even if they were subcommitted. even if they were subcommitted.
</para> </para>

View File

@ -3966,10 +3966,10 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
* must be converted, and * must be converted, and
* - the root partitioned table used for tuple routing. * - the root partitioned table used for tuple routing.
* *
* If it's a partitioned table, the root partition doesn't appear * If it's a partitioned or inherited table, the root partition or
* elsewhere in the plan and its RT index is given explicitly in * appendrel RTE doesn't appear elsewhere in the plan and its RT index is
* node->rootRelation. Otherwise (i.e. table inheritance) the target * given explicitly in node->rootRelation. Otherwise, the target relation
* relation is the first relation in the node->resultRelations list. * is the sole relation in the node->resultRelations list.
*---------- *----------
*/ */
if (node->rootRelation > 0) if (node->rootRelation > 0)
@ -3980,6 +3980,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
} }
else else
{ {
Assert(list_length(node->resultRelations) == 1);
mtstate->rootResultRelInfo = mtstate->resultRelInfo; mtstate->rootResultRelInfo = mtstate->resultRelInfo;
ExecInitResultRelation(estate, mtstate->resultRelInfo, ExecInitResultRelation(estate, mtstate->resultRelInfo,
linitial_int(node->resultRelations)); linitial_int(node->resultRelations));

View File

@ -1800,6 +1800,9 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
parse->resultRelation); parse->resultRelation);
int resultRelation = -1; int resultRelation = -1;
/* Pass the root result rel forward to the executor. */
rootRelation = parse->resultRelation;
/* Add only leaf children to ModifyTable. */ /* Add only leaf children to ModifyTable. */
while ((resultRelation = bms_next_member(root->leaf_result_relids, while ((resultRelation = bms_next_member(root->leaf_result_relids,
resultRelation)) >= 0) resultRelation)) >= 0)
@ -1923,6 +1926,7 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
else else
{ {
/* Single-relation INSERT/UPDATE/DELETE/MERGE. */ /* Single-relation INSERT/UPDATE/DELETE/MERGE. */
rootRelation = 0; /* there's no separate root rel */
resultRelations = list_make1_int(parse->resultRelation); resultRelations = list_make1_int(parse->resultRelation);
if (parse->commandType == CMD_UPDATE) if (parse->commandType == CMD_UPDATE)
updateColnosLists = list_make1(root->update_colnos); updateColnosLists = list_make1(root->update_colnos);
@ -1934,16 +1938,6 @@ grouping_planner(PlannerInfo *root, double tuple_fraction)
mergeActionLists = list_make1(parse->mergeActionList); mergeActionLists = list_make1(parse->mergeActionList);
} }
/*
* If target is a partition root table, we need to mark the
* ModifyTable node appropriately for that.
*/
if (rt_fetch(parse->resultRelation, parse->rtable)->relkind ==
RELKIND_PARTITIONED_TABLE)
rootRelation = parse->resultRelation;
else
rootRelation = 0;
/* /*
* If there was a FOR [KEY] UPDATE/SHARE clause, the LockRows node * If there was a FOR [KEY] UPDATE/SHARE clause, the LockRows node
* will have dealt with fetching non-locked marked rows, else we * will have dealt with fetching non-locked marked rows, else we

View File

@ -3663,7 +3663,7 @@ create_lockrows_path(PlannerInfo *root, RelOptInfo *rel,
* 'operation' is the operation type * 'operation' is the operation type
* 'canSetTag' is true if we set the command tag/es_processed * 'canSetTag' is true if we set the command tag/es_processed
* 'nominalRelation' is the parent RT index for use of EXPLAIN * 'nominalRelation' is the parent RT index for use of EXPLAIN
* 'rootRelation' is the partitioned table root RT index, or 0 if none * 'rootRelation' is the partitioned/inherited table root RTI, or 0 if none
* 'partColsUpdated' is true if any partitioning columns are being updated, * 'partColsUpdated' is true if any partitioning columns are being updated,
* either from the target relation or a descendent partitioned table. * either from the target relation or a descendent partitioned table.
* 'resultRelations' is an integer list of actual RT indexes of target rel(s) * 'resultRelations' is an integer list of actual RT indexes of target rel(s)

View File

@ -2344,7 +2344,7 @@ typedef struct ModifyTablePath
CmdType operation; /* INSERT, UPDATE, DELETE, or MERGE */ CmdType operation; /* INSERT, UPDATE, DELETE, or MERGE */
bool canSetTag; /* do we set the command tag/es_processed? */ bool canSetTag; /* do we set the command tag/es_processed? */
Index nominalRelation; /* Parent RT index for use of EXPLAIN */ Index nominalRelation; /* Parent RT index for use of EXPLAIN */
Index rootRelation; /* Root RT index, if target is partitioned */ Index rootRelation; /* Root RT index, if partitioned/inherited */
bool partColsUpdated; /* some part key in hierarchy updated? */ bool partColsUpdated; /* some part key in hierarchy updated? */
List *resultRelations; /* integer list of RT indexes */ List *resultRelations; /* integer list of RT indexes */
List *updateColnosLists; /* per-target-table update_colnos lists */ List *updateColnosLists; /* per-target-table update_colnos lists */

View File

@ -216,11 +216,12 @@ typedef struct ProjectSet
* Apply rows produced by outer plan to result table(s), * Apply rows produced by outer plan to result table(s),
* by inserting, updating, or deleting. * by inserting, updating, or deleting.
* *
* If the originally named target table is a partitioned table, both * If the originally named target table is a partitioned table or inheritance
* nominalRelation and rootRelation contain the RT index of the partition * tree, both nominalRelation and rootRelation contain the RT index of the
* root, which is not otherwise mentioned in the plan. Otherwise rootRelation * partition root or appendrel RTE, which is not otherwise mentioned in the
* is zero. However, nominalRelation will always be set, as it's the rel that * plan. Otherwise rootRelation is zero. However, nominalRelation will
* EXPLAIN should claim is the INSERT/UPDATE/DELETE/MERGE target. * always be set, as it's the rel that EXPLAIN should claim is the
* INSERT/UPDATE/DELETE/MERGE target.
* *
* Note that rowMarks and epqParam are presumed to be valid for all the * Note that rowMarks and epqParam are presumed to be valid for all the
* table(s); they can't contain any info that varies across tables. * table(s); they can't contain any info that varies across tables.
@ -232,7 +233,7 @@ typedef struct ModifyTable
CmdType operation; /* INSERT, UPDATE, DELETE, or MERGE */ CmdType operation; /* INSERT, UPDATE, DELETE, or MERGE */
bool canSetTag; /* do we set the command tag/es_processed? */ bool canSetTag; /* do we set the command tag/es_processed? */
Index nominalRelation; /* Parent RT index for use of EXPLAIN */ Index nominalRelation; /* Parent RT index for use of EXPLAIN */
Index rootRelation; /* Root RT index, if target is partitioned */ Index rootRelation; /* Root RT index, if partitioned/inherited */
bool partColsUpdated; /* some part key in hierarchy updated? */ bool partColsUpdated; /* some part key in hierarchy updated? */
List *resultRelations; /* integer list of RT indexes */ List *resultRelations; /* integer list of RT indexes */
List *updateColnosLists; /* per-target-table update_colnos lists */ List *updateColnosLists; /* per-target-table update_colnos lists */

View File

@ -10,6 +10,7 @@ include $(top_builddir)/src/Makefile.global
override CPPFLAGS := \ override CPPFLAGS := \
'-I$(top_builddir)/src/port' \ '-I$(top_builddir)/src/port' \
'-I$(top_srcdir)/src/test/regress' \ '-I$(top_srcdir)/src/test/regress' \
'-I$(libpq_srcdir)' \
'-DHOST_TUPLE="$(host_tuple)"' \ '-DHOST_TUPLE="$(host_tuple)"' \
'-DSHELLPROG="$(SHELL)"' \ '-DSHELLPROG="$(SHELL)"' \
$(CPPFLAGS) $(CPPFLAGS)
@ -45,7 +46,7 @@ clean distclean maintainer-clean:
all: pg_regress$(X) all: pg_regress$(X)
pg_regress$(X): pg_regress_ecpg.o $(WIN32RES) $(top_builddir)/src/test/regress/pg_regress.o pg_regress$(X): pg_regress_ecpg.o $(WIN32RES) $(top_builddir)/src/test/regress/pg_regress.o
$(CC) $(CFLAGS) $^ $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@ $(CC) $(CFLAGS) $^ $(libpq_pgport) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@
$(top_builddir)/src/test/regress/pg_regress.o: $(top_builddir)/src/test/regress/pg_regress.o:
$(MAKE) -C $(dir $@) $(notdir $@) $(MAKE) -C $(dir $@) $(notdir $@)

View File

@ -18,7 +18,7 @@ pg_regress_ecpg = executable('pg_regress_ecpg',
pg_regress_ecpg_sources, pg_regress_ecpg_sources,
c_args: pg_regress_cflags, c_args: pg_regress_cflags,
include_directories: [pg_regress_inc, include_directories('.')], include_directories: [pg_regress_inc, include_directories('.')],
dependencies: [frontend_code], dependencies: [frontend_code, libpq],
kwargs: default_bin_args + { kwargs: default_bin_args + {
'install': false 'install': false
}, },

View File

@ -38,7 +38,7 @@ pg_regress.o: | submake-regress
rm -f $@ && $(LN_S) $(top_builddir)/src/test/regress/pg_regress.o . rm -f $@ && $(LN_S) $(top_builddir)/src/test/regress/pg_regress.o .
pg_isolation_regress$(X): isolation_main.o pg_regress.o $(WIN32RES) pg_isolation_regress$(X): isolation_main.o pg_regress.o $(WIN32RES)
$(CC) $(CFLAGS) $^ $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@ $(CC) $(CFLAGS) $^ $(libpq_pgport) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@
isolationtester$(X): $(OBJS) | submake-libpq submake-libpgport isolationtester$(X): $(OBJS) | submake-libpq submake-libpgport
$(CC) $(CFLAGS) $^ $(libpq_pgport) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@ $(CC) $(CFLAGS) $^ $(libpq_pgport) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@

View File

@ -35,7 +35,7 @@ pg_isolation_regress = executable('pg_isolation_regress',
isolation_sources, isolation_sources,
c_args: pg_regress_cflags, c_args: pg_regress_cflags,
include_directories: pg_regress_inc, include_directories: pg_regress_inc,
dependencies: frontend_code, dependencies: [frontend_code, libpq],
kwargs: default_bin_args + { kwargs: default_bin_args + {
'install_dir': dir_pgxs / 'src/test/isolation', 'install_dir': dir_pgxs / 'src/test/isolation',
}, },

View File

@ -36,11 +36,11 @@ EXTRADEFS = '-DHOST_TUPLE="$(host_tuple)"' \
all: pg_regress$(X) all: pg_regress$(X)
pg_regress$(X): pg_regress.o pg_regress_main.o $(WIN32RES) | submake-libpgport pg_regress$(X): pg_regress.o pg_regress_main.o $(WIN32RES) | submake-libpgport
$(CC) $(CFLAGS) $^ $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@ $(CC) $(CFLAGS) $^ $(libpq_pgport) $(LDFLAGS) $(LDFLAGS_EX) $(LIBS) -o $@
# dependencies ensure that path changes propagate # dependencies ensure that path changes propagate
pg_regress.o: pg_regress.c $(top_builddir)/src/port/pg_config_paths.h pg_regress.o: pg_regress.c $(top_builddir)/src/port/pg_config_paths.h
pg_regress.o: override CPPFLAGS += -I$(top_builddir)/src/port $(EXTRADEFS) pg_regress.o: override CPPFLAGS += -I$(top_builddir)/src/port -I$(libpq_srcdir) $(EXTRADEFS)
# note: because of the submake dependency, this rule's action is really a no-op # note: because of the submake dependency, this rule's action is really a no-op
$(top_builddir)/src/port/pg_config_paths.h: | submake-libpgport $(top_builddir)/src/port/pg_config_paths.h: | submake-libpgport

View File

@ -539,6 +539,33 @@ CREATE TEMP TABLE z (b TEXT, PRIMARY KEY(aa, b)) inherits (a);
INSERT INTO z VALUES (NULL, 'text'); -- should fail INSERT INTO z VALUES (NULL, 'text'); -- should fail
ERROR: null value in column "aa" of relation "z" violates not-null constraint ERROR: null value in column "aa" of relation "z" violates not-null constraint
DETAIL: Failing row contains (null, text). DETAIL: Failing row contains (null, text).
-- Check inherited UPDATE with first child excluded
create table some_tab (f1 int, f2 int, f3 int, check (f1 < 10) no inherit);
create table some_tab_child () inherits(some_tab);
insert into some_tab_child select i, i+1, 0 from generate_series(1,1000) i;
create index on some_tab_child(f1, f2);
-- while at it, also check that statement-level triggers fire
create function some_tab_stmt_trig_func() returns trigger as
$$begin raise notice 'updating some_tab'; return NULL; end;$$
language plpgsql;
create trigger some_tab_stmt_trig
before update on some_tab execute function some_tab_stmt_trig_func();
explain (costs off)
update some_tab set f3 = 11 where f1 = 12 and f2 = 13;
QUERY PLAN
------------------------------------------------------------------------------------
Update on some_tab
Update on some_tab_child some_tab_1
-> Result
-> Index Scan using some_tab_child_f1_f2_idx on some_tab_child some_tab_1
Index Cond: ((f1 = 12) AND (f2 = 13))
(5 rows)
update some_tab set f3 = 11 where f1 = 12 and f2 = 13;
NOTICE: updating some_tab
drop table some_tab cascade;
NOTICE: drop cascades to table some_tab_child
drop function some_tab_stmt_trig_func();
-- Check inherited UPDATE with all children excluded -- Check inherited UPDATE with all children excluded
create table some_tab (a int, b int); create table some_tab (a int, b int);
create table some_tab_child () inherits (some_tab); create table some_tab_child () inherits (some_tab);

View File

@ -30,7 +30,7 @@ endif
pg_regress = executable('pg_regress', pg_regress = executable('pg_regress',
regress_sources, regress_sources,
c_args: pg_regress_cflags, c_args: pg_regress_cflags,
dependencies: [frontend_code], dependencies: [frontend_code, libpq],
kwargs: default_bin_args + { kwargs: default_bin_args + {
'install_dir': dir_pgxs / 'src/test/regress', 'install_dir': dir_pgxs / 'src/test/regress',
}, },

View File

@ -32,6 +32,7 @@
#include "common/username.h" #include "common/username.h"
#include "getopt_long.h" #include "getopt_long.h"
#include "lib/stringinfo.h" #include "lib/stringinfo.h"
#include "libpq-fe.h"
#include "libpq/pqcomm.h" /* needed for UNIXSOCK_PATH() */ #include "libpq/pqcomm.h" /* needed for UNIXSOCK_PATH() */
#include "pg_config_paths.h" #include "pg_config_paths.h"
#include "pg_regress.h" #include "pg_regress.h"
@ -75,6 +76,12 @@ const char *pretty_diff_opts = "-w -U3";
*/ */
#define TESTNAME_WIDTH 36 #define TESTNAME_WIDTH 36
/*
* The number times per second that pg_regress checks to see if the test
* instance server has started and is available for connection.
*/
#define WAIT_TICKS_PER_SECOND 20
typedef enum TAPtype typedef enum TAPtype
{ {
DIAG = 0, DIAG = 0,
@ -107,6 +114,7 @@ static bool nolocale = false;
static bool use_existing = false; static bool use_existing = false;
static char *hostname = NULL; static char *hostname = NULL;
static int port = -1; static int port = -1;
static char portstr[16];
static bool port_specified_by_user = false; static bool port_specified_by_user = false;
static char *dlpath = PKGLIBDIR; static char *dlpath = PKGLIBDIR;
static char *user = NULL; static char *user = NULL;
@ -2107,7 +2115,6 @@ regression_main(int argc, char *argv[],
int i; int i;
int option_index; int option_index;
char buf[MAXPGPATH * 4]; char buf[MAXPGPATH * 4];
char buf2[MAXPGPATH * 4];
pg_logging_init(argv[0]); pg_logging_init(argv[0]);
progname = get_progname(argv[0]); progname = get_progname(argv[0]);
@ -2296,6 +2303,9 @@ regression_main(int argc, char *argv[],
const char *env_wait; const char *env_wait;
int wait_seconds; int wait_seconds;
const char *initdb_template_dir; const char *initdb_template_dir;
const char *keywords[4];
const char *values[4];
PGPing rv;
/* /*
* Prepare the temp instance * Prepare the temp instance
@ -2435,22 +2445,29 @@ regression_main(int argc, char *argv[],
} }
#endif #endif
/*
* Prepare the connection params for checking the state of the server
* before starting the tests.
*/
sprintf(portstr, "%d", port);
keywords[0] = "dbname";
values[0] = "postgres";
keywords[1] = "port";
values[1] = portstr;
keywords[2] = "host";
values[2] = hostname ? hostname : sockdir;
keywords[3] = NULL;
values[3] = NULL;
/* /*
* Check if there is a postmaster running already. * Check if there is a postmaster running already.
*/ */
snprintf(buf2, sizeof(buf2),
"\"%s%spsql\" -X postgres <%s 2>%s",
bindir ? bindir : "",
bindir ? "/" : "",
DEVNULL, DEVNULL);
for (i = 0; i < 16; i++) for (i = 0; i < 16; i++)
{ {
fflush(NULL); rv = PQpingParams(keywords, values, 1);
if (system(buf2) == 0)
{
char s[16];
if (rv == PQPING_OK)
{
if (port_specified_by_user || i == 15) if (port_specified_by_user || i == 15)
{ {
note("port %d apparently in use", port); note("port %d apparently in use", port);
@ -2461,8 +2478,8 @@ regression_main(int argc, char *argv[],
note("port %d apparently in use, trying %d", port, port + 1); note("port %d apparently in use, trying %d", port, port + 1);
port++; port++;
sprintf(s, "%d", port); sprintf(portstr, "%d", port);
setenv("PGPORT", s, 1); setenv("PGPORT", portstr, 1);
} }
else else
break; break;
@ -2485,11 +2502,11 @@ regression_main(int argc, char *argv[],
bail("could not spawn postmaster: %s", strerror(errno)); bail("could not spawn postmaster: %s", strerror(errno));
/* /*
* Wait till postmaster is able to accept connections; normally this * Wait till postmaster is able to accept connections; normally takes
* is only a second or so, but Cygwin is reportedly *much* slower, and * only a fraction of a second or so, but Cygwin is reportedly *much*
* test builds using Valgrind or similar tools might be too. Hence, * slower, and test builds using Valgrind or similar tools might be
* allow the default timeout of 60 seconds to be overridden from the * too. Hence, allow the default timeout of 60 seconds to be
* PGCTLTIMEOUT environment variable. * overridden from the PGCTLTIMEOUT environment variable.
*/ */
env_wait = getenv("PGCTLTIMEOUT"); env_wait = getenv("PGCTLTIMEOUT");
if (env_wait != NULL) if (env_wait != NULL)
@ -2501,13 +2518,24 @@ regression_main(int argc, char *argv[],
else else
wait_seconds = 60; wait_seconds = 60;
for (i = 0; i < wait_seconds; i++) for (i = 0; i < wait_seconds * WAIT_TICKS_PER_SECOND; i++)
{ {
/* Done if psql succeeds */ /*
fflush(NULL); * It's fairly unlikely that the server is responding immediately
if (system(buf2) == 0) * so we start with sleeping before checking instead of the other
* way around.
*/
pg_usleep(1000000L / WAIT_TICKS_PER_SECOND);
rv = PQpingParams(keywords, values, 1);
/* Done if the server is running and accepts connections */
if (rv == PQPING_OK)
break; break;
if (rv == PQPING_NO_ATTEMPT)
bail("attempting to connect to postmaster failed");
/* /*
* Fail immediately if postmaster has exited * Fail immediately if postmaster has exited
*/ */
@ -2520,10 +2548,8 @@ regression_main(int argc, char *argv[],
bail("postmaster failed, examine \"%s/log/postmaster.log\" for the reason", bail("postmaster failed, examine \"%s/log/postmaster.log\" for the reason",
outputdir); outputdir);
} }
pg_usleep(1000000L);
} }
if (i >= wait_seconds) if (i >= wait_seconds * WAIT_TICKS_PER_SECOND)
{ {
diag("postmaster did not respond within %d seconds, examine \"%s/log/postmaster.log\" for the reason", diag("postmaster did not respond within %d seconds, examine \"%s/log/postmaster.log\" for the reason",
wait_seconds, outputdir); wait_seconds, outputdir);

View File

@ -97,6 +97,25 @@ SELECT relname, d.* FROM ONLY d, pg_class where d.tableoid = pg_class.oid;
CREATE TEMP TABLE z (b TEXT, PRIMARY KEY(aa, b)) inherits (a); CREATE TEMP TABLE z (b TEXT, PRIMARY KEY(aa, b)) inherits (a);
INSERT INTO z VALUES (NULL, 'text'); -- should fail INSERT INTO z VALUES (NULL, 'text'); -- should fail
-- Check inherited UPDATE with first child excluded
create table some_tab (f1 int, f2 int, f3 int, check (f1 < 10) no inherit);
create table some_tab_child () inherits(some_tab);
insert into some_tab_child select i, i+1, 0 from generate_series(1,1000) i;
create index on some_tab_child(f1, f2);
-- while at it, also check that statement-level triggers fire
create function some_tab_stmt_trig_func() returns trigger as
$$begin raise notice 'updating some_tab'; return NULL; end;$$
language plpgsql;
create trigger some_tab_stmt_trig
before update on some_tab execute function some_tab_stmt_trig_func();
explain (costs off)
update some_tab set f3 = 11 where f1 = 12 and f2 = 13;
update some_tab set f3 = 11 where f1 = 12 and f2 = 13;
drop table some_tab cascade;
drop function some_tab_stmt_trig_func();
-- Check inherited UPDATE with all children excluded -- Check inherited UPDATE with all children excluded
create table some_tab (a int, b int); create table some_tab (a int, b int);
create table some_tab_child () inherits (some_tab); create table some_tab_child () inherits (some_tab);

View File

@ -356,10 +356,11 @@ sub mkvcbuild
$pgregress_ecpg->AddFile('src/test/regress/pg_regress.c'); $pgregress_ecpg->AddFile('src/test/regress/pg_regress.c');
$pgregress_ecpg->AddIncludeDir('src/port'); $pgregress_ecpg->AddIncludeDir('src/port');
$pgregress_ecpg->AddIncludeDir('src/test/regress'); $pgregress_ecpg->AddIncludeDir('src/test/regress');
$pgregress_ecpg->AddIncludeDir('src/interfaces/libpq');
$pgregress_ecpg->AddDefine('HOST_TUPLE="i686-pc-win32vc"'); $pgregress_ecpg->AddDefine('HOST_TUPLE="i686-pc-win32vc"');
$pgregress_ecpg->AddLibrary('ws2_32.lib'); $pgregress_ecpg->AddLibrary('ws2_32.lib');
$pgregress_ecpg->AddDirResourceFile('src/interfaces/ecpg/test'); $pgregress_ecpg->AddDirResourceFile('src/interfaces/ecpg/test');
$pgregress_ecpg->AddReference($libpgcommon, $libpgport); $pgregress_ecpg->AddReference($libpq, $libpgcommon, $libpgport);
my $isolation_tester = my $isolation_tester =
$solution->AddProject('isolationtester', 'exe', 'misc'); $solution->AddProject('isolationtester', 'exe', 'misc');
@ -383,10 +384,11 @@ sub mkvcbuild
$pgregress_isolation->AddFile('src/test/regress/pg_regress.c'); $pgregress_isolation->AddFile('src/test/regress/pg_regress.c');
$pgregress_isolation->AddIncludeDir('src/port'); $pgregress_isolation->AddIncludeDir('src/port');
$pgregress_isolation->AddIncludeDir('src/test/regress'); $pgregress_isolation->AddIncludeDir('src/test/regress');
$pgregress_isolation->AddIncludeDir('src/interfaces/libpq');
$pgregress_isolation->AddDefine('HOST_TUPLE="i686-pc-win32vc"'); $pgregress_isolation->AddDefine('HOST_TUPLE="i686-pc-win32vc"');
$pgregress_isolation->AddLibrary('ws2_32.lib'); $pgregress_isolation->AddLibrary('ws2_32.lib');
$pgregress_isolation->AddDirResourceFile('src/test/isolation'); $pgregress_isolation->AddDirResourceFile('src/test/isolation');
$pgregress_isolation->AddReference($libpgcommon, $libpgport); $pgregress_isolation->AddReference($libpq, $libpgcommon, $libpgport);
# src/bin # src/bin
my $D; my $D;
@ -854,10 +856,11 @@ sub mkvcbuild
$pgregress->AddFile('src/test/regress/pg_regress.c'); $pgregress->AddFile('src/test/regress/pg_regress.c');
$pgregress->AddFile('src/test/regress/pg_regress_main.c'); $pgregress->AddFile('src/test/regress/pg_regress_main.c');
$pgregress->AddIncludeDir('src/port'); $pgregress->AddIncludeDir('src/port');
$pgregress->AddIncludeDir('src/interfaces/libpq');
$pgregress->AddDefine('HOST_TUPLE="i686-pc-win32vc"'); $pgregress->AddDefine('HOST_TUPLE="i686-pc-win32vc"');
$pgregress->AddLibrary('ws2_32.lib'); $pgregress->AddLibrary('ws2_32.lib');
$pgregress->AddDirResourceFile('src/test/regress'); $pgregress->AddDirResourceFile('src/test/regress');
$pgregress->AddReference($libpgcommon, $libpgport); $pgregress->AddReference($libpq, $libpgcommon, $libpgport);
# fix up pg_waldump once it's been set up # fix up pg_waldump once it's been set up
# files symlinked on Unix are copied on windows # files symlinked on Unix are copied on windows