diff options
236 files changed, 12003 insertions, 3296 deletions
diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index b71a625f2..23531973a 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -14,5 +14,11 @@ # # $ git log --pretty=format:"%H # %cd%n# %s" $PGINDENTGITHASH -1 --date=iso +89288109a11bff5ea62f39355d2a6a7efc856b6a # 2025-12-08 16:43:12 +0900 +# Run pgindent. + +a48d72c1682294386fb21b4d17689ac4afde738b # 2025-07-18 15:39:40 +0900 +# Fix indentation. + 468573ad3d19bee5634e362d17df357298d4b51a # 2025-07-17 19:15:48 +0900 # Run pgindent. diff --git a/configure.ac b/configure.ac index bd8283090..bc668a4f2 100644 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,5 @@ dnl Process this file with autoconf to produce a configure script. -AC_INIT([pgpool-II], [4.7devel], [pgpool-hackers@pgpool.net], [pgpool-II]) +AC_INIT([pgpool-II], [4.8devel], [pgpool-hackers@lists.postgresql.org], [pgpool-II]) dnl Checks for programs. AC_PROG_CC diff --git a/doc.ja/src/sgml/advanced.sgml b/doc.ja/src/sgml/advanced.sgml index e240ae310..79407e016 100644 --- a/doc.ja/src/sgml/advanced.sgml +++ b/doc.ja/src/sgml/advanced.sgml @@ -190,7 +190,7 @@ <!-- <title>Changing active/standby state when certain fault is detected</title> --> - <title>障害が検出された際のアクティブ/スタンバイ状態の切換</title> + <title>障害が検出された際のリーダー/スタンバイ状態の切換</title> <indexterm zone="tutorial-watchdog-changing-active"> <primary>WATCHDOG</primary> @@ -204,7 +204,7 @@ by voting and change active/standby state. --> <productname>Pgpool-II</productname>の障害が検出されると、watchdogは他のwatchdogにそのことを通知します。 - 障害が起きたのがアクティブな<productname>Pgpool-II</productname>であれば、watchdogは投票によって新しいアクティブ<productname>Pgpool-II</productname>を決定し、active/standby状態を変更します + 障害が起きたのがリーダー<productname>Pgpool-II</productname>であれば、watchdogは投票によって新しいリーダー<productname>Pgpool-II</productname>を決定し、active/standby状態を変更します </para> </sect2> @@ -225,8 +225,8 @@ <productname>Pgpool-II</productname> to work using the same IP address even when servers are switched. --> - スタンバイ<productname>Pgpool-II</productname>サーバが昇格すると、新しいアクティブサーバは仮想IPインターフェイスを立ち上げます。 - 一方、以前のアクティブサーバは、仮想IPインターフェイスを停止します。 + スタンバイ<productname>Pgpool-II</productname>サーバが昇格すると、新しいリーダーサーバは仮想IPインターフェイスを立ち上げます。 + 一方、以前のリーダーサーバは、仮想IPインターフェイスを停止します。 これにより、サーバが切り替わっても<productname>Pgpool-II</productname>は同じIPアドレスを使うことができます。 </para> </sect2> @@ -784,7 +784,7 @@ --> クエリモードでは、PostgreSQLサーバの障害やpcp_detach_nodeによってすべてのDBノードが<productname>Pgpool-II</productname>から切り離されると、watchdogは<productname>Pgpool-II</productname>サービスが停止状態にあるとみなし、watchdogに割り当てられた仮想IPを停止します。 ですので、<productname>Pgpool-II</productname>のクライアントは仮想IPを使って<productname>Pgpool-II</productname>に接続できなくなります。 - これは、複数のアクティブ<productname>Pgpool-II</productname>が存在するスプリットブレインを回避するために必要です。 + これは、複数のリーダー<productname>Pgpool-II</productname>が存在するスプリットブレインを回避するために必要です。 </para> </sect2> @@ -844,7 +844,7 @@ brought down before a down notification packet is sent to other <productname>Pgpool-II</productname>. --> - 停止通知パケットが他の<productname>Pgpool-II</productname>に送られる前に、以前の仮想IPが停止したことを確認するので、アクティブ<productname>Pgpool-II</productname>が停止してからスタンバイ<productname>Pgpool-II</productname>が新しいアクティブに昇格するまでには数秒を要します。 + 停止通知パケットが他の<productname>Pgpool-II</productname>に送られる前に、以前の仮想IPが停止したことを確認するので、リーダー<productname>Pgpool-II</productname>が停止してからスタンバイ<productname>Pgpool-II</productname>が新しいリーダーに昇格するまでには数秒を要します。 </para> </sect2> </sect1> diff --git a/doc.ja/src/sgml/connection-pooling.sgml b/doc.ja/src/sgml/connection-pooling.sgml index e9c8253c7..07af0fcd4 100644 --- a/doc.ja/src/sgml/connection-pooling.sgml +++ b/doc.ja/src/sgml/connection-pooling.sgml @@ -1356,7 +1356,7 @@ local0.* /var/log/pgpool.log fork and exit status. Default is on. --> onに設定されている場合、PCPプロセスの正常なforkあるいはexitした状態をログに出力します。 - デフォルトはonです。 + デフォルトはoffです。 </para> <para> <!-- diff --git a/doc.ja/src/sgml/connection-settings.sgml b/doc.ja/src/sgml/connection-settings.sgml index 0a39e05ff..d70788340 100644 --- a/doc.ja/src/sgml/connection-settings.sgml +++ b/doc.ja/src/sgml/connection-settings.sgml @@ -1660,29 +1660,6 @@ backend_clustering_mode = logical_replication </para> </sect2> - <sect2 id="runtime-config-slony-mode"> - <title>Slonyモード</title> - - <para> - このモードでは<productname>Pgpool-II</productname>を<acronym>Slony-I</acronym>と組み合わせて使用します。 - Slony-Iが実際にデータのレプリケーションを行います。 - このモードを有効にするには<varname>backend_clustering_mode</varname>にslonyを設定してください。 - <programlisting> -backend_clustering_mode = slony - </programlisting> - このモードでは127台までのレプリカサーバを使用できます。 - また、レプリカサーバをまったく使用しないことも可能です。 - </para> - <para> - このモードの難点は、検索問い合わせを負荷分散させた時に、スタンバイサーバのレプリケーション遅延を意識しなければならない点です。 - ノードをまたがる可視性の一貫性も保証されません。 - また、DDLやラージオブジェクトなど、一部のデータオブジェクトはレプリケーションされません。 - </para> - <para> - ストリーミングレプリケーションやロジカルレプリケーションが登場後、Slony-Iを新規に採用するシステムは少ないので、特に理由がない限りこのモードを使用することはお勧めしません。 - </para> - </sect2> - <sect2 id="guc-raw-mode" xreflabel="rawモード"> <title>rawモード</title> <para> diff --git a/doc.ja/src/sgml/example-cluster.sgml b/doc.ja/src/sgml/example-cluster.sgml index 2950c59c5..bd0f1d0f1 100644 --- a/doc.ja/src/sgml/example-cluster.sgml +++ b/doc.ja/src/sgml/example-cluster.sgml @@ -7,8 +7,7 @@ この設定例では、3台の<productname>Pgpool-II</productname>を使って<productname>PostgreSQL</productname>(プライマリ1台、スタンバイ2台)を管理し、単一障害点やスプリットブレインの起きない堅牢なクラスタを運用することが可能です。 </para> <para> - この設定例では<emphasis><productname>PostgreSQL</productname> 17</emphasis>を使っていますが、 - 各種スクリプトは<productname>PostgreSQL</productname> 10以降での動作確認を行っています。 + この設定例では<emphasis><productname>PostgreSQL</productname> 18</emphasis>を使っています。 </para> <sect2 id="example-cluster-requirement"> <title>前提条件</title> @@ -22,7 +21,7 @@ <title>全体構成</title> <para> 今回は、Linuxサーバを3台用意し、それぞれのホスト名は<literal>server1</literal>、<literal>server2</literal>、<literal>server3</literal>とします。 - 使用するOSはすべて<emphasis>Rocky Linux 9</emphasis>とします。 + 使用するOSはすべて<emphasis>Rocky Linux 10</emphasis>とします。 それぞれのサーバに<productname>PostgreSQL</productname>と<productname>Pgpool-II</productname>をインストールします。 3台の<productname>PostgreSQL</productname>がストリーミングレプリケーション構成になります。全体構成図は以下の通りです。 </para> @@ -83,7 +82,7 @@ <tbody> <row> <entry>PostgreSQLバージョン</entry> - <entry>17.0</entry> + <entry>18.0</entry> <entry>-</entry> </row> <row> @@ -93,7 +92,7 @@ </row> <row> <entry>$PGDATA</entry> - <entry>/var/lib/pgsql/17/data</entry> + <entry>/var/lib/pgsql/18/data</entry> <entry>-</entry> </row> <row> @@ -131,7 +130,7 @@ <tbody> <row> <entry>Pgpool-IIバージョン</entry> - <entry>4.6.0</entry> + <entry>4.6.1</entry> <entry>-</entry> </row> <row> @@ -228,9 +227,9 @@ <productname>PostgreSQL</productname>のインストールは<productname>PostgreSQL</productname>コミュニティのリポジトリを使います。 </para> <programlisting> -[全サーバ]# dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-9-x86_64/pgdg-redhat-repo-latest.noarch.rpm +[全サーバ]# dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-10-x86_64/pgdg-redhat-repo-latest.noarch.rpm [全サーバ]# dnf -qy module disable postgresql -[全サーバ]# dnf install -y postgresql17-server +[全サーバ]# dnf install -y postgresql18-server </programlisting> <para> @@ -252,6 +251,10 @@ exclude=pgpool* +[pgdg18] +... +exclude=pgpool* + [pgdg17] ... exclude=pgpool* @@ -271,10 +274,6 @@ exclude=pgpool* [pgdg13] ... exclude=pgpool* - -[pgdg12] -... -exclude=pgpool* </programlisting> <para> @@ -284,8 +283,8 @@ exclude=pgpool* </para> <programlisting> -[全サーバ]# dnf install -y https://www.pgpool.net/yum/rpms/4.6/redhat/rhel-9-x86_64/pgpool-II-release-4.6-1.noarch.rpm -[全サーバ]# dnf install -y --enablerepo=crb pgpool-II-pg17-* +[全サーバ]# dnf install -y https://www.pgpool.net/yum/rpms/4.6/redhat/rhel-10-x86_64/pgpool-II-release-4.6-1.noarch.rpm +[全サーバ]# dnf install -y --enablerepo=crb pgpool-II-pg18-* </programlisting> </sect2> @@ -350,7 +349,7 @@ PubkeyAuthentication yes <title>firewallの設定</title> <para> <productname>Pgpool-II</productname>や<productname>PostgreSQL</productname>に接続する際には、ファイアーウォールによって目的のポートが開けられていなければなりません。 - <systemitem>Rocky Linux 9/RHEL 9</systemitem>の場合、以下のように設定します。 + <systemitem>Rocky Linux 10/RHEL 10</systemitem>の場合、以下のように設定します。 </para> <programlisting> [全サーバ]# firewall-cmd --permanent --zone=public --add-service=postgresql @@ -366,16 +365,16 @@ PubkeyAuthentication yes </para> <para> まず、データベースクラスタの初期化を行います。 - <productname>PostgreSQL</productname> 17ではデータベースクラスタのデフォルトの作成先は<filename>/var/lib/pgsql/17/data</filename>で、<literal>postgres</literal>ユーザの設定ファイル<filename>~/.bash_profile</filename>で環境変数<varname>PGDATA</varname>に指定されています。 + <productname>PostgreSQL</productname> 18ではデータベースクラスタのデフォルトの作成先は<filename>/var/lib/pgsql/18/data</filename>で、<literal>postgres</literal>ユーザの設定ファイル<filename>~/.bash_profile</filename>で環境変数<varname>PGDATA</varname>に指定されています。 必要に応じて変更してください。 </para> <para> <command>initdb</command>コマンドを実行して、データベースクラスタの初期化を行います。 - 必要に応じて、<literal>--encoding</literal>や<literal>--locale</literal><ulink url="https://www.postgresql.org/docs/17/app-initdb.html">オプション</ulink>を指定して、データベースのエンコーディングやロケールを設定してください。 + 必要に応じて、<literal>--encoding</literal>や<literal>--locale</literal><ulink url="https://www.postgresql.org/docs/18/app-initdb.html">オプション</ulink>を指定して、データベースのエンコーディングやロケールを設定してください。 </para> <programlisting> [root@server1 ~]# su - postgres -[postgres@server1 ~]$ /usr/pgsql-17/bin/initdb +[postgres@server1 ~]$ /usr/pgsql-18/bin/initdb </programlisting> <para> @@ -391,7 +390,7 @@ wal_log_hints = on 最後に、<literal>server1</literal>で<productname>PostgreSQL</productname>を起動します。 </para> <programlisting> -[postgres@server1 ~]$ /usr/pgsql-17/bin/pg_ctl start +[postgres@server1 ~]$ /usr/pgsql-18/bin/pg_ctl start </programlisting> </sect3> @@ -402,16 +401,38 @@ wal_log_hints = on <itemizedlist> <listitem> <para> - スタンバイで<command>pg_basebackup</command>を実行して、プライマリのデータディレクトリのバックアップを生成します。(この方法を利用する場合は、手動でレプリケーションスロットを作成してください。) + <productname>Pgpool-II</productname>のオンラインリカバリ機能(<xref linkend="runtime-online-recovery">)を使用して、スタンバイサーバを自動的にセットアップします。 </para> </listitem> <listitem> <para> - <productname>Pgpool-II</productname>のオンラインリカバリ機能(<xref linkend="runtime-online-recovery">)を使用して、スタンバイサーバを自動的にセットアップします。 + スタンバイで<command>pg_basebackup</command>を実行して、プライマリのデータディレクトリのバックアップを生成します。 </para> </listitem> </itemizedlist> </para> + <note> + <para> + オンラインリカバリを使用せず手動でスタンバイをセットアップする場合は次の注意点があります。 + <itemizedlist> + <listitem> + <para> + 手動でレプリケーションスロットを作成する必要があります。 + </para> + </listitem> + </itemizedlist> + <itemizedlist> + <listitem> + <para> + pg_basebackup を実行する際には -R オプションを指定しないでください。<varname>primary_conninfo</varname>、 <varname>recovery_target_timeline</varname>、 <varname>primary_slot_name</varname> は <filename>postgresql.auto.conf</filename> ではなく、<filename>$PGDATA/myrecovery.conf</filename> に記載し、<filename>postgresql.conf</filename> に以下を追記してください。 + </para> + </listitem> + </itemizedlist> + <programlisting> +include_if_exists = 'myrecovery.conf' + </programlisting> + </para> + </note> <para> この設定例では、<productname>Pgpool-II</productname>の構成が完了した後に、<xref linkend="example-cluster-verify-standby">で<productname>Pgpool-II</productname>のオンラインリカバリを使用してスタンバイサーバをセットアップします。 </para> @@ -703,19 +724,19 @@ health_check_max_retries = 3 backend_hostname0 = 'server1' backend_port0 = 5432 backend_weight0 = 1 -backend_data_directory0 = '/var/lib/pgsql/17/data' +backend_data_directory0 = '/var/lib/pgsql/18/data' backend_flag0 = 'ALLOW_TO_FAILOVER' backend_hostname1 = 'server2' backend_port1 = 5432 backend_weight1 = 1 -backend_data_directory1 = '/var/lib/pgsql/17/data' +backend_data_directory1 = '/var/lib/pgsql/18/data' backend_flag1 = 'ALLOW_TO_FAILOVER' backend_hostname2 = 'server3' backend_port2 = 5432 backend_weight2 = 1 -backend_data_directory2 = '/var/lib/pgsql/17/data' +backend_data_directory2 = '/var/lib/pgsql/18/data' backend_flag2 = 'ALLOW_TO_FAILOVER' </programlisting> @@ -769,8 +790,8 @@ follow_primary_command = '/etc/pgpool-II/follow_primary.sh %d %h %p %D %m %H %M </para> </note> <para> - サンプルスクリプト<ulink url="https://git.postgresql.org/gitweb/?p=pgpool2.git;a=blob_plain;f=src/sample/scripts/failover.sh.sample;hb=refs/heads/V4_6_STABLE">failover.sh</ulink>及び - <ulink url="https://git.postgresql.org/gitweb/?p=pgpool2.git;a=blob_plain;f=src/sample/scripts/follow_primary.sh.sample;hb=refs/heads/V4_6_STABLE">follow_primary.sh</ulink>は + サンプルスクリプト<ulink url="https://raw.githubusercontent.com/pgpool/pgpool2/refs/heads/master/src/sample/scripts/failover.sh.sample">failover.sh</ulink>及び + <ulink url="https://raw.githubusercontent.com/pgpool/pgpool2/refs/heads/master/src/sample/scripts/follow_primary.sh.sample">follow_primary.sh</ulink>は <filename>/etc/pgpool-II/</filename>配下にインストールされていますので、これらのファイルをコピーして作成します。 </para> <programlisting> @@ -784,12 +805,12 @@ follow_primary_command = '/etc/pgpool-II/follow_primary.sh %d %h %p %D %m %H %M <programlisting> [root@server1 ~]# vi /etc/pgpool-II/failover.sh ... -PGHOME=/usr/pgsql-17 +PGHOME=/usr/pgsql-18 ... [root@server1 ~]# vi /etc/pgpool-II/follow_primary.sh ... -PGHOME=/usr/pgsql-17 +PGHOME=/usr/pgsql-18 ... </programlisting> <para> @@ -827,8 +848,8 @@ recovery_password = '' recovery_1st_stage_command = 'recovery_1st_stage' </programlisting> <para> - オンラインリカバリ用のサンプルスクリプト<ulink url="https://git.postgresql.org/gitweb/?p=pgpool2.git;a=blob_plain;f=src/sample/scripts/recovery_1st_stage.sample;hb=refs/heads/V4_6_STABLE">recovery_1st_stage</ulink> - 及び<ulink url="https://git.postgresql.org/gitweb/?p=pgpool2.git;a=blob_plain;f=src/sample/scripts/pgpool_remote_start.sample;hb=refs/heads/V4_6_STABLE">pgpool_remote_start</ulink>は + オンラインリカバリ用のサンプルスクリプト<ulink url="https://raw.githubusercontent.com/pgpool/pgpool2/refs/heads/master/src/sample/scripts/recovery_1st_stage.sample">recovery_1st_stage</ulink> + 及び<ulink url="https://raw.githubusercontent.com/pgpool/pgpool2/refs/heads/master/src/sample/scripts/pgpool_remote_start.sample">pgpool_remote_start</ulink>は <filename>/etc/pgpool-II/</filename>配下にインストールされていますので、 これらのファイルをプライマリサーバ(<literal>server1</literal>)のデータベースクラスタ配下に配置します。 </para> @@ -840,14 +861,14 @@ recovery_1st_stage_command = 'recovery_1st_stage' 基本的には<emphasis>PGHOME</emphasis>を環境に合わせて変更すれば、動作します。 </para> <programlisting> -[root@server1 ~]# vi /var/lib/pgsql/17/data/recovery_1st_stage +[root@server1 ~]# vi /var/lib/pgsql/18/data/recovery_1st_stage ... -PGHOME=/usr/pgsql-17 +PGHOME=/usr/pgsql-18 ... -[root@server1 ~]# vi /var/lib/pgsql/17/data/pgpool_remote_start +[root@server1 ~]# vi /var/lib/pgsql/18/data/pgpool_remote_start ... -PGHOME=/usr/pgsql-17 +PGHOME=/usr/pgsql-18 ... </programlisting> @@ -1057,7 +1078,7 @@ wd_heartbeat_deadtime = 30 wd_escalation_command = '/etc/pgpool-II/escalation.sh' </programlisting> <para> - サンプルスクリプト<ulink url="https://git.postgresql.org/gitweb/?p=pgpool2.git;a=blob_plain;f=src/sample/scripts/escalation.sh.sample;hb=refs/heads/V4_6_STABLE">escalation.sh</ulink>は + サンプルスクリプト<ulink url="https://raw.githubusercontent.com/pgpool/pgpool2/refs/heads/master/src/sample/scripts/escalation.sh.sample">escalation.sh</ulink>は <filename>/etc/pgpool-II/</filename>配下にインストールされています。 </para> <programlisting> @@ -1103,7 +1124,7 @@ CIDR_NETMASK=24 <programlisting> log_destination = 'stderr' logging_collector = on -log_directory = '/var/log/pgpool_log' +log_directory = '/var/log/pgpool' log_filename = 'pgpool-%a.log' log_truncate_on_rotation = on log_rotation_age = 1d @@ -1141,7 +1162,7 @@ log_rotation_age = 1d <productname>PostgreSQL</productname>プライマリサーバがまだ起動していない場合は、まず次のコマンドを実行して<productname>PostgreSQL</productname>起動します。 </para> <programlisting> -[root@server1 ~]# su - postgres -c "/usr/pgsql-17/bin/pg_ctl start" +[root@server1 ~]# su - postgres -c "/usr/pgsql-18/bin/pg_ctl start" </programlisting> <para> <literal>server1</literal>、<literal>server2</literal>および<literal>server3</literal>で以下のコマンドを実行し、<productname>Pgpool-II</productname>を起動します。 @@ -1282,7 +1303,7 @@ Password for user pgpool: フェイルオーバするかどうか確認してみます。 </para> <programlisting> -[root@server1 ~]# su - postgres -c "/usr/pgsql-17/bin/pg_ctl -m immediate stop" +[root@server1 ~]# su - postgres -c "/usr/pgsql-18/bin/pg_ctl -m immediate stop" </programlisting> <para> <literal>ノード1</literal>を停止した後に、フェイルオーバが発生し、<literal>server2</literal>が diff --git a/doc.ja/src/sgml/example-replication-si-mode.sgml b/doc.ja/src/sgml/example-replication-si-mode.sgml index 2915ccbb8..7c27df3e6 100644 --- a/doc.ja/src/sgml/example-replication-si-mode.sgml +++ b/doc.ja/src/sgml/example-replication-si-mode.sgml @@ -16,8 +16,7 @@ レプリケーションを行う点はネイティブレプリケーションモードと同じです。 </para> <para> - この設定例では<productname>PostgreSQL</productname> 15を使っていますが、 - 各種スクリプトは<productname>PostgreSQL</productname> 10以降での動作確認を行っています。 + この設定例では<productname>PostgreSQL</productname> 18を使っています。 </para> <sect2 id="example-replication-mode-structure"> @@ -26,7 +25,7 @@ この設定例では、Pgpool-II 1台、PostgreSQL 3台を用いて、Pgpool-IIのレプリケーション機能を説明します。 </para> <para> - 物理サーバを3台用意し、それぞれのホスト名は 「server1」、「server2」、「server3」 とします。使用するOSはすべてCentOS 7.9とします。 + 物理サーバを3台用意し、それぞれのホスト名は 「server1」、「server2」、「server3」 とします。使用するOSはすべてRocky Linux 10とします。 それぞれのサーバにPostgreSQLをインストールし、その中の1台にPgpool-IIをインストールします。 </para> <para> @@ -78,7 +77,7 @@ <tbody> <row> <entry>PostgreSQLバージョン</entry> - <entry>15.0</entry> + <entry>18.0</entry> <entry>-</entry> </row> <row> @@ -88,7 +87,7 @@ </row> <row> <entry>$PGDATA</entry> - <entry>/var/lib/pgsql/15/data</entry> + <entry>/var/lib/pgsql/18/data</entry> <entry>-</entry> </row> <row> @@ -113,7 +112,7 @@ <tbody> <row> <entry>Pgpool-IIバージョン</entry> - <entry>4.3.0</entry> + <entry>4.6.1</entry> <entry>-</entry> </row> <row> @@ -158,8 +157,8 @@ <productname>PostgreSQL</productname>のインストールは<productname>PostgreSQL</productname>コミュニティのリポジトリを使います。 </para> <programlisting> -[全サーバ]# yum install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm -[全サーバ]# yum install -y postgresql15-server +[全サーバ]# yum install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-10-x86_64/pgdg-redhat-repo-latest.noarch.rpm +[全サーバ]# yum install -y postgresql18-server </programlisting> <para> @@ -181,27 +180,27 @@ exclude=pgpool* -[pgdg15] +[pgdg18] ... exclude=pgpool* -[pgdg14] +[pgdg17] ... exclude=pgpool* -[pgdg13] +[pgdg16] ... exclude=pgpool* -[pgdg12] +[pgdg15] ... exclude=pgpool* -[pgdg11] +[pgdg14] ... exclude=pgpool* -[pgdg10] +[pgdg13] ... exclude=pgpool* </programlisting> @@ -210,8 +209,8 @@ exclude=pgpool* <productname>Pgpool-II</productname>をインストールします。 </para> <programlisting> -[全サーバ]# yum install -y https://www.pgpool.net/yum/rpms/4.4/redhat/rhel-7-x86_64/pgpool-II-release-4.4-1.noarch.rpm -[全サーバ]# yum install -y pgpool-II-pg15-* +[全サーバ]# yum install -y https://www.pgpool.net/yum/rpms/4.6/redhat/rhel-10-x86_64/pgpool-II-release-4.6-1.noarch.rpm +[全サーバ]# yum install -y pgpool-II-pg18-* </programlisting> </sect2> @@ -221,16 +220,6 @@ exclude=pgpool* PostgreSQL、Pgpool-IIの設定の前に、以下の設定を行います。 </para> - <sect3 id="example-replication-mode-postgres-password"> - <title>postgresユーザパスワードの設定</title> - <para> - 全サーバで以下のコマンドを実行し、<literal>postgres</literal>ユーザのパスワードの設定を行います。 - </para> - <programlisting> -[全サーバ]# passwd postgres - </programlisting> - </sect3> - <sect3 id="example-replication-mode-ssh"> <title>SSHの設定</title> <para> @@ -240,19 +229,42 @@ exclude=pgpool* </para> <programlisting> [全サーバ]# su - postgres -[全サーバ]$ cd ~/.ssh -[全サーバ]$ ssh-keygen -t rsa -f id_rsa_pgpool -[全サーバ]$ ssh-copy-id -i id_rsa_pgpool.pub postgres@server1 -[全サーバ]$ ssh-copy-id -i id_rsa_pgpool.pub postgres@server2 -[全サーバ]$ ssh-copy-id -i id_rsa_pgpool.pub postgres@server3 - </programlisting> - <para> - 設定後、<literal>postgres</literal>ユーザで、 - <command>ssh postgres@serverX -i ~/.ssh/id_rsa_pgpool</command>コマンドを実行し、 - パスワード入力せずログインできることを確認してください。 - 必要に応じて<filename>/etc/ssh/sshd_config</filename>を編集し、 - <systemitem>sshd</systemitem>を再起動してください。 - </para> +[全サーバ]$ mkdir ~/.ssh && chmod 700 ~/.ssh +[全サーバ]$ ssh-keygen -t rsa -f ~/.ssh/id_rsa_pgpool + </programlisting> + <para> + 次に、公開鍵<literal>id_rsa_pgpool.pub</literal>を各サーバの<filename>/var/lib/pgsql/.ssh/authorized_keys</filename>ファイルに追加します。 + </para> + <para> + 設定後、<literal>postgres</literal>ユーザで<command>ssh postgres@serverX -i ~/.ssh/id_rsa_pgpool</command>コマンドを実行し、パスワードなしでログインできることを確認してください。 + </para> + + <note> + <para> + 公開鍵認証によるログインに失敗した場合には、以下を確認してください。 + <itemizedlist> + <listitem> + <para> + <filename>/etc/ssh/sshd_config</filename>で公開鍵認証が許可されていることを確認します。 + </para> + </listitem> + </itemizedlist> + <programlisting> +PubkeyAuthentication yes + </programlisting> + <itemizedlist> + <listitem> + <para> + SELinuxを有効化している場合は、SSH公開鍵認証(パスワードなし)が失敗する可能性があるので、すべてのサーバで以下のコマンドを実行する必要があります。 + </para> + </listitem> + </itemizedlist> + <programlisting> +[全サーバ]# su - postgres +[全サーバ]$ restorecon -Rv ~/.ssh + </programlisting> + </para> + </note> </sect3> <sect3 id="example-replication-mode-pgpass"> @@ -265,7 +277,7 @@ exclude=pgpool* </para> <programlisting> [全サーバ]# su - postgres -[全サーバ]$ vi /var/lib/pgsql/.pgpass +[全サーバ]$ vi ~/.pgpass (以下を追加) server1:5432:replication:repl:<replユーザのパスワード> server2:5432:replication:repl:<replユーザのパスワード> @@ -273,7 +285,7 @@ server3:5432:replication:repl:<replユーザのパスワード> server1:5432:postgres:postgres:<postgresユーザのパスワード> server2:5432:postgres:postgres:<postgresユーザのパスワード> server3:5432:postgres:postgres:<postgresユーザのパスワード> -[全サーバ]$ chmod 600 /var/lib/pgsql/.pgpass +[全サーバ]$ chmod 600 ~/.pgpass </programlisting> </sect3> @@ -282,7 +294,7 @@ server3:5432:postgres:postgres:<postgresユーザのパスワード> <para> <productname>Pgpool-II</productname>や<productname>PostgreSQL</productname>に接続する際には、 ファイアーウォールによって目的のポートが開けられていなければなりません。 - <systemitem>CentOS/RHEL7</systemitem>の場合、以下のように設定します。 + <systemitem>Rocky Linux 10/RHEL 10</systemitem>の場合、以下のように設定します。 </para> <programlisting> [全サーバ]# firewall-cmd --permanent --zone=public --add-service=postgresql @@ -319,7 +331,7 @@ server3:5432:postgres:postgres:<postgresユーザのパスワード> </para> <programlisting> [server1]# su - postgres -[server1]$ /usr/pgsql-15/bin/initdb -E UTF8 --no-locale +[server1]$ /usr/pgsql-18/bin/initdb -E UTF8 --no-locale </programlisting> <para> 次に<literal>server1</literal>にて、設定ファイル<filename>$PGDATA/postgresql.conf</filename>を以下のように編集します。 @@ -348,7 +360,7 @@ host replication all samenet scram-sha-256 server1で以下のコマンドを実行し、PostgreSQLを起動します。 </para> <programlisting> -[server1]$ /usr/pgsql-15/bin/pg_ctl start +[server1]$ /usr/pgsql-18/bin/pg_ctl start </programlisting> <para> @@ -498,19 +510,19 @@ health_check_max_retries = 3 backend_hostname0 = 'server1' backend_port0 = 5432 backend_weight0 = 1 -backend_data_directory0 = '/var/lib/pgsql/15/data' +backend_data_directory0 = '/var/lib/pgsql/18/data' backend_flag0 = 'ALLOW_TO_FAILOVER' backend_hostname1 = 'server2' backend_port1 = 5432 backend_weight1 = 1 -backend_data_directory1 = '/var/lib/pgsql/15/data' +backend_data_directory1 = '/var/lib/pgsql/18/data' backend_flag1 = 'ALLOW_TO_FAILOVER' backend_hostname2 = 'server3' backend_port2 = 5432 backend_weight2 = 1 -backend_data_directory2 = '/var/lib/pgsql/15/data' +backend_data_directory2 = '/var/lib/pgsql/18/data' backend_flag2 = 'ALLOW_TO_FAILOVER' </programlisting> </sect3> @@ -534,35 +546,35 @@ recovery_1st_stage_command = 'recovery_1st_stage.sh' recovery_2nd_stage_command = 'recovery_2nd_stage.sh' </programlisting> <para> - ネイティブレプリケーションモード/スナップショットアイソレーションモード専用のオンラインリカバリ用のサンプルスクリプト<ulink url="https://git.postgresql.org/gitweb/?p=pgpool2.git;a=blob_plain;f=src/sample/scripts/replication_mode_recovery_1st_stage.sample;hb=refs/heads/V4_4_STABLE">replication_mode_recovery_1st_stage.sample</ulink>、 - <ulink url="https://git.postgresql.org/gitweb/?p=pgpool2.git;a=blob_plain;f=src/sample/scripts/replication_mode_recovery_2nd_stage.sample;hb=refs/heads/V4_4_STABLE">replication_mode_recovery_2nd_stage.sample</ulink> - 及び<ulink url="https://git.postgresql.org/gitweb/?p=pgpool2.git;a=blob_plain;f=src/sample/scripts/pgpool_remote_start.sample;hb=refs/heads/V4_4_STABLE">pgpool_remote_start.sample</ulink>は + ネイティブレプリケーションモード/スナップショットアイソレーションモード専用のオンラインリカバリ用のサンプルスクリプト<ulink url="https://raw.githubusercontent.com/pgpool/pgpool2/refs/heads/master/src/sample/scripts/replication_mode_recovery_1st_stage.sample">replication_mode_recovery_1st_stage.sample</ulink>、 + <ulink url="https://raw.githubusercontent.com/pgpool/pgpool2/refs/heads/master/src/sample/scripts/replication_mode_recovery_2nd_stage.sample">replication_mode_recovery_2nd_stage.sample</ulink> + 及び<ulink url="https://raw.githubusercontent.com/pgpool/pgpool2/refs/heads/master/src/sample/scripts/pgpool_remote_start.sample">pgpool_remote_start.sample</ulink>は <filename>/etc/pgpool-II/</filename>配下にインストールされていますので、 これらのファイルをmainノード(<literal>server1</literal>)のデータベースクラスタ配下に配置します。 </para> <programlisting> -[server1]# cp -p /etc/pgpool-II/sample_scripts/replication_mode_recovery_1st_stage.sample /var/lib/pgsql/15/data/recovery_1st_stage.sh -[server1]# cp -p /etc/pgpool-II/sample_scripts/replication_mode_recovery_2nd_stage.sample /var/lib/pgsql/15/data/recovery_2nd_stage.sh -[server1]# cp -p /etc/pgpool-II/sample_scripts/pgpool_remote_start.sample /var/lib/pgsql/15/data/pgpool_remote_start -[server1]# chown postgres:postgres /var/lib/pgsql/15/data/{recovery_1st_stage.sh,recovery_2nd_stage.sh,pgpool_remote_start} +[server1]# cp -p /etc/pgpool-II/sample_scripts/replication_mode_recovery_1st_stage.sample /var/lib/pgsql/18/data/recovery_1st_stage.sh +[server1]# cp -p /etc/pgpool-II/sample_scripts/replication_mode_recovery_2nd_stage.sample /var/lib/pgsql/18/data/recovery_2nd_stage.sh +[server1]# cp -p /etc/pgpool-II/sample_scripts/pgpool_remote_start.sample /var/lib/pgsql/18/data/pgpool_remote_start +[server1]# chown postgres:postgres /var/lib/pgsql/18/data/{recovery_1st_stage.sh,recovery_2nd_stage.sh,pgpool_remote_start} </programlisting> <para> 基本的には<emphasis>PGHOME</emphasis>を環境に合わせて変更すれば、動作します。 </para> <programlisting> -[server1]# vi /var/lib/pgsql/15/data/recovery_1st_stage.sh +[server1]# vi /var/lib/pgsql/18/data/recovery_1st_stage.sh ... -PGHOME=/usr/pgsql-15 +PGHOME=/usr/pgsql-18 ... -[server1]# vi /var/lib/pgsql/15/data/recovery_2nd_stage.sh +[server1]# vi /var/lib/pgsql/18/data/recovery_2nd_stage.sh ... -PGHOME=/usr/pgsql-15 +PGHOME=/usr/pgsql-18 ... -[server1]# vi /var/lib/pgsql/15/data/pgpool_remote_start +[server1]# vi /var/lib/pgsql/18/data/pgpool_remote_start ... -PGHOME=/usr/pgsql-15 +PGHOME=/usr/pgsql-18 ... </programlisting> @@ -675,7 +687,7 @@ postgres:AESHs/pWL5rtXy2IwuzroHfqg== <programlisting> log_destination = 'stderr' logging_collector = on -log_directory = '/var/log/pgpool_log' +log_directory = '/var/log/pgpool' log_filename = 'pgpool-%Y-%m-%d_%H%M%S.log' log_truncate_on_rotation = on log_rotation_age = 1d @@ -765,15 +777,15 @@ Password for user pgpool: pgbenchを使って、レプリケーション機能を試してみましょう。 </para> <programlisting> -[server1]# /usr/pgsql-15/bin/createdb test -U postgres -p 9999 -[server1]# /usr/pgsql-15/bin/pgbench -h server1 -U postgres -i -p 9999 test +[server1]# /usr/pgsql-18/bin/createdb test -U postgres -p 9999 +[server1]# /usr/pgsql-18/bin/pgbench -h server1 -U postgres -i -p 9999 test </programlisting> <para> <productname>Pgpool-II</productname>のレプリケーション機能が正しく動いているかどうか確かめるために、 それぞれのノードに接続して、同じ結果を返すかどうか見てみます。 </para> <programlisting> -[server1]# /usr/pgsql-15/bin/psql -h server1 -U postgres -p 5432 test +[server1]# /usr/pgsql-18/bin/psql -h server1 -U postgres -p 5432 test test=# \d List of relations Schema | Name | Type | Owner @@ -784,7 +796,7 @@ test=# \d public | pgbench_tellers | table | postgres (4 rows) -[server1]# /usr/pgsql-15/bin/psql -h server2 -U postgres -p 5432 test +[server1]# /usr/pgsql-18/bin/psql -h server2 -U postgres -p 5432 test test=# \d List of relations Schema | Name | Type | Owner @@ -795,7 +807,7 @@ test=# \d public | pgbench_tellers | table | postgres (4 rows) -[server1]# /usr/pgsql-15/bin/psql -h server3 -U postgres -p 5432 test +[server1]# /usr/pgsql-18/bin/psql -h server3 -U postgres -p 5432 test test=# \d List of relations Schema | Name | Type | Owner @@ -813,27 +825,27 @@ test=# \d 次に、pgbenchをしばらく走らせて、結果を見てみます。 </para> <programlisting> -[server1]# /usr/pgsql-15/bin/pgbench -h server1 -U postgres -p 9999 -T 10 test +[server1]# /usr/pgsql-18/bin/pgbench -h server1 -U postgres -p 9999 -T 10 test </programlisting> <para> すべてのPostgreSQLは、同一の結果を返しています。 </para> <programlisting> -[server1]# /usr/pgsql-15/bin/psql -h server1 -U postgres -p 5432 test -c "SELECT sum(abalance) FROM pgbench_accounts" +[server1]# /usr/pgsql-18/bin/psql -h server1 -U postgres -p 5432 test -c "SELECT sum(abalance) FROM pgbench_accounts" Password for user postgres: sum -------- -99710 (1 row) -[server1]# /usr/pgsql-15/bin/psql -h server2 -U postgres -p 5432 test -c "SELECT sum(abalance) FROM pgbench_accounts" +[server1]# /usr/pgsql-18/bin/psql -h server2 -U postgres -p 5432 test -c "SELECT sum(abalance) FROM pgbench_accounts" Password for user postgres: sum -------- -99710 (1 row) -[server1]# /usr/pgsql-15/bin/psql -h server3 -U postgres -p 5432 test -c "SELECT sum(abalance) FROM pgbench_accounts" +[server1]# /usr/pgsql-18/bin/psql -h server3 -U postgres -p 5432 test -c "SELECT sum(abalance) FROM pgbench_accounts" Password for user postgres: sum -------- @@ -849,7 +861,7 @@ Password for user postgres: mainノードの切り替えを確認してみます。 </para> <programlisting> -[server1]# su - postgres -c "/usr/pgsql-15/bin/pg_ctl -m i stop" +[server1]# su - postgres -c "/usr/pgsql-18/bin/pg_ctl -m i stop" </programlisting> <para> <literal>ノード0</literal>を停止した後に、ノード0が切り離されて、mainノードの切り替えが発生することを確認します。 diff --git a/doc.ja/src/sgml/filelist.sgml b/doc.ja/src/sgml/filelist.sgml index bd4b3f77d..ea205e2fb 100644 --- a/doc.ja/src/sgml/filelist.sgml +++ b/doc.ja/src/sgml/filelist.sgml @@ -53,6 +53,7 @@ <!-- appendixes --> <!ENTITY release SYSTEM "release.sgml"> +<!ENTITY release-4.7 SYSTEM "release-4.7.sgml"> <!ENTITY release-4.6 SYSTEM "release-4.6.sgml"> <!ENTITY release-4.5 SYSTEM "release-4.5.sgml"> <!ENTITY release-4.4 SYSTEM "release-4.4.sgml"> diff --git a/doc.ja/src/sgml/installation-rpm.sgml b/doc.ja/src/sgml/installation-rpm.sgml index dd862c7f7..8f4c4ddd9 100644 --- a/doc.ja/src/sgml/installation-rpm.sgml +++ b/doc.ja/src/sgml/installation-rpm.sgml @@ -15,12 +15,12 @@ </para> <para> <!-- - <productname>Pgpool-II</productname> community provides RPM packages for RHEL9/8/7 + <productname>Pgpool-II</productname> community provides RPM packages for RHEL10/9/8 and the operating system which is compatible with RHEL. You can download package files from <ulink url="https://www.pgpool.net/yum/">official Pgpool-II repository</ulink>. --> - <productname>Pgpool-II</productname>コミュニティはRHEL9/8/7および互換OS向けにRPMパッケージを提供しています。 + <productname>Pgpool-II</productname>コミュニティはRHEL10/9/8および互換OS向けにRPMパッケージを提供しています。 パッケージファイルは<ulink url="https://www.pgpool.net/yum/">Pgpool-IIの公式リポジトリ</ulink>から入手できます。 </para> <para> @@ -53,11 +53,11 @@ </row> <row> <entry>pgpool-II-pgXX-debugsource</entry> - <entry>RHEL8/9の場合のみ。デバッグ情報が含まれる</entry> + <entry>RHEL10/9/8の場合のみ。デバッグ情報が含まれる</entry> </row> <row> <entry>pgpool-II-pgXX-extensions-debuginfo</entry> - <entry>RHEL8/9の場合のみ。デバッグ情報が含まれる</entry> + <entry>RHEL10/9/8の場合のみ。デバッグ情報が含まれる</entry> </row> <row> <entry>pgpool-II-pgXX-devel</entry> @@ -75,11 +75,11 @@ <productname>Pgpool-II</productname> provides separate packages for each PostgreSQL version. "XX" in the above package is a two-digit number representing the version of PostgreSQL. Choose <productname>Pgpool-II</productname> RPM corresponding to your PostgreSQL version. - (For example, if you are using PostgreSQL 17, you need to install <filename>pgpool-II-pg17</filename>) + (For example, if you are using PostgreSQL 18, you need to install <filename>pgpool-II-pg18</filename>) --> <productname>Pgpool-II</productname>は<productname>PostgreSQL</productname>のライブラリと拡張のディレクトリが必要です。 そのディレクトリへのパスは<productname>PostgreSQL</productname>のバージョンごとに異なっているので、<productname>Pgpool-II</productname>はPostgreSQLバージョンごとにパッケージを提供しています。 - 上記パッケージの「XX」はPostgreSQLのバージョンを表す2桁の数値です。<productname>PostgreSQL</productname>バージョンに対応する<productname>Pgpool-II</productname>のRPMを選んでください。(例えば、PostgreSQL 17を利用している場合は、<filename>pgpool-II-pg17</filename>を使用してください) + 上記パッケージの「XX」はPostgreSQLのバージョンを表す2桁の数値です。<productname>PostgreSQL</productname>バージョンに対応する<productname>Pgpool-II</productname>のRPMを選んでください。(例えば、PostgreSQL 18を利用している場合は、<filename>pgpool-II-pg18</filename>を使用してください) </para> <sect2 id="before-installing"> @@ -116,6 +116,10 @@ vi /etc/yum.repos.d/pgdg-redhat-all.repo exclude=pgpool* +[pgdg18] +... +exclude=pgpool* + [pgdg17] ... exclude=pgpool* @@ -135,14 +139,6 @@ exclude=pgpool* [pgdg13] ... exclude=pgpool* - -[pgdg12] -... -exclude=pgpool* - -[pgdg11] -... -exclude=pgpool* </programlisting> </sect2> @@ -160,23 +156,23 @@ exclude=pgpool* </para> <para> <!-- - The following commands assume that you are using Pgpool-II 4.6.x for PostgreSQL 17 on RHEL9. + The following commands assume that you are using Pgpool-II 4.6.x for PostgreSQL 18 on RHEL10. If you are using other versions, replace "pgXX" with your PostgreSQL version. --> - 以下の手順はRHEL9に<productname>PostgreSQL 17</productname>に対応した<productname>Pgpool-II 4.6.x</productname>をインストールすることが前提となります。 + 以下の手順はRHEL10に<productname>PostgreSQL 18</productname>に対応した<productname>Pgpool-II 4.6.x</productname>をインストールすることが前提となります。 他のバージョンの<productname>PostgreSQL</productname>を利用している場合は、<productname>PostgreSQL</productname>のバージョンに応じて「pgXX」を適宜置き換えてください。 </para> <para> <!-- First, install the repository corresponding to your <productname>Pgpool-II</productname> version and distribution. - For REHL7/9, see <ulink url="https://www.pgpool.net/mediawiki/index.php/Yum_Repository">here</ulink>. + For REHL9/8, see <ulink url="https://www.pgpool.net/mediawiki/index.php/Yum_Repository">here</ulink>. --> まず、Pgpool-IIバージョンとディストリビューションに対応するレポジトリをインストールします。 - REHL7/8の場合は、<ulink url="https://www.pgpool.net/mediawiki/index.php/Yum_Repository">こちら</ulink>を参照してください。 + REHL9/8の場合は、<ulink url="https://www.pgpool.net/mediawiki/index.php/Yum_Repository">こちら</ulink>を参照してください。 </para> <programlisting> -dnf install https://www.pgpool.net/yum/rpms/4.6/redhat/rhel-9-x86_64/pgpool-II-release-4.6-1.noarch.rpm +dnf install https://www.pgpool.net/yum/rpms/4.6/redhat/rhel-10-x86_64/pgpool-II-release-4.6-1.noarch.rpm </programlisting> <para> <!-- @@ -185,7 +181,7 @@ dnf install https://www.pgpool.net/yum/rpms/4.6/redhat/rhel-9-x86_64/pgpool-II-r 次に、<productname>Pgpool-II</productname>をインストールします。 </para> <programlisting> -dnf install pgpool-II-pg17 +dnf install pgpool-II-pg18 </programlisting> <para> <!-- @@ -212,7 +208,7 @@ dnf install pgpool-II-pg17 </para> </note> <programlisting> -dnf install pgpool-II-pg17-extensions pgpool-II-pg17 +dnf install pgpool-II-pg18-extensions pgpool-II-pg18 </programlisting> <para> <!-- @@ -221,7 +217,7 @@ dnf install pgpool-II-pg17-extensions pgpool-II-pg17 必要に応じて、開発者向けのオプションパッケージdebuginfoおよびdevelパッケージをインストールします。 </para> <programlisting> -dnf install pgpool-II-pg17-debuginfo pgpool-II-pg17-devel +dnf install pgpool-II-pg18-debuginfo pgpool-II-pg18-devel </programlisting> </sect2> @@ -249,9 +245,9 @@ dnf install pgpool-II-pg17-debuginfo pgpool-II-pg17-devel <title>Pgpool-IIの起動と停止</title> <para> <!-- - On RHEL7,8/CentOS7,8, do this once, if set the automatic startup of <productname>Pgpool-II</productname>. + On RHEL10/9/8, do this once, if set the automatic startup of <productname>Pgpool-II</productname>. --> - RHEL7/8/9では、<productname>Pgpool-II</productname>の自動起動を設定する場合、以下を実行してください。 + RHEL10/9/8では、<productname>Pgpool-II</productname>の自動起動を設定する場合、以下を実行してください。 <programlisting> systemctl enable pgpool.service </programlisting> diff --git a/doc.ja/src/sgml/installation-tips.sgml b/doc.ja/src/sgml/installation-tips.sgml index 3edf23156..f11f3e533 100644 --- a/doc.ja/src/sgml/installation-tips.sgml +++ b/doc.ja/src/sgml/installation-tips.sgml @@ -49,10 +49,10 @@ </para> <para> <!-- - Here is an example for CentOS/RHEL7 when access + Here is an example for Rocky Linux/RHEL10 when access to <productname>PostgreSQL</productname> is required. --> - CentOS/RHEL7において、<productname>PostgreSQL</productname>にアクセスが必要な場合の例を示します。 + Rocky Linux/RHEL10において、<productname>PostgreSQL</productname>にアクセスが必要な場合の例を示します。 <programlisting> firewall-cmd --permanent --zone=public --add-service=postgresql firewall-cmd --reload diff --git a/doc.ja/src/sgml/loadbalance.sgml b/doc.ja/src/sgml/loadbalance.sgml index 87cfa8e97..80cb27da5 100644 --- a/doc.ja/src/sgml/loadbalance.sgml +++ b/doc.ja/src/sgml/loadbalance.sgml @@ -8,7 +8,7 @@ <para> <productname>Pgpool-II</productname>のSELECTクエリの負荷分散はrawモードを除くすべてのクラスタリングモードで動作します。 - 有効時、<productname>Pgpool-II</productname>は更新を伴うクエリを、ストリーミングレプリケーションモード、ロジカルレプリケーションモード、Slonyモードでは<acronym>プライマリノード</acronym>に、レプリケーションモードでは全てのバックエンドノードに対し送信します。 + 有効時、<productname>Pgpool-II</productname>は更新を伴うクエリを、ストリーミングレプリケーションモード、ロジカルレプリケーションモードでは<acronym>プライマリノード</acronym>に、レプリケーションモードでは全てのバックエンドノードに対し送信します。 そして、その他のクエリは全てのバックエンドの間で負荷分散されます。 <xref linkend="guc-statement-level-load-balance">が指定されている場合を除き、負荷分散メカニズムが参照クエリをどのノードに送信するかはセッション開始時に決められ、セッションの終了まで変更されません。 ただし、いくつかの例外があります。 diff --git a/doc.ja/src/sgml/misc-config.sgml b/doc.ja/src/sgml/misc-config.sgml index 37dcf0b54..3a0e2d37c 100644 --- a/doc.ja/src/sgml/misc-config.sgml +++ b/doc.ja/src/sgml/misc-config.sgml @@ -282,13 +282,13 @@ </listitem> </varlistentry> - <varlistentry id="guc-logdir" xreflabel="logdir"> - <term><varname>logdir</varname> (<type>string</type>) + <varlistentry id="guc-work-dir" xreflabel="work_dir"> + <term><varname>work_dir</varname> (<type>string</type>) <indexterm> <!-- - <primary><varname>logdir</varname> configuration parameter</primary> + <primary><varname>work_dir</varname> configuration parameter</primary> --> - <primary><varname>logdir</varname> 設定パラメータ</primary> + <primary><varname>work_dir</varname> 設定パラメータ</primary> </indexterm> </term> <listitem> @@ -338,7 +338,7 @@ enables the testing facility of health checking. In this case the health check process looks into <filename>backend_down_request</filename> - under <xref linkend="guc-logdir">. The file may contain multiple + under <xref linkend="guc-work-dir">. The file may contain multiple lines, and each line corresponds to each backend. A line in the file starts with backend id (must be a decimal number starting with zero), then a TAB, and ends with "down". The backend is @@ -348,7 +348,7 @@ repeating failovers. --> onにすると、ヘルスチェックのテスト機能が有効になります。 - この場合、ヘルスチェックプロセスは<xref linkend="guc-logdir">の下にある<filename>backend_down_request</filename>を参照します。 + この場合、ヘルスチェックプロセスは<xref linkend="guc-work-dir">の下にある<filename>backend_down_request</filename>を参照します。 このファイルは、複数の行から構成され、各行は各々のバックエンドに対応します。 各行はバックエンドID(ゼロから始まる十進数でなければなりません)で始まり、続いてタブ、最後に"down"で終わります。 そのバックエンドはダウン状態と見なされ、<productname>Pgpool-II</productname>はフェイルオーバを開始します。 diff --git a/doc.ja/src/sgml/performance.sgml b/doc.ja/src/sgml/performance.sgml index 5c188eed0..ae5fc4f83 100644 --- a/doc.ja/src/sgml/performance.sgml +++ b/doc.ja/src/sgml/performance.sgml @@ -142,7 +142,7 @@ <sect1 id="read-query-load-balancing"> <title>読み出しクエリの負荷分散</title> <para> - 複数の<productname>PostgreSQL</productname>ノードがあり、<productname>Pgpool-II</productname>がストリーミングレプリケーションモード、ロジカルレプリケーションモード、slonyモード、レプリケーションモードで動作していると(これらの動作モードについては<xref linkend="running-mode">を参照のこと)、読み出しクエリをこれらのデータベースノードに分散させ、各々のノードにより少ない数のクエリを処理させることによってより高いスループットを得ることができます。 + 複数の<productname>PostgreSQL</productname>ノードがあり、<productname>Pgpool-II</productname>がストリーミングレプリケーションモード、ロジカルレプリケーションモード、レプリケーションモードで動作していると(これらの動作モードについては<xref linkend="running-mode">を参照のこと)、読み出しクエリをこれらのデータベースノードに分散させ、各々のノードにより少ない数のクエリを処理させることによってより高いスループットを得ることができます。 この機能を使うためには、<xref linkend="guc-load-balance-mode">をonにする必要があります。 </para> diff --git a/doc.ja/src/sgml/ref/watchdog_setup.sgml b/doc.ja/src/sgml/ref/watchdog_setup.sgml index 0a51eda28..fc75c16cf 100644 --- a/doc.ja/src/sgml/ref/watchdog_setup.sgml +++ b/doc.ja/src/sgml/ref/watchdog_setup.sgml @@ -54,10 +54,8 @@ Pgpool-II documentation <!-- <application>watchdog_setup</application> is for testing purpose only and should not be used to create production installations. - Also please note that heartbeat is not used. --> - <application>watchdog_setup</application> はテストのために使うツールなので、 - 実際の業務システムで利用することはおすすめしません。また、heartbeat が使用されていないことにもご注意ください。 + <application>watchdog_setup</application> はテストのために使うツールなので、実際の業務システムで利用することはおすすめしません。 </para> <para> @@ -161,6 +159,24 @@ Pgpool-II documentation </varlistentry> <varlistentry> + <term><option>-vip [<replaceable class="parameter">ip</replaceable>]</option></term> + <listitem> + <para> + 仮想IPを指定します。 + ipを省略した場合は、'127.0.0.1'を指定したものと見なされます。 + ここで指定した仮想IPは、<xref linkend="guc-delegate-ip">パラメータに設定されます。 + 仮想IPを指定しても、実際に仮想IPがシステムに設定されるわけではなく、単に<xref linkend="PCP-WATCHDOG-INFO">や、ログファイルで仮想IPを設定する動作が確認できるだけですが、<productname>Pgpool-II</productname>の仮想IPに関する挙動をテストするのに役立ちます。 + また、以下のパラメータも設定されます。 + <programlisting> + if_up_cmd = '/usr/bin/echo "if_up_cmd executed"' + if_down_cmd = 'usr/bin/echo "if_down_cmd executed"' + arping_cmd = '/usr/bin/true' + </programlisting> + </para> + </listitem> + </varlistentry> + + <varlistentry> <term><option>--no-stop</option></term> <listitem> <para> diff --git a/doc.ja/src/sgml/release-3.6.sgml b/doc.ja/src/sgml/release-3.6.sgml index f0c9e9560..5412250e5 100644 --- a/doc.ja/src/sgml/release-3.6.sgml +++ b/doc.ja/src/sgml/release-3.6.sgml @@ -2205,7 +2205,7 @@ <!-- Doc: fix typo in logdir description. (<ulink url="http://www.pgpool.net/mantisbt/view.php?id=453">bug 453</ulink>)(Tatsuo Ishii) --> - Doc: <xref linkend="GUC-LOGDIR">に関するドキュメントのタイポを修正しました。(<ulink url="http://www.pgpool.net/mantisbt/view.php?id=453">bug 453</ulink>)(Tatsuo Ishii) + Doc: <link linkend="GUC-WORK-DIR">logdir</link>に関するドキュメントのタイポを修正しました。(<ulink url="http://www.pgpool.net/mantisbt/view.php?id=453">bug 453</ulink>)(Tatsuo Ishii) </para> </listitem> diff --git a/doc.ja/src/sgml/release-3.7.sgml b/doc.ja/src/sgml/release-3.7.sgml index 47cc2e0a6..b84b5188f 100644 --- a/doc.ja/src/sgml/release-3.7.sgml +++ b/doc.ja/src/sgml/release-3.7.sgml @@ -3228,7 +3228,7 @@ <!-- Doc: fix typo in logdir description. (<ulink url="http://www.pgpool.net/mantisbt/view.php?id=453">bug 453</ulink>)(Tatsuo Ishii) --> - Doc: <xref linkend="GUC-LOGDIR">に関するドキュメントのタイポを修正しました。(<ulink url="http://www.pgpool.net/mantisbt/view.php?id=453">bug 453</ulink>)(Tatsuo Ishii) + Doc: <link linkend="GUC-WORK-DIR">logdir</link>に関するドキュメントのタイポを修正しました。(<ulink url="http://www.pgpool.net/mantisbt/view.php?id=453">bug 453</ulink>)(Tatsuo Ishii) </para> </listitem> diff --git a/doc.ja/src/sgml/release-4.0.sgml b/doc.ja/src/sgml/release-4.0.sgml index 99785620b..d75b3bbb6 100644 --- a/doc.ja/src/sgml/release-4.0.sgml +++ b/doc.ja/src/sgml/release-4.0.sgml @@ -4260,7 +4260,7 @@ <!-- Doc: fix typo in logdir description. (<ulink url="http://www.pgpool.net/mantisbt/view.php?id=453">bug 453</ulink>)(Tatsuo Ishii) --> - Doc: <xref linkend="GUC-LOGDIR">に関するドキュメントのタイポを修正しました。(<ulink url="http://www.pgpool.net/mantisbt/view.php?id=453">bug 453</ulink>)(Tatsuo Ishii) + Doc: <link linkend="GUC-WORK-DIR">logdir</link>に関するドキュメントのタイポを修正しました。(<ulink url="http://www.pgpool.net/mantisbt/view.php?id=453">bug 453</ulink>)(Tatsuo Ishii) </para> </listitem> diff --git a/doc.ja/src/sgml/release-4.2.sgml b/doc.ja/src/sgml/release-4.2.sgml index 823879cc9..c60138355 100644 --- a/doc.ja/src/sgml/release-4.2.sgml +++ b/doc.ja/src/sgml/release-4.2.sgml @@ -1,6 +1,448 @@ <!-- doc/src/sgml/release-4.2.sgml --> <!-- See header comment in release.sgml about typical markup --> +<sect1 id="release-4-2-24"> + <title>リリース 4.2.24</title> + <note> + <title>リリース日</title> + <simpara>2025-11-25</simpara> + </note> + + <sect2> + <title>変更点</title> + <itemizedlist> + <listitem> + <!-- + 2025-11-07 [4fabca331] + --> + <para> + 不要な<varname>application_name</varname>の処理を削除しました。(Tatsuo Ishii) + </para> + <para> + 以前のコミットで、既存接続を再利用する際に<varname>application_name</varname>を設定する処理が追加されました。 + しかしこれは不要です。DISCARD ALLにより接続再利用時に自動的に<varname>application_name</varname>がリセットされ、 + <function>send_params()</function>によってフロントエンドに必要なパラメータステータス(<varname>application_name</varname>を含む)が送信されます。 + この冗長な処理を削除することで、特に地理的に離れたバックエンドノードでのパフォーマンスが向上します。 + </para> + <para> + ディスカッション: <ulink url="https://github.com/pgpool/pgpool2/issues/130">Severely degraded performance of pgPool in geo-distributed configurations</ulink> + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>不具合修正</title> + <itemizedlist> + <listitem> + <!-- + 2025-11-16 [b113027dd] + --> + <para> + <command>CopyOut</command>でのセグメンテーションフォルトを修正しました。(Tatsuo Ishii) + </para> + <para> + 拡張プロトコルで<command>COPY relname TO STDOUT</command>が実行された場合、<productname>Pgpool-II</productname>がセグフォルトを起こしていました。 + </para> + <para> + この問題は<ulink url="https://github.com/tetesh">https://github.com/tetesh</ulink>によって報告されました。 + </para> + <para> + ディスカッション: <ulink url="https://github.com/pgpool/pgpool2/issues/133">datanymizer and pg-pool segmentation fault</ulink> + </para> + </listitem> + <listitem> + <!-- + 2025-10-03 [b84553bf0] + --> + <para> + Watchdogのスプリットブレイン回避するよう修正しました。(Tatsuo Ishii) + </para> + <para> + Watchdogはビーコンメッセージとハートビートで通信します。 + ハートビートが有効でない場合、ビーコンが30秒以上届かないとスプリットブレインが発生することがあります。 + 古いリーダーを無効化することで、同時に二人のリーダーが存在しないように修正しました。 + ノードがリーダーからのビーコンを2回以上見逃すと、リーダーはLOST状態となり、 + set_state(WD_JOINING) により新リーダー選出が開始されます。 + </para> + </listitem> + + <listitem> + <!-- + 2025-10-03 [ef8ccb9e7] + --> + <para> + 存在しないプリペアドステートメント使用時のFATALエラー防止するよう修正しました。(Tatsuo Ishii) + </para> + <para> + 以前は <function>Bind()</function>が存在しないプリペアドステートメントでFATALエラーを出していました。 + はステートメントの存在を確認し、存在しない場合はフロントエンドにERRORメッセージを送信するようになりました。ログは残りません。 + </para> + </listitem> + + <listitem> + <!-- + 2025-09-24 [59a359eef] + --> + <para> + <xref linkend="pg-enc"> -pと -P両方使用時に動作しない問題を修正しました。(Tatsuo Ishii) + </para> + <para> + 元の報告では、pg_enc -p -P実行時にパスワードと暗号キーを求められましたが、 + キーが提供されない場合に失敗していました。 + また、コメント /* prompt for postgres password */ が誤解を招くため、 + /* prompt for password to be encrypted */ に修正されました。 + </para> + <para> + ディスカッション: <ulink url="https://www.postgresql.org/message-id/7f18c30b.237.1997555ca11.Coremail.liujy%40highgo.com">pg_enc</ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-09-18 [f20f7041c] + --> + <para> + 32ビット環境でのコンパイルの問題を修正しました。(Tatsuo Ishii) + </para> + <para> + 32ビットシステムでsrc/parser/snprintf.cをコンパイルすると <function>isnan()</function>や <function>isinf()</function>が未定義でエラーになりました。 + math.hをインクルードし、ヘッダーファイルの順序も整理しました。 + 元々 PostgreSQLから取り込まれたファイルで、math.hは既に含まれていました。 + 修正は <ulink url="https://github.com/pgpool/pgpool2/pull/128">fix compiling issues for 32-bit targets</ulink> のプルリクエストに記載してあります。 + </para> + </listitem> + + <listitem> + <!-- + 2025-09-10 [0a6868d40] + --> + <para> + recovery_1st_stage.sampleでBashのディレクトリ削除を安全に行うよう修正しました。(Taiki Koshino) + </para> + <para> + rmコマンドの変数をクォートし、意図しない削除を防止しました: + <command>rm -rf "${DEST_NODE_PGDATA}"</command> + </para> + </listitem> + + <listitem> + <!-- + 2025-09-05 [441f338ab] + --> + <para> + <option>--with-memcached</option>指定なしでコンパイルする際のエラーを修正しました。(Tatsuo Ishii) + </para> + <para> + <option>--with-memcached</option>指定なしでコンパイルするとエラーが発生していました。 + 対応として該当コードブロックを #ifdef USE_MEMCACHEDで囲みました。 + </para> + <para> + この問題はBo Pengによって報告されました。 + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>ドキュメント修正</title> + <itemizedlist> + <listitem> + <!-- + 2025-09-17 [1a975b539] + --> + <para> + <ulink url="https://www.pgpool.net/docs/latest/ja/html/example-cluster.html">8.2. Pgpool-II + Watchdog Setup Example</ulink> の "PostgreSQLスタンバイ設定" ドキュメントを更新しました。(Taiki Koshino) + </para> + <para> + オンラインリカバリなしでスタンバイを設定する場合、postgresql.auto.confに<varname>primary_conninfo</varname>を書き込まないよう注意を追加しました。 + </para> + <para> + ディスカッション: <ulink url="https://github.com/pgpool/pgpool2/issues/67">Follow primary command not fixing postgresql.auto.conf </ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-08-22 [5bd535792] + --> + <para> + watchdog_setupのマニュアルを修正しました。(Tatsuo Ishii) + </para> + <para> + heartbeartがwatchdog_setupに設定されていないと誤記されていた箇所を修正しました。 + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>回帰テスト修正</title> + <itemizedlist> + <listitem> + <!-- + 2025-09-30 [3ddbc64f1] + --> + <para> + 023.ssl_connectionをPostgreSQL 18に対応するよう修正しました。(Tatsuo Ishii) + </para> + <para> + PostgreSQL 18でpsqlの \conninfo出力形式が大幅に変更されたため、 + このテストが失敗していました。 + PostgreSQLバージョンに応じてテストスクリプトを修正しました。 + </para> + </listitem> + + <listitem> + <!-- + 2025-08-29 [b4043e6c3] + --> + <para> + 010.rewrite_timestampのRubyスクリプトを修正しました。(Tatsuo Ishii) + </para> + <para> + RubyのFile.existsは新しいバージョンで非推奨のため、File.existに置き換えました。 + </para> + </listitem> + + <listitem> + <!-- + 2025-08-29 [9c901e60a] + --> + <para> + 034と075のタイムアウトを調整しました。(Tatsuo Ishii) + </para> + <para> + 034.promote_nodeと075.detach_primary_left_down_nodeのスクリプト終了タイムアウトを60秒から120秒に変更し、 + 誤エラーが発生する可能性を減らしました。 + </para> + </listitem> + + <listitem> + <!-- + 2025-08-27 [42b177614] + --> + <para> + 023.ssl_connectionにssl_ecdh_curveのテストを追加しました。(Tatsuo Ishii) + </para> + <para> + 023.ssl_connectionはssl_ecdh_curveのテストをカバーしていなかったため、 + 不正なssl_ecdh_curveパラメータでフロントエンドとpgpoolの接続が失敗するか確認しました。 + </para> + </listitem> + </itemizedlist> + </sect2> +</sect1> + +<sect1 id="release-4-2-23"> + <title>リリース 4.2.23</title> + <note> + <title>リリース日</title> + <simpara>2025-08-21</simpara> + </note> + + <sect2> + <title>不具合修正</title> + <itemizedlist> + <listitem> + <!-- + 2025-07-25 [75d905ff9] + --> + <para> + watchdog が不適切な NOTICE メッセージを出力する問題を修正しました。 (Tatsuo Ishii) + </para> + <para> + <function>read_ipc_socket_and_process()</function> は、IPCソケットへのコマンド書き込みのたびに、書き込みが成功した場合でも通知メッセージを出力していました。これを修正し、書き込みが失敗した場合にのみ通知メッセージを出力するようにしました。 + <varname>log_min_messages</varname>が notice 以上に設定されている場合にのみメッセージが表示されるため、このバグが発見されていませんでした。 + </para> + <para> + ディスカッション: <ulink url="https://github.com/pgpool/pgpool2/issues/121">pgpool IPC socket connection issue</ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-07-19 [d05de5c73] + --> + <!-- + 2025-07-19 [ed57af34e] + --> + <para> + スタートアップパケットを読んでいるときのメモリーリークを修正しました。(Tatsuo Ishii) + </para> + <para> + pool_push_pending_data でのリソースリークを修正しました。 + </para> + </listitem> + + <listitem> + <!-- + 2025-06-30 [bac455b2f] + --> + <para> + ビッグエンディアンマシン上の scram-sha-256 認証の不具合を修正しました。(Tatsuo Ishii) + </para> + <para> + <literal>scram-sha-256</literal> 認証を実行する際、ハッシュ関数 <function>pg_sha_256_final</function> が使用されます。 + これは <productname>PostgreSQL</productname> からインポートされたもので、プリプロセッサ定義 WORDS_BIGENDIAN を使用してホストマシンのエンディアンを判断します。 + WORDS_BIGENDIAN は configure 時に定義する必要がありますが、<function>pg_sha_256_final</function>(およびその他)が <productname>PostgreSQL</productname> からインポートされた際にこの部分が省略されていました。 + その結果、scram-sha-256 はリトルエンディアンマシンでのみ動作していました。 + configure.ac に AC_C_BIGENDIAN マクロを追加することでこの問題を修正しました。。 + </para> + <para> + この問題は Christoph Berg によって報告され、 pranavkaruvally によって分析されました。 + </para> + <para> + ディスカッション: <ulink url="https://github.com/pgpool/pgpool2/issues/106">4.6.1 fails on big-endian s390x: backend response with kind 'E' when expecting 'R'</ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-06-23 [2721c7b76] + --> + <para> + ソースコードのタイプミスを修正しました。 (Bo Peng) + </para> + </listitem> + + <listitem> + <!-- + 2025-06-09 [4305c42d6] + --> + <para> + ハートビートデバイスの処理を修正しました。(Tatsuo Ishii) + </para> + <para> + <filename>pgpool.conf</filename> の処理中に、<varname>heartbeat_device</varname>が誤って処理され、最初のデバイスが無視されていました。 + </para> + <para> + この問題は Bo Peng によって分析されました。 + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>ドキュメント修正</title> + <itemizedlist> + <listitem> + <!-- + 2025-08-04 [e2f24fec8] + --> + <para> + リロードによって反映されないパラメータのドキュメントを修正しました。 (Taiki Koshino) + </para> + <para> + <varname>authentication_timeout</varname>と<varname>memqcache_oiddir</varname>はリロードしても反映されません。 + ドキュメントが「このパラメータはサーバー起動時にのみ設定できます。」に変更されました。 + </para> + </listitem> + + <listitem> + <!-- + 2025-07-24 [bc5fa5e7e] + --> + <!-- + 2025-07-23 [1e8963554] + --> + <para> + watchdog リーダーの用語を統一しました。(Tatsuo Ishii) + </para> + <para> + 以前は「leader」「active」「coordinater」という用語が、watchdog のリーダーノードを指すために使用されていました。このコミットではこれらを「leader」に統一しました。 + advanced.sgml も修正しました。 + </para> + </listitem> + + <listitem> + <!-- + 2025-08-06 [31eee18d7] + --> + <!-- + 2025-07-16 [34b07c2d5] + --> + <para> + サンプルスクリプトを修正しました。(Taiki Koshino) + </para> + <para> + 「<ulink url="https://www.pgpool.net/docs/latest/ja/html/example-cluster.html">8.2. Pgpool-II + Watchdogの構築の例</ulink>」のサンプルスクリプトを修正しました。 + </para> + </listitem> + + <listitem> + <!-- + 2025-06-18 [f4ae9f39e] + 2025-06-18 [7a20dc419] + --> + <para> + ロードバランスの説明で論理レプリケーションモードと Slony モードが抜けている問題を修正しました(Tatsuo Ishii) + </para> + </listitem> + + <listitem> + <!-- + 2025-06-08 [59f9df005] + --> + <para> + カーネルの資源に関するセクションを追加しました。 (Tatsuo Ishii) + </para> + <para> + <productname>Pgpool-II</productname> は System V の共有メモリとセマフォを使用します。 + 要件についてはドキュメントを参照することをお勧めします。 + </para> + </listitem> + + <listitem> + <!-- + 2025-06-07 [40617fd90] + --> + <para> + configure の <option>--with-ldap</option> オプションの説明を追加しました。(Tatsuo Ishii) + </para> + <para> + これは LDAPサポートがv4.2で導入されたときに見落としていました。 + </para> + </listitem> + + <listitem> + <!-- + 2025-06-04 [ff60bf930] + --> + <para> + <productname>Pgpool-II</productname> でサポートされているプラットフォームを明確にしました。 (Tatsuo Ishii) + </para> + </listitem> + + <listitem> + <!-- + 2025-06-03 [cc4da5979] + --> + <para> + <xref linkend="guc-child-life-time"> のドキュメントを改善しました。 (Tatsuo Ishii) + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>回帰テスト修正</title> + <itemizedlist> + <listitem> + <!-- + 2025-06-08 [78e45decf] + --> + <para> + 029.cert_passphrase 回帰テストを安定化しました。 (Tatsuo Ishii) + </para> + <para> + <varname>ssl_passphrase_command</varname>が有効でない場合、エラーメッセージは通常「bad decrypt」ですが、「wrong tag」となる場合もありました。 + </para> + </listitem> + </itemizedlist> + </sect2> +</sect1> + <sect1 id="release-4-2-22"> <title>リリース 4.2.22</title> <note> diff --git a/doc.ja/src/sgml/release-4.3.sgml b/doc.ja/src/sgml/release-4.3.sgml index 4d6db27b0..7aaa9b41b 100644 --- a/doc.ja/src/sgml/release-4.3.sgml +++ b/doc.ja/src/sgml/release-4.3.sgml @@ -1,6 +1,546 @@ <!-- doc/src/sgml/release-4.3.sgml --> <!-- See header comment in release.sgml about typical markup --> +<sect1 id="release-4-3-18"> + <title>リリース 4.3.18</title> + <note> + <title>リリース日</title> + <simpara>2025-12-15</simpara> + </note> + + <sect2> + <title>変更点</title> + <itemizedlist> + <listitem> + <!-- + 2025-12-08 [5bd10177c] + --> + <para> + pgpool_setupで非推奨の「egrep」の代わりに「grep -E」を使用するようにしました。(Bo Peng) + </para> + <para> + 新しいGNUのgrepバージョンでの廃止警告を回避するために、「egrep」を「grep -E」に置き換えました。 + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>不具合修正</title> + <itemizedlist> + <listitem> + <!-- + 2025-12-08 [8deccc15e] + --> + <para> + show pool_statusのバッファオーバーフローエラーを修正しました。(Tatsuo Ishii) + </para> + <para> + SHOW POOL_STATUS、pgpool show、および pcp_pool_statusコマンドでバッファオーバーフローが発生する問題を修正しました。 + 問題の原因は、backend_flagがALWAYS_PRIMARYに設定されている場合に、pool_flag_to_str()関数がbackend_flagを文字列化する際に静的バッファの末尾を越えて書き込んでしまうことでした。 + </para> + <para> + この問題はzam bakによって報告され、Bo Pengによってよって分析されました。 + </para> + <para> + ディスカッション: <ulink url="https://www.postgresql.org/message-id/20251202.140205.427777414210613577.ishii%40postgresql.org">Re: "buffer overflow detected" when running SHOW POOL_STATUS</ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-12-02 [c8865c703] + --> + <para> + 「show pool_status」に表示されるmemqcache_stats_start_timeの出力を修正しました。(Tatsuo Ishii) + </para> + <para> + get_config()がctime()を使って時刻を文字列化していましたが、ctime()の戻り値の末尾には改行が含まれることを考慮していませんでした。 + その結果、memqcache_stats_start_timeの行に余計な改行が入り、さらに次の行が空欄として表示されてしまう問題が発生していました。 + </para> + <para> + ディスカッション: <ulink url="https://www.postgresql.org/message-id/20251130.102712.131456481338876013.ishii%40postgresql.org">Re: "buffer overflow detected" when running SHOW POOL_STATUS</ulink> + </para> + </listitem> + </itemizedlist> + </sect2> +</sect1> + +<sect1 id="release-4-3-17"> + <title>リリース 4.3.17</title> + <note> + <title>リリース日</title> + <simpara>2025-11-25</simpara> + </note> + + <sect2> + <title>変更点</title> + <itemizedlist> + <listitem> + <!-- + 2025-11-07 [4fabca331] + --> + <para> + 不要な<varname>application_name</varname>の処理を削除しました。(Tatsuo Ishii) + </para> + <para> + 以前のコミットで、既存接続を再利用する際に<varname>application_name</varname>を設定する処理が追加されました。 + しかしこれは不要です。DISCARD ALLにより接続再利用時に自動的に<varname>application_name</varname>がリセットされ、 + <function>send_params()</function>によってフロントエンドに必要なパラメータステータス(<varname>application_name</varname>を含む)が送信されます。 + この冗長な処理を削除することで、特に地理的に離れたバックエンドノードでのパフォーマンスが向上します。 + </para> + <para> + ディスカッション: <ulink url="https://github.com/pgpool/pgpool2/issues/130">Severely degraded performance of pgPool in geo-distributed configurations</ulink> + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>不具合修正</title> + <itemizedlist> + <listitem> + <!-- + 2025-11-16 [b113027dd] + --> + <para> + <command>CopyOut</command>でのセグメンテーションフォルトを修正しました。(Tatsuo Ishii) + </para> + <para> + 拡張プロトコルで<command>COPY relname TO STDOUT</command>が実行された場合、<productname>Pgpool-II</productname>がセグフォルトを起こしていました。 + </para> + <para> + この問題は<ulink url="https://github.com/tetesh">https://github.com/tetesh</ulink>によって報告されました。 + </para> + <para> + ディスカッション: <ulink url="https://github.com/pgpool/pgpool2/issues/133">datanymizer and pg-pool segmentation fault</ulink> + </para> + </listitem> + <listitem> + <!-- + 2025-10-03 [b84553bf0] + --> + <para> + Watchdogのスプリットブレイン回避するよう修正しました。(Tatsuo Ishii) + </para> + <para> + Watchdogはビーコンメッセージとハートビートで通信します。 + ハートビートが有効でない場合、ビーコンが30秒以上届かないとスプリットブレインが発生することがあります。 + 古いリーダーを無効化することで、同時に二人のリーダーが存在しないように修正しました。 + ノードがリーダーからのビーコンを2回以上見逃すと、リーダーはLOST状態となり、 + set_state(WD_JOINING) により新リーダー選出が開始されます。 + </para> + </listitem> + + <listitem> + <!-- + 2025-10-03 [ef8ccb9e7] + --> + <para> + 存在しないプリペアドステートメント使用時のFATALエラー防止するよう修正しました。(Tatsuo Ishii) + </para> + <para> + 以前は<function>Bind()</function>が存在しないプリペアドステートメントでFATALエラーを出していました。 + はステートメントの存在を確認し、存在しない場合はフロントエンドにERRORメッセージを送信するようになりました。ログは残りません。 + </para> + </listitem> + + <listitem> + <!-- + 2025-09-24 [59a359eef] + --> + <para> + <xref linkend="pg-enc"> -pと -P両方使用時に動作しない問題を修正しました。(Tatsuo Ishii) + </para> + <para> + 元の報告では、pg_enc -p -P実行時にパスワードと暗号キーを求められましたが、 + キーが提供されない場合に失敗していました。 + また、コメント /* prompt for postgres password */ が誤解を招くため、 + /* prompt for password to be encrypted */ に修正されました。 + </para> + <para> + ディスカッション: <ulink url="https://www.postgresql.org/message-id/7f18c30b.237.1997555ca11.Coremail.liujy%40highgo.com">pg_enc</ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-09-18 [f20f7041c] + --> + <para> + 32ビット環境でのコンパイルの問題を修正しました。(Tatsuo Ishii) + </para> + <para> + 32ビットシステムでsrc/parser/snprintf.cをコンパイルすると<function>isnan()</function>や<function>isinf()</function>が未定義でエラーになりました。 + math.hをインクルードし、ヘッダーファイルの順序も整理しました。 + 元々 PostgreSQLから取り込まれたファイルで、math.hは既に含まれていました。 + 修正は <ulink url="https://github.com/pgpool/pgpool2/pull/128">fix compiling issues for 32-bit targets</ulink> のプルリクエストに記載してあります。 + </para> + </listitem> + + <listitem> + <!-- + 2025-09-10 [0a6868d40] + --> + <para> + recovery_1st_stage.sampleでBashのディレクトリ削除を安全に行うよう修正しました。(Taiki Koshino) + </para> + <para> + rmコマンドの変数をクォートし、意図しない削除を防止しました: + <command>rm -rf "${DEST_NODE_PGDATA}"</command> + </para> + </listitem> + + <listitem> + <!-- + 2025-09-05 [441f338ab] + --> + <para> + <option>--with-memcached</option>指定なしでコンパイルする際のエラーを修正しました。(Tatsuo Ishii) + </para> + <para> + <option>--with-memcached</option>指定なしでコンパイルするとエラーが発生していました。 + 対応として該当コードブロックを #ifdef USE_MEMCACHEDで囲みました。 + </para> + <para> + この問題はBo Pengによって報告されました。 + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>ドキュメント修正</title> + <itemizedlist> + <listitem> + <!-- + 2025-09-17 [1a975b539] + --> + <para> + <ulink url="https://www.pgpool.net/docs/latest/ja/html/example-cluster.html">8.2. Pgpool-II + Watchdog Setup Example</ulink> の "PostgreSQLスタンバイ設定" ドキュメントを更新しました。(Taiki Koshino) + </para> + <para> + オンラインリカバリなしでスタンバイを設定する場合、postgresql.auto.confに<varname>primary_conninfo</varname>を書き込まないよう注意を追加しました。 + </para> + <para> + ディスカッション: <ulink url="https://github.com/pgpool/pgpool2/issues/67">Follow primary command not fixing postgresql.auto.conf </ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-08-22 [5bd535792] + --> + <para> + watchdog_setupのマニュアルを修正しました。(Tatsuo Ishii) + </para> + <para> + heartbeartがwatchdog_setupに設定されていないと誤記されていた箇所を修正しました。 + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>回帰テスト修正</title> + <itemizedlist> + <listitem> + <!-- + 2025-09-30 [3ddbc64f1] + --> + <para> + 023.ssl_connectionをPostgreSQL 18に対応するよう修正しました。(Tatsuo Ishii) + </para> + <para> + PostgreSQL 18でpsqlの\conninfo出力形式が大幅に変更されたため、 + このテストが失敗していました。 + PostgreSQLバージョンに応じてテストスクリプトを修正しました。 + </para> + </listitem> + + <listitem> + <!-- + 2025-08-29 [b4043e6c3] + --> + <para> + 010.rewrite_timestampのRubyスクリプトを修正しました。(Tatsuo Ishii) + </para> + <para> + RubyのFile.existsは新しいバージョンで非推奨のため、File.existに置き換えました。 + </para> + </listitem> + + <listitem> + <!-- + 2025-08-29 [9c901e60a] + --> + <para> + 034と075のタイムアウトを調整しました。(Tatsuo Ishii) + </para> + <para> + 034.promote_nodeと075.detach_primary_left_down_nodeのスクリプト終了タイムアウトを60秒から120秒に変更し、 + 誤エラーが発生する可能性を減らしました。 + </para> + </listitem> + + <listitem> + <!-- + 2025-08-27 [42b177614] + --> + <para> + 023.ssl_connectionにssl_ecdh_curveのテストを追加しました。(Tatsuo Ishii) + </para> + <para> + 023.ssl_connectionはssl_ecdh_curveのテストをカバーしていなかったため、 + 不正なssl_ecdh_curveパラメータでフロントエンドとpgpoolの接続が失敗するか確認しました。 + </para> + </listitem> + </itemizedlist> + </sect2> +</sect1> + +<sect1 id="release-4-3-16"> + <title>リリース 4.3.16</title> + <note> + <title>リリース日</title> + <simpara>2025-08-21</simpara> + </note> + + <sect2> + <title>不具合修正</title> + <itemizedlist> + <listitem> + <!-- + 2025-07-25 [75d905ff9] + --> + <para> + watchdog が不適切な NOTICE メッセージを出力する問題を修正しました。 (Tatsuo Ishii) + </para> + <para> + <function>read_ipc_socket_and_process()</function> は、IPCソケットへのコマンド書き込みのたびに、書き込みが成功した場合でも通知メッセージを出力していました。これを修正し、書き込みが失敗した場合にのみ通知メッセージを出力するようにしました。 + <varname>log_min_messages</varname> が notice 以上に設定されている場合にのみメッセージが表示されるため、このバグが発見されていませんでした。 + </para> + <para> + ディスカッション: <ulink url="https://github.com/pgpool/pgpool2/issues/121">pgpool IPC socket connection issue</ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-07-19 [d05de5c73] + --> + <!-- + 2025-07-19 [ed57af34e] + --> + <para> + スタートアップパケットを読んでいるときのメモリーリークを修正しました。(Tatsuo Ishii) + </para> + <para> + pool_push_pending_data でのリソースリークを修正しました。 + </para> + </listitem> + + <listitem> + <!-- + 2025-06-30 [bac455b2f] + --> + <para> + ビッグエンディアンマシン上の scram-sha-256 認証の不具合を修正しました。(Tatsuo Ishii) + </para> + <para> + <literal>scram-sha-256</literal> 認証を実行する際、ハッシュ関数 <function>pg_sha_256_final</function> が使用されます。 + これは <productname>PostgreSQL</productname> からインポートされたもので、プリプロセッサ定義 WORDS_BIGENDIAN を使用してホストマシンのエンディアンを判断します。 + WORDS_BIGENDIAN は configure 時に定義する必要がありますが、<function>pg_sha_256_final</function>(およびその他)が <productname>PostgreSQL</productname> からインポートされた際にこの部分が省略されていました。 + その結果、scram-sha-256 はリトルエンディアンマシンでのみ動作していました。 + configure.ac に AC_C_BIGENDIAN マクロを追加することでこの問題を修正しました。。 + </para> + <para> + この問題は Christoph Berg によって報告され、 pranavkaruvally によって分析されました。 + </para> + <para> + ディスカッション: <ulink url="https://github.com/pgpool/pgpool2/issues/106">4.6.1 fails on big-endian s390x: backend response with kind 'E' when expecting 'R'</ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-06-23 [2721c7b76] + --> + <para> + ソースコードのタイプミスを修正しました。 (Bo Peng) + </para> + </listitem> + + <listitem> + <!-- + 2025-06-09 [4305c42d6] + --> + <para> + ハートビートデバイスの処理を修正しました。(Tatsuo Ishii) + </para> + <para> + <filename>pgpool.conf</filename> の処理中に、<varname>heartbeat_device</varname> が誤って処理され、最初のデバイスが無視されていました。 + </para> + <para> + この問題は Bo Peng によって分析されました。 + </para> + </listitem> + + <listitem> + <!-- + 2025-06-02 [06ba7dde4] + --> + <para> + <filename>pgpool.conf</filename>のコメントのタイプミスを修正しました。 (Tatsuo Ishii) + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>ドキュメント修正</title> + <itemizedlist> + <listitem> + <!-- + 2025-08-15 [a54f5d1ad] + --> + <para> + 「8.3. ネイティブレプリケーション/スナップショットアイソレーションモードの構築の例」のドキュメントを改善しました。(Taiki Koshino) + </para> + <para> + サンプルスクリプトのリンクと「事前設定」の説明を改善しました。 + </para> + </listitem> + + <listitem> + <!-- + 2025-08-04 [e2f24fec8] + --> + <para> + リロードによって反映されないパラメータのドキュメントを修正しました。 (Taiki Koshino) + </para> + <para> + <varname>authentication_timeout</varname> と <varname>memqcache_oiddir</varname> はリロードしても反映されません。 + ドキュメントが「このパラメータはサーバー起動時にのみ設定できます。」に変更されました。 + </para> + </listitem> + + <listitem> + <!-- + 2025-07-24 [bc5fa5e7e] + --> + <!-- + 2025-07-23 [1e8963554] + --> + <para> + watchdog リーダーの用語を統一しました。(Tatsuo Ishii) + </para> + <para> + 以前は「leader」「active」「coordinater」という用語が、watchdog のリーダーノードを指すために使用されていました。このコミットではこれらを「leader」に統一しました。 + advanced.sgml も修正しました。 + </para> + </listitem> + + <listitem> + <!-- + 2025-08-06 [31eee18d7] + --> + <!-- + 2025-07-16 [34b07c2d5] + --> + <para> + サンプルスクリプトを修正しました。(Taiki Koshino) + </para> + <para> + 「<ulink url="https://www.pgpool.net/docs/latest/ja/html/example-cluster.html">8.2. Pgpool-II + Watchdogの構築の例</ulink>」のサンプルスクリプトを修正しました。 + </para> + </listitem> + + <listitem> + <!-- + 2025-06-18 [f4ae9f39e] + 2025-06-18 [7a20dc419] + --> + <para> + ロードバランスの説明で論理レプリケーションモードと Slony モードが抜けている問題を修正しました(Tatsuo Ishii) + </para> + </listitem> + + <listitem> + <!-- + 2025-06-18 [9d2e4e692] + --> + <para> + <xref linkend="pcp-node-info">のドキュメントを改善しました。 (Bo Peng) + </para> + <para> + 「<varname>replication_state</varname>」と「<varname>replication_sync_state</varname>」を正しく表示するには、各 <varname>backend_application_nameX</varname> が <varname>primary_conninfo</varname> の <varname>application_name</varname> に指定された値と一致する必要があることを明確にしました。 + </para> + </listitem> + + <listitem> + <!-- + 2025-06-08 [59f9df005] + --> + <para> + カーネルの資源に関するセクションを追加しました。 (Tatsuo Ishii) + </para> + <para> + <productname>Pgpool-II</productname> は System V の共有メモリとセマフォを使用します。 + 要件についてはドキュメントを参照することをお勧めします。 + </para> + </listitem> + + <listitem> + <!-- + 2025-06-07 [40617fd90] + --> + <para> + configure の <option>--with-ldap</option> オプションの説明を追加しました。(Tatsuo Ishii) + </para> + <para> + これは LDAPサポートがv4.2で導入されたときに見落としていました。 + </para> + </listitem> + + <listitem> + <!-- + 2025-06-04 [ff60bf930] + --> + <para> + <productname>Pgpool-II</productname> でサポートされているプラットフォームを明確にしました。 (Tatsuo Ishii) + </para> + </listitem> + + <listitem> + <!-- + 2025-06-03 [cc4da5979] + --> + <para> + <xref linkend="guc-child-life-time"> のドキュメントを改善しました。 (Tatsuo Ishii) + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>回帰テスト修正</title> + <itemizedlist> + <listitem> + <!-- + 2025-06-08 [78e45decf] + --> + <para> + 029.cert_passphrase 回帰テストを安定化しました。 (Tatsuo Ishii) + </para> + <para> + <varname>ssl_passphrase_command</varname> が有効でない場合、エラーメッセージは通常「bad decrypt」ですが、「wrong tag」となる場合もありました。 + </para> + </listitem> + </itemizedlist> + </sect2> +</sect1> + <sect1 id="release-4-3-15"> <title>リリース 4.3.15</title> <note> diff --git a/doc.ja/src/sgml/release-4.4.sgml b/doc.ja/src/sgml/release-4.4.sgml index da942a8f7..cbc09a88c 100644 --- a/doc.ja/src/sgml/release-4.4.sgml +++ b/doc.ja/src/sgml/release-4.4.sgml @@ -1,6 +1,562 @@ <!-- doc/src/sgml/release-4.4.sgml --> <!-- See header comment in release.sgml about typical markup --> +<sect1 id="release-4-4-15"> + <title>リリース 4.4.15</title> + <note> + <title>リリース日</title> + <simpara>2025-12-15</simpara> + </note> + + <sect2> + <title>変更点</title> + <itemizedlist> + <listitem> + <!-- + 2025-12-08 [5bd10177c] + --> + <para> + pgpool_setupで非推奨の「egrep」の代わりに「grep -E」を使用するようにしました。(Bo Peng) + </para> + <para> + 新しいGNUのgrepバージョンでの廃止警告を回避するために、「egrep」を「grep -E」に置き換えました。 + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>不具合修正</title> + <itemizedlist> + <listitem> + <!-- + 2025-12-08 [8deccc15e] + --> + <para> + show pool_statusのバッファオーバーフローエラーを修正しました。(Tatsuo Ishii) + </para> + <para> + SHOW POOL_STATUS、pgpool show、および pcp_pool_statusコマンドでバッファオーバーフローが発生する問題を修正しました。 + 問題の原因は、backend_flagがALWAYS_PRIMARYに設定されている場合に、pool_flag_to_str()関数がbackend_flagを文字列化する際に静的バッファの末尾を越えて書き込んでしまうことでした。 + </para> + <para> + この問題はzam bakによって報告され、Bo Pengによってよって分析されました。 + </para> + <para> + ディスカッション: <ulink url="https://www.postgresql.org/message-id/20251202.140205.427777414210613577.ishii%40postgresql.org">Re: "buffer overflow detected" when running SHOW POOL_STATUS</ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-12-02 [c8865c703] + --> + <para> + 「show pool_status」に表示されるmemqcache_stats_start_timeの出力を修正しました。(Tatsuo Ishii) + </para> + <para> + get_config()がctime()を使って時刻を文字列化していましたが、ctime()の戻り値の末尾には改行が含まれることを考慮していませんでした。 + その結果、memqcache_stats_start_timeの行に余計な改行が入り、さらに次の行が空欄として表示されてしまう問題が発生していました。 + </para> + <para> + ディスカッション: <ulink url="https://www.postgresql.org/message-id/20251130.102712.131456481338876013.ishii%40postgresql.org">Re: "buffer overflow detected" when running SHOW POOL_STATUS</ulink> + </para> + </listitem> + </itemizedlist> + </sect2> +</sect1> + +<sect1 id="release-4-4-14"> + <title>リリース 4.4.14</title> + <note> + <title>リリース日</title> + <simpara>2025-11-25</simpara> + </note> + + <sect2> + <title>変更点</title> + <itemizedlist> + <listitem> + <!-- + 2025-11-07 [4fabca331] + --> + <para> + 不要な <varname>application_name</varname> の処理を削除しました。(Tatsuo Ishii) + </para> + <para> + 以前のコミットで、既存接続を再利用する際に <varname>application_name</varname> を設定する処理が追加されました。 + しかしこれは不要です。DISCARD ALLにより接続再利用時に自動的に <varname>application_name</varname> がリセットされ、 + <function>send_params()</function>によってフロントエンドに必要なパラメータステータス(<varname>application_name</varname> を含む)が送信されます。 + この冗長な処理を削除することで、特に地理的に離れたバックエンドノードでのパフォーマンスが向上します。 + </para> + <para> + ディスカッション: <ulink url="https://github.com/pgpool/pgpool2/issues/130">Severely degraded performance of pgPool in geo-distributed configurations</ulink> + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>不具合修正</title> + <itemizedlist> + <listitem> + <!-- + 2025-11-16 [b113027dd] + --> + <para> + <command>CopyOut</command>でのセグメンテーションフォルトを修正しました。(Tatsuo Ishii) + </para> + <para> + 拡張プロトコルで<command>COPY relname TO STDOUT</command>が実行された場合、<productname>Pgpool-II</productname>がセグフォルトを起こしていました。 + </para> + <para> + この問題は<ulink url="https://github.com/tetesh">https://github.com/tetesh</ulink>によって報告されました。 + </para> + <para> + ディスカッション: <ulink url="https://github.com/pgpool/pgpool2/issues/133">datanymizer and pg-pool segmentation fault</ulink> + </para> + </listitem> + <listitem> + <!-- + 2025-10-03 [b84553bf0] + --> + <para> + Watchdogのスプリットブレイン回避するよう修正しました。(Tatsuo Ishii) + </para> + <para> + Watchdogはビーコンメッセージとハートビートで通信します。 + ハートビートが有効でない場合、ビーコンが30秒以上届かないとスプリットブレインが発生することがあります。 + 古いリーダーを無効化することで、同時に二人のリーダーが存在しないように修正しました。 + ノードがリーダーからのビーコンを2回以上見逃すと、リーダーはLOST状態となり、 + set_state(WD_JOINING) により新リーダー選出が開始されます。 + </para> + </listitem> + + <listitem> + <!-- + 2025-10-03 [ef8ccb9e7] + --> + <para> + 存在しないプリペアドステートメント使用時のFATALエラー防止するよう修正しました。(Tatsuo Ishii) + </para> + <para> + 以前は <function>Bind()</function>が存在しないプリペアドステートメントでFATALエラーを出していました。 + はステートメントの存在を確認し、存在しない場合はフロントエンドにERRORメッセージを送信するようになりました。ログは残りません。 + </para> + </listitem> + + <listitem> + <!-- + 2025-09-24 [59a359eef] + --> + <para> + <xref linkend="pg-enc"> -pと -P両方使用時に動作しない問題を修正しました。(Tatsuo Ishii) + </para> + <para> + 元の報告では、pg_enc -p -P実行時にパスワードと暗号キーを求められましたが、 + キーが提供されない場合に失敗していました。 + また、コメント /* prompt for postgres password */ が誤解を招くため、 + /* prompt for password to be encrypted */ に修正されました。 + </para> + <para> + ディスカッション: <ulink url="https://www.postgresql.org/message-id/7f18c30b.237.1997555ca11.Coremail.liujy%40highgo.com">pg_enc</ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-09-18 [f20f7041c] + --> + <para> + 32ビット環境でのコンパイルの問題を修正しました。(Tatsuo Ishii) + </para> + <para> + 32ビットシステムでsrc/parser/snprintf.cをコンパイルすると <function>isnan()</function>や <function>isinf()</function>が未定義でエラーになりました。 + math.hをインクルードし、ヘッダーファイルの順序も整理しました。 + 元々 PostgreSQLから取り込まれたファイルで、math.hは既に含まれていました。 + 修正は <ulink url="https://github.com/pgpool/pgpool2/pull/128">fix compiling issues for 32-bit targets</ulink> のプルリクエストに記載してあります。 + </para> + </listitem> + + <listitem> + <!-- + 2025-09-10 [0a6868d40] + --> + <para> + recovery_1st_stage.sampleでBashのディレクトリ削除を安全に行うよう修正しました。(Taiki Koshino) + </para> + <para> + rmコマンドの変数をクォートし、意図しない削除を防止しました: + <command>rm -rf "${DEST_NODE_PGDATA}"</command> + </para> + </listitem> + + <listitem> + <!-- + 2025-09-05 [441f338ab] + --> + <para> + <option>--with-memcached</option>指定なしでコンパイルする際のエラーを修正しました。(Tatsuo Ishii) + </para> + <para> + <option>--with-memcached</option>指定なしでコンパイルするとエラーが発生していました。 + 対応として該当コードブロックを #ifdef USE_MEMCACHEDで囲みました。 + </para> + <para> + この問題はBo Pengによって報告されました。 + </para> + </listitem> + + <listitem> + <!-- + 2025-09-04 [9e0324575] + --> + <para> + クエリキャッシュロックファイルの取り扱い修正を修正しました。(Tatsuo Ishii) + </para> + <para> + クエリキャッシュモジュールは並列制御のため <varname>logdir</varname> にロックファイルを作成しますが、 + メインプロセスがゴミファイルを作成したり、シャットダウン時に削除されない問題がありました。 + </para> + <para> + この問題はBo Pengによって報告・分析されました。 + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>ドキュメント修正</title> + <itemizedlist> + <listitem> + <!-- + 2025-09-17 [1a975b539] + --> + <para> + <ulink url="https://www.pgpool.net/docs/latest/ja/html/example-cluster.html">8.2. Pgpool-II + Watchdog Setup Example</ulink> の "PostgreSQLスタンバイ設定" ドキュメントを更新しました。(Taiki Koshino) + </para> + <para> + オンラインリカバリなしでスタンバイを設定する場合、postgresql.auto.confに <varname>primary_conninfo</varname> を書き込まないよう注意を追加しました。 + </para> + <para> + ディスカッション: <ulink url="https://github.com/pgpool/pgpool2/issues/67">Follow primary command not fixing postgresql.auto.conf </ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-08-22 [5bd535792] + --> + <para> + watchdog_setupのマニュアルを修正しました。(Tatsuo Ishii) + </para> + <para> + heartbeartがwatchdog_setupに設定されていないと誤記されていた箇所を修正しました。 + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>回帰テスト修正</title> + <itemizedlist> + <listitem> + <!-- + 2025-09-30 [3ddbc64f1] + --> + <para> + 023.ssl_connectionをPostgreSQL 18に対応するよう修正しました。(Tatsuo Ishii) + </para> + <para> + PostgreSQL 18でpsqlの \conninfo出力形式が大幅に変更されたため、 + このテストが失敗していました。 + PostgreSQLバージョンに応じてテストスクリプトを修正しました。 + </para> + </listitem> + + <listitem> + <!-- + 2025-08-29 [b4043e6c3] + --> + <para> + 010.rewrite_timestampのRubyスクリプトを修正しました。(Tatsuo Ishii) + </para> + <para> + RubyのFile.existsは新しいバージョンで非推奨のため、File.existに置き換えました。 + </para> + </listitem> + + <listitem> + <!-- + 2025-08-29 [9c901e60a] + --> + <para> + 034と075のタイムアウトを調整しました。(Tatsuo Ishii) + </para> + <para> + 034.promote_nodeと075.detach_primary_left_down_nodeのスクリプト終了タイムアウトを60秒から120秒に変更し、 + 誤エラーが発生する可能性を減らしました。 + </para> + </listitem> + + <listitem> + <!-- + 2025-08-27 [42b177614] + --> + <para> + 023.ssl_connectionにssl_ecdh_curveのテストを追加しました。(Tatsuo Ishii) + </para> + <para> + 023.ssl_connectionはssl_ecdh_curveのテストをカバーしていなかったため、 + 不正なssl_ecdh_curveパラメータでフロントエンドとpgpoolの接続が失敗するか確認しました。 + </para> + </listitem> + </itemizedlist> + </sect2> +</sect1> + +<sect1 id="release-4-4-13"> + <title>リリース 4.4.13</title> + <note> + <title>リリース日</title> + <simpara>2025-08-21</simpara> + </note> + + <sect2> + <title>不具合修正</title> + <itemizedlist> + <listitem> + <!-- + 2025-07-25 [75d905ff9] + --> + <para> + watchdog が不適切な NOTICE メッセージを出力する問題を修正しました。 (Tatsuo Ishii) + </para> + <para> + <function>read_ipc_socket_and_process()</function> は、IPCソケットへのコマンド書き込みのたびに、書き込みが成功した場合でも通知メッセージを出力していました。これを修正し、書き込みが失敗した場合にのみ通知メッセージを出力するようにしました。 + <varname>log_min_messages</varname> が notice 以上に設定されている場合にのみメッセージが表示されるため、このバグが発見されていませんでした。 + </para> + <para> + ディスカッション: <ulink url="https://github.com/pgpool/pgpool2/issues/121">pgpool IPC socket connection issue</ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-07-19 [d05de5c73] + --> + <!-- + 2025-07-19 [ed57af34e] + --> + <para> + スタートアップパケットを読んでいるときのメモリーリークを修正しました。(Tatsuo Ishii) + </para> + <para> + pool_push_pending_data でのリソースリークを修正しました。 + </para> + </listitem> + + <listitem> + <!-- + 2025-06-30 [bac455b2f] + --> + <para> + ビッグエンディアンマシン上の scram-sha-256 認証の不具合を修正しました。(Tatsuo Ishii) + </para> + <para> + <literal>scram-sha-256</literal> 認証を実行する際、ハッシュ関数 <function>pg_sha_256_final</function> が使用されます。 + これは <productname>PostgreSQL</productname> からインポートされたもので、プリプロセッサ定義 WORDS_BIGENDIAN を使用してホストマシンのエンディアンを判断します。 + WORDS_BIGENDIAN は configure 時に定義する必要がありますが、<function>pg_sha_256_final</function>(およびその他)が <productname>PostgreSQL</productname> からインポートされた際にこの部分が省略されていました。 + その結果、scram-sha-256 はリトルエンディアンマシンでのみ動作していました。 + configure.ac に AC_C_BIGENDIAN マクロを追加することでこの問題を修正しました。。 + </para> + <para> + この問題は Christoph Berg によって報告され、 pranavkaruvally によって分析されました。 + </para> + <para> + ディスカッション: <ulink url="https://github.com/pgpool/pgpool2/issues/106">4.6.1 fails on big-endian s390x: backend response with kind 'E' when expecting 'R'</ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-06-23 [2721c7b76] + --> + <para> + ソースコードのタイプミスを修正しました。 (Bo Peng) + </para> + </listitem> + + <listitem> + <!-- + 2025-06-09 [4305c42d6] + --> + <para> + ハートビートデバイスの処理を修正しました。(Tatsuo Ishii) + </para> + <para> + <filename>pgpool.conf</filename> の処理中に、<varname>heartbeat_device</varname> が誤って処理され、最初のデバイスが無視されていました。 + </para> + <para> + この問題は Bo Peng によって分析されました。 + </para> + </listitem> + + <listitem> + <!-- + 2025-06-02 [06ba7dde4] + --> + <para> + <filename>pgpool.conf</filename>のコメントのタイプミスを修正しました。 (Tatsuo Ishii) + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>ドキュメント修正</title> + <itemizedlist> + <listitem> + <!-- + 2025-08-15 [a54f5d1ad] + --> + <para> + 「8.3. ネイティブレプリケーション/スナップショットアイソレーションモードの構築の例」のドキュメントを改善しました。(Taiki Koshino) + </para> + <para> + サンプルスクリプトのリンクと「事前設定」説明を改善しました。 + </para> + </listitem> + + <listitem> + <!-- + 2025-08-04 [e2f24fec8] + --> + <para> + リロードによって反映されないパラメータのドキュメントを修正しました。 (Taiki Koshino) + </para> + <para> + <varname>authentication_timeout</varname> と <varname>memqcache_oiddir</varname> はリロードしても反映されません。 + ドキュメントが「このパラメータはサーバー起動時にのみ設定できます。」に変更されました。 + </para> + </listitem> + + <listitem> + <!-- + 2025-07-24 [bc5fa5e7e] + --> + <!-- + 2025-07-23 [1e8963554] + --> + <para> + watchdog リーダーの用語を統一しました。(Tatsuo Ishii) + </para> + <para> + 以前は「leader」「active」「coordinater」という用語が、watchdog のリーダーノードを指すために使用されていました。このコミットではこれらを「leader」に統一しました。 + advanced.sgml も修正しました。 + </para> + </listitem> + + <listitem> + <!-- + 2025-08-06 [31eee18d7] + --> + <!-- + 2025-07-16 [34b07c2d5] + --> + <para> + サンプルスクリプトを修正しました。(Taiki Koshino) + </para> + <para> + 「<ulink url="https://www.pgpool.net/docs/latest/ja/html/example-cluster.html">8.2. Pgpool-II + Watchdogの構築の例</ulink>」のサンプルスクリプトを修正しました。 + </para> + </listitem> + + <listitem> + <!-- + 2025-06-18 [f4ae9f39e] + 2025-06-18 [7a20dc419] + --> + <para> + ロードバランスの説明で論理レプリケーションモードと Slony モードが抜けている問題を修正しました(Tatsuo Ishii) + </para> + </listitem> + + <listitem> + <!-- + 2025-06-18 [9d2e4e692] + --> + <para> + <xref linkend="pcp-node-info">のドキュメントを改善しました。 (Bo Peng) + </para> + <para> + 「<varname>replication_state</varname>」と「<varname>replication_sync_state</varname>」を正しく表示するには、各 <varname>backend_application_nameX</varname> が <varname>primary_conninfo</varname> の <varname>application_name</varname> に指定された値と一致する必要があることを明確にしました。 + </para> + </listitem> + + <listitem> + <!-- + 2025-06-08 [59f9df005] + --> + <para> + カーネルの資源に関するセクションを追加しました。 (Tatsuo Ishii) + </para> + <para> + <productname>Pgpool-II</productname> は System V の共有メモリとセマフォを使用します。 + 要件についてはドキュメントを参照することをお勧めします。 + </para> + </listitem> + + <listitem> + <!-- + 2025-06-07 [40617fd90] + --> + <para> + configure の <option>--with-ldap</option> オプションの説明を追加しました。(Tatsuo Ishii) + </para> + <para> + これは LDAPサポートがv4.2で導入されたときに見落としていました。 + </para> + </listitem> + + <listitem> + <!-- + 2025-06-04 [ff60bf930] + --> + <para> + <productname>Pgpool-II</productname> でサポートされているプラットフォームを明確にしました。 (Tatsuo Ishii) + </para> + </listitem> + + <listitem> + <!-- + 2025-06-03 [cc4da5979] + --> + <para> + <xref linkend="guc-child-life-time"> のドキュメントを改善しました。 (Tatsuo Ishii) + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>回帰テスト修正</title> + <itemizedlist> + <listitem> + <!-- + 2025-06-08 [78e45decf] + --> + <para> + 029.cert_passphrase 回帰テストを安定化しました。 (Tatsuo Ishii) + </para> + <para> + <varname>ssl_passphrase_command</varname> が有効でない場合、エラーメッセージは通常「bad decrypt」ですが、「wrong tag」となる場合もありました。 + </para> + </listitem> + </itemizedlist> + </sect2> +</sect1> + <sect1 id="release-4-4-12"> <title>リリース 4.4.12</title> <note> diff --git a/doc.ja/src/sgml/release-4.5.sgml b/doc.ja/src/sgml/release-4.5.sgml index 30cde86af..bdeb50db4 100644 --- a/doc.ja/src/sgml/release-4.5.sgml +++ b/doc.ja/src/sgml/release-4.5.sgml @@ -1,6 +1,581 @@ <!-- doc/src/sgml/release-4.5.sgml --> <!-- See header comment in release.sgml about typical markup --> +<sect1 id="release-4-5-10"> + <title>リリース 4.5.10</title> + <note> + <title>リリース日</title> + <simpara>2025-12-15</simpara> + </note> + + <sect2> + <title>変更点</title> + <itemizedlist> + <listitem> + <!-- + 2025-12-08 [5bd10177c] + --> + <para> + pgpool_setupで非推奨の「egrep」の代わりに「grep -E」を使用するようにしました。(Bo Peng) + </para> + <para> + 新しいGNUのgrepバージョンでの廃止警告を回避するために、「egrep」を「grep -E」に置き換えました。 + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>不具合修正</title> + <itemizedlist> + <listitem> + <!-- + 2025-12-08 [8deccc15e] + --> + <para> + show pool_statusのバッファオーバーフローエラーを修正しました。(Tatsuo Ishii) + </para> + <para> + SHOW POOL_STATUS、pgpool show、および pcp_pool_statusコマンドでバッファオーバーフローが発生する問題を修正しました。 + 問題の原因は、backend_flagがALWAYS_PRIMARYに設定されている場合に、pool_flag_to_str()関数がbackend_flagを文字列化する際に静的バッファの末尾を越えて書き込んでしまうことでした。 + </para> + <para> + この問題はzam bakによって報告され、Bo Pengによってよって分析されました。 + </para> + <para> + ディスカッション: <ulink url="https://www.postgresql.org/message-id/20251202.140205.427777414210613577.ishii%40postgresql.org">Re: "buffer overflow detected" when running SHOW POOL_STATUS</ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-12-02 [c8865c703] + --> + <para> + 「show pool_status」に表示されるmemqcache_stats_start_timeの出力を修正しました。(Tatsuo Ishii) + </para> + <para> + get_config()がctime()を使って時刻を文字列化していましたが、ctime()の戻り値の末尾には改行が含まれることを考慮していませんでした。 + その結果、memqcache_stats_start_timeの行に余計な改行が入り、さらに次の行が空欄として表示されてしまう問題が発生していました。 + </para> + <para> + ディスカッション: <ulink url="https://www.postgresql.org/message-id/20251130.102712.131456481338876013.ishii%40postgresql.org">Re: "buffer overflow detected" when running SHOW POOL_STATUS</ulink> + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>回帰テスト修正</title> + <itemizedlist> + <listitem> + <!-- + 2025-11-25 [0c45a1e01] + --> + <para> + 037.failover_sessionのテストを安定させました。(Tatsuo Ishii) + </para> + <para> + 特定の環境では、test1の後にshutdownallが終了しないことがありました。 + これは、テスト中のフェイルオーバー処理が、shutdownallからの終了シグナルを受け取れるようにしているシグナルハンドラの復元に失敗していることが原因と考えられます。 + shutdownall の前にsleep 5を追加することで、この問題が緩和されることを確認しました。 + </para> + </listitem> + </itemizedlist> + </sect2> +</sect1> + +<sect1 id="release-4-5-9"> + <title>リリース 4.5.9</title> + <note> + <title>リリース日</title> + <simpara>2025-11-25</simpara> + </note> + + <sect2> + <title>変更点</title> + <itemizedlist> + <listitem> + <!-- + 2025-11-07 [4fabca331] + --> + <para> + 不要な <varname>application_name</varname> の処理を削除しました。(Tatsuo Ishii) + </para> + <para> + 以前のコミットで、既存接続を再利用する際に <varname>application_name</varname> を設定する処理が追加されました。 + しかしこれは不要です。DISCARD ALLにより接続再利用時に自動的に <varname>application_name</varname> がリセットされ、 + <function>send_params()</function>によってフロントエンドに必要なパラメータステータス(<varname>application_name</varname> を含む)が送信されます。 + この冗長な処理を削除することで、特に地理的に離れたバックエンドノードでのパフォーマンスが向上します。 + </para> + <para> + ディスカッション: <ulink url="https://github.com/pgpool/pgpool2/issues/130">Severely degraded performance of pgPool in geo-distributed configurations</ulink> + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>不具合修正</title> + <itemizedlist> + <listitem> + <!-- + 2025-11-16 [b113027dd] + --> + <para> + <command>CopyOut</command>でのセグメンテーションフォルトを修正しました。(Tatsuo Ishii) + </para> + <para> + 拡張プロトコルで<command>COPY relname TO STDOUT</command>が実行された場合、<productname>Pgpool-II</productname>がセグフォルトを起こしていました。 + </para> + <para> + この問題は<ulink url="https://github.com/tetesh">https://github.com/tetesh</ulink>によって報告されました。 + </para> + <para> + ディスカッション: <ulink url="https://github.com/pgpool/pgpool2/issues/133">datanymizer and pg-pool segmentation fault</ulink> + </para> + </listitem> + <listitem> + <!-- + 2025-10-03 [b84553bf0] + --> + <para> + Watchdogのスプリットブレイン回避するよう修正しました。(Tatsuo Ishii) + </para> + <para> + Watchdogはビーコンメッセージとハートビートで通信します。 + ハートビートが有効でない場合、ビーコンが30秒以上届かないとスプリットブレインが発生することがあります。 + 古いリーダーを無効化することで、同時に二人のリーダーが存在しないように修正しました。 + ノードがリーダーからのビーコンを2回以上見逃すと、リーダーはLOST状態となり、 + set_state(WD_JOINING) により新リーダー選出が開始されます。 + </para> + </listitem> + + <listitem> + <!-- + 2025-10-03 [ef8ccb9e7] + --> + <para> + 存在しないプリペアドステートメント使用時のFATALエラー防止するよう修正しました。(Tatsuo Ishii) + </para> + <para> + 以前は<function>Bind()</function>が存在しないプリペアドステートメントでFATALエラーを出していました。 + はステートメントの存在を確認し、存在しない場合はフロントエンドにERRORメッセージを送信するようになりました。ログは残りません。 + </para> + </listitem> + + <listitem> + <!-- + 2025-09-24 [59a359eef] + --> + <para> + <xref linkend="pg-enc"> -pと -P両方使用時に動作しない問題を修正しました。(Tatsuo Ishii) + </para> + <para> + 元の報告では、pg_enc -p -P実行時にパスワードと暗号キーを求められましたが、 + キーが提供されない場合に失敗していました。 + また、コメント /* prompt for postgres password */ が誤解を招くため、 + /* prompt for password to be encrypted */ に修正されました。 + </para> + <para> + ディスカッション: <ulink url="https://www.postgresql.org/message-id/7f18c30b.237.1997555ca11.Coremail.liujy%40highgo.com">pg_enc</ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-09-18 [f20f7041c] + --> + <para> + 32ビット環境でのコンパイルの問題を修正しました。(Tatsuo Ishii) + </para> + <para> + 32ビットシステムでsrc/parser/snprintf.cをコンパイルすると<function>isnan()</function>や<function>isinf()</function>が未定義でエラーになりました。 + math.hをインクルードし、ヘッダーファイルの順序も整理しました。 + 元々 PostgreSQLから取り込まれたファイルで、math.hは既に含まれていました。 + 修正は <ulink url="https://github.com/pgpool/pgpool2/pull/128">fix compiling issues for 32-bit targets</ulink> のプルリクエストに記載してあります。 + </para> + </listitem> + + <listitem> + <!-- + 2025-09-10 [0a6868d40] + --> + <para> + recovery_1st_stage.sampleでBashのディレクトリ削除を安全に行うよう修正しました。(Taiki Koshino) + </para> + <para> + rmコマンドの変数をクォートし、意図しない削除を防止しました: + <command>rm -rf "${DEST_NODE_PGDATA}"</command> + </para> + </listitem> + + <listitem> + <!-- + 2025-09-05 [441f338ab] + --> + <para> + <option>--with-memcached</option>指定なしでコンパイルする際のエラーを修正しました。(Tatsuo Ishii) + </para> + <para> + <option>--with-memcached</option>指定なしでコンパイルするとエラーが発生していました。 + 対応として該当コードブロックを #ifdef USE_MEMCACHEDで囲みました。 + </para> + <para> + この問題はBo Pengによって報告されました。 + </para> + </listitem> + + <listitem> + <!-- + 2025-09-04 [9e0324575] + --> + <para> + クエリキャッシュロックファイルの取り扱い修正を修正しました。(Tatsuo Ishii) + </para> + <para> + クエリキャッシュモジュールは並列制御のため <varname>logdir</varname> にロックファイルを作成しますが、 + メインプロセスがゴミファイルを作成したり、シャットダウン時に削除されない問題がありました。 + </para> + <para> + この問題はBo Pengによって報告・分析されました。 + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>ドキュメント修正</title> + <itemizedlist> + <listitem> + <!-- + 2025-09-17 [1a975b539] + --> + <para> + <ulink url="https://www.pgpool.net/docs/latest/ja/html/example-cluster.html">8.2. Pgpool-II + Watchdog Setup Example</ulink> の "PostgreSQLスタンバイ設定" ドキュメントを更新しました。(Taiki Koshino) + </para> + <para> + オンラインリカバリなしでスタンバイを設定する場合、postgresql.auto.confに <varname>primary_conninfo</varname> を書き込まないよう注意を追加しました。 + </para> + <para> + ディスカッション: <ulink url="https://github.com/pgpool/pgpool2/issues/67">Follow primary command not fixing postgresql.auto.conf </ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-08-22 [5bd535792] + --> + <para> + watchdog_setupのマニュアルを修正しました。(Tatsuo Ishii) + </para> + <para> + heartbeartがwatchdog_setupに設定されていないと誤記されていた箇所を修正しました。 + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>回帰テスト修正</title> + <itemizedlist> + <listitem> + <!-- + 2025-09-30 [3ddbc64f1] + --> + <para> + 023.ssl_connectionをPostgreSQL 18に対応するよう修正しました。(Tatsuo Ishii) + </para> + <para> + PostgreSQL 18でpsqlの \conninfo出力形式が大幅に変更されたため、 + このテストが失敗していました。 + PostgreSQLバージョンに応じてテストスクリプトを修正しました。 + </para> + </listitem> + + <listitem> + <!-- + 2025-08-29 [b4043e6c3] + --> + <para> + 010.rewrite_timestampのRubyスクリプトを修正しました。(Tatsuo Ishii) + </para> + <para> + RubyのFile.existsは新しいバージョンで非推奨のため、File.existに置き換えました。 + </para> + </listitem> + + <listitem> + <!-- + 2025-08-29 [9c901e60a] + --> + <para> + 034と075のタイムアウトを調整しました。(Tatsuo Ishii) + </para> + <para> + 034.promote_nodeと075.detach_primary_left_down_nodeのスクリプト終了タイムアウトを60秒から120秒に変更し、 + 誤エラーが発生する可能性を減らしました。 + </para> + </listitem> + + <listitem> + <!-- + 2025-08-27 [42b177614] + --> + <para> + 023.ssl_connectionにssl_ecdh_curveのテストを追加しました。(Tatsuo Ishii) + </para> + <para> + 023.ssl_connectionはssl_ecdh_curveのテストをカバーしていなかったため、 + 不正なssl_ecdh_curveパラメータでフロントエンドとpgpoolの接続が失敗するか確認しました。 + </para> + </listitem> + </itemizedlist> + </sect2> +</sect1> + +<sect1 id="release-4-5-8"> + <title>リリース 4.5.8</title> + <note> + <title>リリース日</title> + <simpara>2025-08-21</simpara> + </note> + + <sect2> + <title>不具合修正</title> + <itemizedlist> + <listitem> + <!-- + 2025-07-25 [75d905ff9] + --> + <para> + watchdog が不適切な NOTICE メッセージを出力する問題を修正しました。 (Tatsuo Ishii) + </para> + <para> + <function>read_ipc_socket_and_process()</function> は、IPCソケットへのコマンド書き込みのたびに、書き込みが成功した場合でも通知メッセージを出力していました。これを修正し、書き込みが失敗した場合にのみ通知メッセージを出力するようにしました。 + <varname>log_min_messages</varname> が notice 以上に設定されている場合にのみメッセージが表示されるため、このバグが発見されていませんでした。 + </para> + <para> + ディスカッション: <ulink url="https://github.com/pgpool/pgpool2/issues/121">pgpool IPC socket connection issue</ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-07-19 [d05de5c73] + --> + <!-- + 2025-07-19 [ed57af34e] + --> + <para> + スタートアップパケットを読んでいるときのメモリーリークを修正しました。(Tatsuo Ishii) + </para> + <para> + pool_push_pending_data でのリソースリークを修正しました。 + </para> + </listitem> + + <listitem> + <!-- + 2025-06-30 [bac455b2f] + --> + <para> + ビッグエンディアンマシン上の scram-sha-256 認証の不具合を修正しました。(Tatsuo Ishii) + </para> + <para> + <literal>scram-sha-256</literal> 認証を実行する際、ハッシュ関数 <function>pg_sha_256_final</function> が使用されます。 + これは <productname>PostgreSQL</productname> からインポートされたもので、プリプロセッサ定義 WORDS_BIGENDIAN を使用してホストマシンのエンディアンを判断します。 + WORDS_BIGENDIAN は configure 時に定義する必要がありますが、<function>pg_sha_256_final</function>(およびその他)が <productname>PostgreSQL</productname> からインポートされた際にこの部分が省略されていました。 + その結果、scram-sha-256 はリトルエンディアンマシンでのみ動作していました。 + configure.ac に AC_C_BIGENDIAN マクロを追加することでこの問題を修正しました。。 + </para> + <para> + この問題は Christoph Berg によって報告され、 pranavkaruvally によって分析されました。 + </para> + <para> + ディスカッション: <ulink url="https://github.com/pgpool/pgpool2/issues/106">4.6.1 fails on big-endian s390x: backend response with kind 'E' when expecting 'R'</ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-06-23 [2721c7b76] + --> + <para> + ソースコードのタイプミスを修正しました。 (Bo Peng) + </para> + </listitem> + + <listitem> + <!-- + 2025-06-09 [4305c42d6] + --> + <para> + ハートビートデバイスの処理を修正しました。(Tatsuo Ishii) + </para> + <para> + <filename>pgpool.conf</filename> の処理中に、<varname>heartbeat_device</varname> が誤って処理され、最初のデバイスが無視されていました。 + </para> + <para> + この問題は Bo Peng によって分析されました。 + </para> + </listitem> + + <listitem> + <!-- + 2025-06-02 [06ba7dde4] + --> + <para> + <filename>pgpool.conf</filename>のコメントのタイプミスを修正しました。 (Tatsuo Ishii) + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>ドキュメント修正</title> + <itemizedlist> + <listitem> + <!-- + 2025-08-15 [a54f5d1ad] + --> + <para> + 「8.3. ネイティブレプリケーション/スナップショットアイソレーションモードの構築の例」のドキュメントを改善しました。(Taiki Koshino) + </para> + <para> + サンプルスクリプトのリンクと「事前設定」の説明を改善しました。 + </para> + </listitem> + + <listitem> + <!-- + 2025-08-04 [e2f24fec8] + --> + <para> + リロードによって反映されないパラメータのドキュメントを修正しました。 (Taiki Koshino) + </para> + <para> + <varname>authentication_timeout</varname> と <varname>memqcache_oiddir</varname> はリロードしても反映されません。 + ドキュメントが「このパラメータはサーバー起動時にのみ設定できます。」に変更されました。 + </para> + </listitem> + + <listitem> + <!-- + 2025-07-24 [bc5fa5e7e] + --> + <!-- + 2025-07-23 [1e8963554] + --> + <para> + watchdog リーダーの用語を統一しました。(Tatsuo Ishii) + </para> + <para> + 以前は「leader」「active」「coordinater」という用語が、watchdog のリーダーノードを指すために使用されていました。このコミットではこれらを「leader」に統一しました。 + advanced.sgml も修正しました。 + </para> + </listitem> + + <listitem> + <!-- + 2025-08-06 [31eee18d7] + --> + <!-- + 2025-07-16 [34b07c2d5] + --> + <para> + サンプルスクリプトを修正しました。(Taiki Koshino) + </para> + <para> + 「<ulink url="https://www.pgpool.net/docs/latest/ja/html/example-cluster.html">8.2. Pgpool-II + Watchdogの構築の例</ulink>」のサンプルスクリプトを修正しました。 + </para> + </listitem> + + <listitem> + <!-- + 2025-06-18 [f4ae9f39e] + 2025-06-18 [7a20dc419] + --> + <para> + ロードバランスの説明で論理レプリケーションモードと Slony モードが抜けている問題を修正しました(Tatsuo Ishii) + </para> + </listitem> + + <listitem> + <!-- + 2025-06-18 [9d2e4e692] + --> + <para> + <xref linkend="pcp-node-info">のドキュメントを改善しました。 (Bo Peng) + </para> + <para> + 「<varname>replication_state</varname>」と「<varname>replication_sync_state</varname>」を正しく表示するには、各 <varname>backend_application_nameX</varname> が <varname>primary_conninfo</varname> の <varname>application_name</varname> に指定された値と一致する必要があることを明確にしました。 + </para> + </listitem> + + <listitem> + <!-- + 2025-06-08 [59f9df005] + --> + <para> + カーネルの資源に関するセクションを追加しました。 (Tatsuo Ishii) + </para> + <para> + <productname>Pgpool-II</productname> は System V の共有メモリとセマフォを使用します。 + 要件についてはドキュメントを参照することをお勧めします。 + </para> + </listitem> + + <listitem> + <!-- + 2025-06-07 [40617fd90] + --> + <para> + configure の <option>--with-ldap</option> オプションの説明を追加しました。(Tatsuo Ishii) + </para> + <para> + これは LDAPサポートがv4.2で導入されたときに見落としていました。 + </para> + </listitem> + + <listitem> + <!-- + 2025-06-04 [ff60bf930] + --> + <para> + <productname>Pgpool-II</productname> でサポートされているプラットフォームを明確にしました。 (Tatsuo Ishii) + </para> + </listitem> + + <listitem> + <!-- + 2025-06-03 [cc4da5979] + --> + <para> + <xref linkend="guc-child-life-time"> のドキュメントを改善しました。 (Tatsuo Ishii) + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>回帰テスト修正</title> + <itemizedlist> + <listitem> + <!-- + 2025-06-08 [78e45decf] + --> + <para> + 029.cert_passphrase 回帰テストを安定化しました。 (Tatsuo Ishii) + </para> + <para> + <varname>ssl_passphrase_command</varname> が有効でない場合、エラーメッセージは通常「bad decrypt」ですが、「wrong tag」となる場合もありました。 + </para> + </listitem> + </itemizedlist> + </sect2> +</sect1> + <sect1 id="release-4-5-7"> <title>リリース 4.5.7</title> <note> diff --git a/doc.ja/src/sgml/release-4.6.sgml b/doc.ja/src/sgml/release-4.6.sgml index d0b7fe9d8..931f0029f 100644 --- a/doc.ja/src/sgml/release-4.6.sgml +++ b/doc.ja/src/sgml/release-4.6.sgml @@ -1,3 +1,738 @@ +<sect1 id="release-4-6-5"> + <title>リリース 4.6.5</title> + <note> + <title>リリース日</title> + <simpara>2025-12-15</simpara> + </note> + + <sect2> + <title>変更点</title> + <itemizedlist> + <listitem> + <!-- + 2025-12-08 [5bd10177c] + --> + <para> + pgpool_setupで非推奨の「egrep」の代わりに「grep -E」を使用するようにしました。(Bo Peng) + </para> + <para> + 新しいGNUのgrepバージョンでの廃止警告を回避するために、「egrep」を「grep -E」に置き換えました。 + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>不具合修正</title> + <itemizedlist> + <listitem> + <!-- + 2025-12-08 [8deccc15e] + --> + <para> + show pool_statusのバッファオーバーフローエラーを修正しました。(Tatsuo Ishii) + </para> + <para> + SHOW POOL_STATUS、pgpool show、および pcp_pool_statusコマンドでバッファオーバーフローが発生する問題を修正しました。 + 問題の原因は、backend_flagがALWAYS_PRIMARYに設定されている場合に、pool_flag_to_str()関数がbackend_flagを文字列化する際に静的バッファの末尾を越えて書き込んでしまうことでした。 + </para> + <para> + この問題はzam bakによって報告され、Bo Pengによってよって分析されました。 + </para> + <para> + ディスカッション: <ulink url="https://www.postgresql.org/message-id/20251202.140205.427777414210613577.ishii%40postgresql.org">Re: "buffer overflow detected" when running SHOW POOL_STATUS</ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-12-02 [c8865c703] + --> + <para> + 「show pool_status」に表示されるmemqcache_stats_start_timeの出力を修正しました。(Tatsuo Ishii) + </para> + <para> + get_config()がctime()を使って時刻を文字列化していましたが、ctime()の戻り値の末尾には改行が含まれることを考慮していませんでした。 + その結果、memqcache_stats_start_timeの行に余計な改行が入り、さらに次の行が空欄として表示されてしまう問題が発生していました。 + </para> + <para> + ディスカッション: <ulink url="https://www.postgresql.org/message-id/20251130.102712.131456481338876013.ishii%40postgresql.org">Re: "buffer overflow detected" when running SHOW POOL_STATUS</ulink> + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>回帰テスト修正</title> + <itemizedlist> + <listitem> + <!-- + 2025-11-25 [0c45a1e01] + --> + <para> + 037.failover_sessionのテストを安定させました。(Tatsuo Ishii) + </para> + <para> + 特定の環境では、test1の後にshutdownallが終了しないことがありました。 + これは、テスト中のフェイルオーバー処理が、shutdownallからの終了シグナルを受け取れるようにしているシグナルハンドラの復元に失敗していることが原因と考えられます。 + shutdownall の前にsleep 5を追加することで、この問題が緩和されることを確認しました。 + </para> + </listitem> + </itemizedlist> + </sect2> +</sect1> + +<sect1 id="release-4-6-4"> + <title>リリース 4.6.4</title> + <note> + <title>リリース日</title> + <simpara>2025-11-25</simpara> + </note> + + <sect2> + <title>変更点</title> + <itemizedlist> + <listitem> + <!-- + 2025-11-07 [4fabca331] + --> + <para> + 不要な<varname>application_name</varname>の処理を削除しました。(Tatsuo Ishii) + </para> + <para> + 以前のコミットで、既存接続を再利用する際に<varname>application_name</varname>を設定する処理が追加されました。 + しかしこれは不要です。DISCARD ALLにより接続再利用時に自動的に<varname>application_name</varname>がリセットされ、 + <function>send_params()</function>によってフロントエンドに必要なパラメータステータス(<varname>application_name</varname>を含む)が送信されます。 + この冗長な処理を削除することで、特に地理的に離れたバックエンドノードでのパフォーマンスが向上します。 + </para> + <para> + ディスカッション: <ulink url="https://github.com/pgpool/pgpool2/issues/130">Severely degraded performance of pgPool in geo-distributed configurations</ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-10-09 [f91abf862] + --> + <para> + 時間計算を常にlong longに変更しました。(Tatsuo Ishii) + </para> + <para> + 以前、<productname>Pgpool-II</productname> はtime_tを単なるlongとして扱っており、OpenBSDのようなシステムではコンパイル時警告が発生していました。 + 計算をlong longにアップキャストするようにしてトランケーションを防ぎ、 + 64ビットクリーンなtime_tシステムでもY2038問題後も正しく動作するようにしています。 + また、json_get_long_value_for_keyはjson_get_llong_value_for_keyに変更され、パラメータもlong longになりました。 + これにより_json_valueのint64型と整合性が取れ、32ビット環境でも大きな整数を正しく扱えるようになりました。 + </para> + <para> + この問題はTatsuo IshiiとGyorgy Sarvariによって分析されました。 + </para> + <para> + ディスカッション: <ulink url="https://www.pgpool.net/pipermail/pgpool-hackers/2025-May/004584.html">Fix time_t warnings on OpenBSD</ulink> + </para> + <para> + ディスカッション: <ulink url="https://www.postgresql.org/message-id/20251003.211957.2067537305399895611.ishii%40postgresql.org">Fix time_t warnings on OpenBSD</ulink> + </para> + <para> + ディスカッション: <ulink url="https://github.com/pgpool/pgpool2/issues/128">fix compiling issues for 32-bit targets</ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-08-31 [dced45a52] + --> + <para> + GCC 15 (C23) でコンパイル可能にしました。(Tatsuo Ishii) + </para> + <para> + Fedora 42 + GCC 15で<productname>Pgpool-II</productname>をコンパイルできるよう修正しました。 + pool_type.hをstdbool.hに変更し、TRUE/FALSEを (bool)1 / (bool)0と定義しました。 + 関数ポインタの引数が呼び出し先プロトタイプと一致するよう修正され、 + <function>pool_create_relcache()</function>のプロトタイプも更新されました。 + <function>raw_expression_tree_walker()</function>内の<function>walker()</function>呼び出しは、WALKマクロを使い (Node *) キャストされるよう変更されました。 + OpenSSLに関する警告はまだ残っており、将来的に対応予定です。 + </para> + <para> + ディスカッション: <ulink url="https://github.com/pgpool/pgpool2/issues/124">4.6.X build issue against GCC 15</ulink> + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>不具合修正</title> + <itemizedlist> + <listitem> + <!-- + 2025-11-16 [b113027dd] + --> + <para> + <command>CopyOut</command>でのセグメンテーションフォルトを修正しました。(Tatsuo Ishii) + </para> + <para> + 拡張プロトコルで<command>COPY relname TO STDOUT</command>が実行された場合、<productname>Pgpool-II</productname>がセグフォルトを起こしていました。 + </para> + <para> + この問題は<ulink url="https://github.com/tetesh">https://github.com/tetesh</ulink>によって報告されました。 + </para> + <para> + ディスカッション: <ulink url="https://github.com/pgpool/pgpool2/issues/133">datanymizer and pg-pool segmentation fault</ulink> + </para> + </listitem> + <listitem> + <!-- + 2025-10-03 [b84553bf0] + --> + <para> + Watchdogのスプリットブレイン回避するよう修正しました。(Tatsuo Ishii) + </para> + <para> + Watchdogはビーコンメッセージとハートビートで通信します。 + ハートビートが有効でない場合、ビーコンが30秒以上届かないとスプリットブレインが発生することがあります。 + 古いリーダーを無効化することで、同時に二人のリーダーが存在しないように修正しました。 + ノードがリーダーからのビーコンを2回以上見逃すと、リーダーはLOST状態となり、 + set_state(WD_JOINING) により新リーダー選出が開始されます。 + </para> + </listitem> + + <listitem> + <!-- + 2025-10-03 [ef8ccb9e7] + --> + <para> + 存在しないプリペアドステートメント使用時のFATALエラー防止するよう修正しました。(Tatsuo Ishii) + </para> + <para> + 以前は<function>Bind()</function>が存在しないプリペアドステートメントでFATALエラーを出していました。 + はステートメントの存在を確認し、存在しない場合はフロントエンドにERRORメッセージを送信するようになりました。ログは残りません。 + </para> + </listitem> + + <listitem> + <!-- + 2025-09-24 [59a359eef] + --> + <para> + <xref linkend="pg-enc"> が -pと -P両方使用時に動作しない問題を修正しました。(Tatsuo Ishii) + </para> + <para> + 元の報告では、pg_enc -p -P実行時にパスワードと暗号キーを求められましたが、 + キーが提供されない場合に失敗していました。 + </para> + <para> + ディスカッション: <ulink url="https://www.postgresql.org/message-id/7f18c30b.237.1997555ca11.Coremail.liujy%40highgo.com">pg_enc</ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-09-18 [f20f7041c] + --> + <para> + 32ビット環境でのコンパイルの問題を修正しました。(Tatsuo Ishii) + </para> + <para> + 32ビットシステムでsrc/parser/snprintf.cをコンパイルすると<function>isnan()</function>や<function>isinf()</function>が未定義でエラーになりました。 + math.hをインクルードし、ヘッダーファイルの順序も整理しました。 + 元々 PostgreSQLから取り込まれたファイルで、math.hは既に含まれていました。 + 修正は <ulink url="https://github.com/pgpool/pgpool2/pull/128">fix compiling issues for 32-bit targets</ulink> のプルリクエストに記載してあります。 + </para> + </listitem> + + <listitem> + <!-- + 2025-09-10 [0a6868d40] + --> + <para> + recovery_1st_stage.sampleでBashのディレクトリ削除を安全に行うよう修正しました。(Taiki Koshino) + </para> + <para> + rmコマンドの変数をクォートし、意図しない削除を防止しました: + <command>rm -rf "${DEST_NODE_PGDATA}"</command> + </para> + </listitem> + + <listitem> + <!-- + 2025-09-05 [1793db95f] + --> + <para> + クエリキャッシュ無効化時の不要な警告が出ないよう修正しました。(Tatsuo Ishii) + </para> + <para> + memcachedサポートが無効な場合、クエリキャッシュ無効化時に不要な警告が出ていました。 + これにより006.memcachedリグレッションテストが失敗していました。 + </para> + </listitem> + + <listitem> + <!-- + 2025-09-05 [441f338ab] + --> + <para> + <option>--with-memcached</option>指定なしでコンパイルする際のエラーを修正しました。(Tatsuo Ishii) + </para> + <para> + <option>--with-memcached</option>指定なしでコンパイルするとエラーが発生していました。 + 対応として該当コードブロックを #ifdef USE_MEMCACHEDで囲みました。 + </para> + <para> + この問題はBo Pengによって報告されました。 + </para> + </listitem> + + <listitem> + <!-- + 2025-09-04 [9e0324575] + --> + <para> + クエリキャッシュのロックファイルの取り扱い修正を修正しました。(Tatsuo Ishii) + </para> + <para> + クエリキャッシュモジュールは並列制御のため<varname>logdir</varname>にロックファイルを作成しますが、 + メインプロセスがゴミファイルを作成したり、シャットダウン時に削除されない問題がありました。 + </para> + <para> + この問題はBo Pengによって報告・分析されました。 + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>ドキュメント修正</title> + <itemizedlist> + <listitem> + <!-- + 2025-09-17 [1a975b539] + --> + <para> + <ulink url="https://www.pgpool.net/docs/latest/ja/html/example-cluster.html">8.2. Pgpool-II + Watchdog Setup Example</ulink>の"PostgreSQLスタンバイ設定"ドキュメントを更新しました。(Taiki Koshino) + </para> + <para> + オンラインリカバリなしでスタンバイを設定する場合、postgresql.auto.confに<varname>primary_conninfo</varname>を書き込まないよう注意を追加しました。 + </para> + <para> + ディスカッション: <ulink url="https://github.com/pgpool/pgpool2/issues/67">Follow primary command not fixing postgresql.auto.conf </ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-08-22 [5bd535792] + --> + <para> + watchdog_setupのマニュアルを修正しました。(Tatsuo Ishii) + </para> + <para> + heartbeartがwatchdog_setupに設定されていないと誤記されていた箇所を修正しました。 + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>回帰テスト修正</title> + <itemizedlist> + <listitem> + <!-- + 2025-09-30 [3ddbc64f1] + --> + <para> + 023.ssl_connectionをPostgreSQL 18に対応するよう修正しました。(Tatsuo Ishii) + </para> + <para> + PostgreSQL 18でpsqlの\conninfo出力形式が大幅に変更されたため、 + このテストが失敗していました。 + PostgreSQLバージョンに応じてテストスクリプトを修正しました。 + </para> + </listitem> + + <listitem> + <!-- + 2025-08-31 [3897b7afd] + --> + <para> + 039.log_backend_messagesを修正しました。(Tatsuo Ishii) + </para> + <para> + 同期コミットパラメータがpgpool.confに誤って設定されていました。 + 正しいpostgresql.confに移動し、クラスタリングモードがストリーミングレプリケーションかを確認することでテストを修復しました。 + </para> + </listitem> + + <listitem> + <!-- + 2025-08-31 [0f19fc60a] + --> + <para> + 039.log_backend_messagesテストを安定化しました。(Tatsuo Ishii) + </para> + <para> + テスト中、プライマリに行を挿入後、レプリケーション遅延によりスタンバイで行が見つからない場合がありました。 + <varname>remote_apply</varname>オプションを用いた同期レプリケーションを利用して問題を改善しました。 + </para> + </listitem> + + <listitem> + <!-- + 2025-08-29 [b4043e6c3] + --> + <para> + 010.rewrite_timestampのRubyスクリプトを修正しました。(Tatsuo Ishii) + </para> + <para> + RubyのFile.existsは新しいバージョンで非推奨のため、File.existに置き換えました。 + </para> + </listitem> + + <listitem> + <!-- + 2025-08-29 [9c901e60a] + --> + <para> + 034と075のタイムアウトを調整しました。(Tatsuo Ishii) + </para> + <para> + 034.promote_nodeと075.detach_primary_left_down_nodeのスクリプト終了タイムアウトを60秒から120秒に変更し、 + 誤エラーが発生する可能性を減らしました。 + </para> + </listitem> + + <listitem> + <!-- + 2025-08-27 [42b177614] + --> + <para> + 023.ssl_connectionにssl_ecdh_curveのテストを追加しました。(Tatsuo Ishii) + </para> + <para> + 023.ssl_connectionはssl_ecdh_curveのテストをカバーしていなかったため、 + 不正なssl_ecdh_curveパラメータでフロントエンドとpgpool の接続が失敗するか確認しました。 + </para> + </listitem> + </itemizedlist> + </sect2> +</sect1> + +<sect1 id="release-4-6-3"> + <title>リリース 4.6.3</title> + <note> + <title>リリース日</title> + <simpara>2025-08-21</simpara> + </note> + + <sect2> + <title>変更点</title> + <itemizedlist> + <listitem> + <!-- + 2025-06-13 [ebfd2423c] + --> + <para> + バックエンドへの接続プロセスを強化しました。 (Tatsuo Ishii) + </para> + <para> + 特定の環境(特に k8s)では、DNS ルックアップが不安定になり、バックエンドプロセスへの接続に失敗します。これは、<function>connect_inet_domain_socket_by_port()</function> 内の <function>getaddrinfo()</function> の呼び出しで発生します。 + この状況を改善するために、<function>getaddrinfo()</function> が EAI_AGAIN で失敗した場合、最大 5 回まで再試行します(再試行ごとに 1 秒間スリープします)。 + <function>connect_inet_domain_socket_by_port()</function> が "retry" 引数を false に設定して呼び出された場合、再試行は行われないことに注意してください。 + ヘルスチェックは、再試行フラグを false に設定して <function>connect_inet_domain_socket_by_port()</function> を呼び出すため、再試行はヘルスチェック自身のパラメータによって制御されます。 + </para> + <para> + ディスカッション: <ulink url="https://github.com/pgpool/pgpool2/issues/104">A single DNS lookup failure will trigger backend failover</ulink> + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>不具合修正</title> + <itemizedlist> + <listitem> + <!-- + 2025-07-25 [75d905ff9] + --> + <para> + watchdog が不適切な NOTICE メッセージを出力する問題を修正しました。 (Tatsuo Ishii) + </para> + <para> + <function>read_ipc_socket_and_process()</function> は、IPCソケットへのコマンド書き込みのたびに、書き込みが成功した場合でも通知メッセージを出力していました。これを修正し、書き込みが失敗した場合にのみ通知メッセージを出力するようにしました。 + <varname>log_min_messages</varname> が notice 以上に設定されている場合にのみメッセージが表示されるため、このバグが発見されていませんでした。 + </para> + <para> + ディスカッション: <ulink url="https://github.com/pgpool/pgpool2/issues/121">pgpool IPC socket connection issue</ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-07-19 [d05de5c73] + --> + <!-- + 2025-07-19 [ed57af34e] + --> + <para> + スタートアップパケットを読んでいるときのメモリーリークを修正しました。(Tatsuo Ishii) + </para> + <para> + pool_push_pending_data でのリソースリークを修正しました。 + </para> + </listitem> + </itemizedlist> + + <itemizedlist> + <listitem> + <!-- + 2025-06-30 [bac455b2f] + --> + <para> + ビッグエンディアンマシン上の scram-sha-256 認証の不具合を修正しました。(Tatsuo Ishii) + </para> + <para> + <literal>scram-sha-256</literal> 認証を実行する際、ハッシュ関数 <function>pg_sha_256_final</function> が使用されます。 + これは <productname>PostgreSQL</productname> からインポートされたもので、プリプロセッサ定義 WORDS_BIGENDIAN を使用してホストマシンのエンディアンを判断します。 + WORDS_BIGENDIAN は configure 時に定義する必要がありますが、<function>pg_sha_256_final</function>(およびその他)が <productname>PostgreSQL</productname> からインポートされた際にこの部分が省略されていました。 + その結果、scram-sha-256 はリトルエンディアンマシンでのみ動作していました。 + configure.ac に AC_C_BIGENDIAN マクロを追加することでこの問題を修正しました。。 + </para> + <para> + この問題は Christoph Berg によって報告され、 pranavkaruvally によって分析されました。 + </para> + <para> + ディスカッション: <ulink url="https://github.com/pgpool/pgpool2/issues/106">4.6.1 fails on big-endian s390x: backend response with kind 'E' when expecting 'R'</ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-06-23 [2721c7b76] + --> + <para> + ソースコードのタイプミスを修正しました。 (Bo Peng) + </para> + </listitem> + + <listitem> + <!-- + 2025-06-14 [f88b1c18f] + --> + <para> + ハートビートデバイスの処理を修正しました。(Tatsuo Ishii) + </para> + <para> + <function>wd_create_hb_recv_socket()</function> と <function>wd_create_hb_send_socket()</function> を修正しました。 + setsockopt(SO_BINDTODEVICE) に struct ifreq を誤って渡すのではなく、NULL で終了するデバイス名文字列を渡すようにしました。 + </para> + <para> + ディスカッション: <ulink url="https://www.pgpool.net/pipermail/pgpool-hackers/2025-May/004603.html">[pgpool-hackers: 4602] heartbeat and SO_BINDTODEVICE</ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-06-14 [73bcbd96e] + --> + <para> + heartbeat receiver プロセスでのリソースリークを修正しました。 (Tatsuo Ishii) + </para> + </listitem> + + <listitem> + <!-- + 2025-06-09 [4305c42d6] + --> + <para> + ハートビートデバイスの処理を修正しました。(Tatsuo Ishii) + </para> + <para> + <filename>pgpool.conf</filename> の処理中に、<varname>heartbeat_device</varname> が誤って処理され、最初のデバイスが無視されていました。 + </para> + <para> + この問題は Bo Peng によって分析されました。 + </para> + </listitem> + + <listitem> + <!-- + 2025-06-05 [b249a118c] + --> + <para> + hearbeat receiver プロセスが動作しない問題を修正しました。 (Tatsuo Ishii) + </para> + <para> + ハートビートの IPv6 サポートはバージョン 4.6 で追加されましたが、heartbeat receiver プロセスが誤ってループバックアドレスのみにバインドされ、他のノードからの受信が妨げられていました。 + <function>getaddrinfo()</function> に AI_PASSIVE フラグを追加すると、すべてのネットワークインターフェースにバインドされるようになり、この問題は修正されました。 + </para> + <para> + この問題は Bo Peng によって分析されました。 + </para> + </listitem> + + <listitem> + <!-- + 2025-06-02 [06ba7dde4] + --> + <para> + <filename>pgpool.conf</filename>のコメントのタイプミスを修正しました。 (Tatsuo Ishii) + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>ドキュメント修正</title> + <itemizedlist> + <listitem> + <!-- + 2025-08-15 [a54f5d1ad] + --> + <para> + 「8.3. ネイティブレプリケーション/スナップショットアイソレーションモードの構築の例」のドキュメントを改善しました。(Taiki Koshino) + </para> + <para> + サンプルスクリプトのリンクと「事前設定」の説明を改善しました。 + </para> + </listitem> + + <listitem> + <!-- + 2025-08-04 [e2f24fec8] + --> + <para> + リロードによって反映されないパラメータのドキュメントを修正しました。 (Taiki Koshino) + </para> + <para> + <varname>authentication_timeout</varname> と <varname>memqcache_oiddir</varname> はリロードしても反映されません。 + ドキュメントが「このパラメータはサーバー起動時にのみ設定できます。」に変更されました。 + </para> + </listitem> + + <listitem> + <!-- + 2025-07-24 [bc5fa5e7e] + --> + <!-- + 2025-07-23 [1e8963554] + --> + <para> + watchdog リーダーの用語を統一しました。(Tatsuo Ishii) + </para> + <para> + 以前は「leader」「active」「coordinater」という用語が、watchdog のリーダーノードを指すために使用されていました。このコミットではこれらを「leader」に統一しました。 + advanced.sgml も修正しました。 + </para> + </listitem> + + <listitem> + <!-- + 2025-08-06 [31eee18d7] + --> + <!-- + 2025-07-16 [34b07c2d5] + --> + <para> + サンプルスクリプトを修正しました。(Taiki Koshino) + </para> + <para> + 「<ulink url="https://www.pgpool.net/docs/latest/ja/html/example-cluster.html">8.2. Pgpool-II + Watchdogの構築の例</ulink>」のサンプルスクリプトを修正しました。 + </para> + </listitem> + + <listitem> + <!-- + 2025-06-18 [f4ae9f39e] + 2025-06-18 [7a20dc419] + --> + <para> + ロードバランスの説明で論理レプリケーションモードと Slony モードが抜けている問題を修正しました(Tatsuo Ishii) + </para> + </listitem> + + <listitem> + <!-- + 2025-06-18 [9d2e4e692] + --> + <para> + <xref linkend="pcp-node-info">のドキュメントを改善しました。 (Bo Peng) + </para> + <para> + 「<varname>replication_state</varname>」と「<varname>replication_sync_state</varname>」を正しく表示するには、各 <varname>backend_application_nameX</varname> が <varname>primary_conninfo</varname> の <varname>application_name</varname> に指定された値と一致する必要があることを明確にしました。 + </para> + </listitem> + + <listitem> + <!-- + 2025-06-08 [59f9df005] + --> + <para> + カーネルの資源に関するセクションを追加しました。 (Tatsuo Ishii) + </para> + <para> + <productname>Pgpool-II</productname> は System V の共有メモリとセマフォを使用します。 + 要件についてはドキュメントを参照することをお勧めします。 + </para> + </listitem> + + <listitem> + <!-- + 2025-06-07 [40617fd90] + --> + <para> + configure の <option>--with-ldap</option> オプションの説明を追加しました。(Tatsuo Ishii) + </para> + <para> + これは LDAPサポートがv4.2で導入されたときに見落としていました。 + </para> + </listitem> + + <listitem> + <!-- + 2025-06-05 [9ee9eb164] + --> + <para> + $PGDATA をエスケープするよう、「8.2. <productname>Pgpool-II</productname> + Watchdogの構築の例」のコマンドを修正しました。(Bo Peng) + </para> + </listitem> + + <listitem> + <!-- + 2025-06-04 [ff60bf930] + --> + <para> + <productname>Pgpool-II</productname> でサポートされているプラットフォームを明確にしました。 (Tatsuo Ishii) + </para> + </listitem> + + <listitem> + <!-- + 2025-06-03 [cc4da5979] + --> + <para> + <xref linkend="guc-child-life-time"> のドキュメントを改善しました。 (Tatsuo Ishii) + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>回帰テスト修正</title> + <itemizedlist> + <listitem> + <!-- + 2025-06-08 [78e45decf] + --> + <para> + 029.cert_passphrase 回帰テストを安定化しました。 (Tatsuo Ishii) + </para> + <para> + <varname>ssl_passphrase_command</varname> が有効でない場合、エラーメッセージは通常「bad decrypt」ですが、「wrong tag」となる場合もありました。 + </para> + </listitem> + </itemizedlist> + </sect2> +</sect1> + <sect1 id="release-4-6-2"> <title>リリース 4.6.2</title> <note> diff --git a/doc.ja/src/sgml/release-4.7.sgml b/doc.ja/src/sgml/release-4.7.sgml new file mode 100644 index 000000000..9daa945a1 --- /dev/null +++ b/doc.ja/src/sgml/release-4.7.sgml @@ -0,0 +1,524 @@ +<sect1 id="release-4-7-0"> + <title>リリース 4.7.0</title> + <note> + <title>リリース日</title> + <simpara>2025-12-23</simpara> + </note> + + <sect2> + <title>概要</title> + <para> + このリリースでは、<productname>Pgpool-II</productname>に対して複数の機能強化を行いました。 + 主な改善点として、従来の<literal>Slony</literal>モードの廃止、セキュリティの強化、フロントエンド/バックエンドプロトコルの互換性向上、運用性の向上などが含まれます。 + </para> + + <para> + 主な機能の改良は以下の通りです。 + </para> + + <itemizedlist> + + <listitem> + <para> + <literal>Slony</literal>モードの廃止 + </para> + </listitem> + + <listitem> + <para> + <varname>logdir</varname>パラメータ名を<xref linkend="guc-work-dir">に変更 + </para> + </listitem> + + <listitem> + <para> + フロントエンド/バックエンドプロトコルバージョン3.2サポートの追加 + </para> + </listitem> + + <listitem> + <para> + watchdogとheartbeat receiverのセキュリティ強化 + </para> + </listitem> + + <listitem> + <para> + クライアント情報を表示するための<command>pcp_proc_info</command>および<command>show pool_pools</command>に新しいフィールドの追加と、<function>pgpool_adm_pcp_proc_info</function>拡張関数の追加 + </para> + </listitem> + + <listitem> + <para> + オンラインリカバリに使用するデータベースを指定できるrecovery_databaseパラメータの追加 + </para> + </listitem> + + <listitem> + <para> + PostgreSQL 18のSQLパーサの導入 + </para> + </listitem> + + </itemizedlist> + </sect2> + + <sect2 id="migration-4-7-0"> + <title>バージョン4.7への移行</title> + <itemizedlist> + + <listitem> + <!-- + 2025-10-29 [b402dbc09] + --> + <para> + <literal>Slony</literal>モードを廃止しました。(Tatsuo Ishii) + </para> + <para> + これまで、<productname>Pgpool-II</productname>は、<literal>slony</literal>モードを<xref linkend="guc-backend-clustering-mode">の1つとしてサポートしていました。 + <literal>Slony-I</literal> + (https://www.slony.info/)。最新の<literal>Slony-I</literal> は2022 年にリリースされましたが、ユーザーから <literal>Slony</literal>モードの廃止について何の報告もありませんでした。 + これは、<literal>Slony-I</literal>モードを積極的に利用するユーザーがいないことを示唆しています。 + そこで、<literal>Slony-I</literal>のサポートを中止することにしました。 + </para> + <para> + ディスカッション: <ulink url="https://www.pgpool.net/pipermail/pgpool-general/2025-May/009489.html">[pgpool-general: 9486] Retiring slony mode</ulink> + </para> + <para> + ディスカッション: <ulink url="https://www.postgresql.org/message-id/20250722.153130.1007226654125839063.ishii%40postgresql.org">Re: [pgpool-general: 9486] Retiring slony mode</ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-08-15 [579306dbc] + --> + <para> + <xref linkend="guc-log-pcp-processes">パラメータのデフォルト値を<literal>off</literal>に変更しました。(Tatsuo Ishii) + </para> + <para> + 以前の<varname>log_pcp_processes</varname>のデフォルトは<literal>on</literal>でしたが、管理者が<productname>Pgpool-II</productname>の状態を監視するためにpcpコマンドを頻繁に使用すると、過剰なログ行が生成される可能性がありました。 + また、このログは一種のデバッグメッセージであるため、デフォルト値を<literal>off</literal>に変更することをお勧めします。 + </para> + <para> + ディスカッション: <ulink url="https://www.postgresql.org/message-id/20250815.111100.2261166502134199972.ishii%40postgresql.org">Proposal: change log_pcp_processes default to off</ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-07-17 [3cc3d2d84] + 2025-07-25 [a16b63b8d] + --> + <para> + オンラインリカバリに使用するデータベースの設定が可能になりました。 (Bo Peng) + </para> + <para> + 新しい設定パラメータ<xref linkend="guc-recovery-database">が追加され、オンラインリカバリに使用するデータベースをユーザーが指定できるようになりました。 + 以前は、この値は<literal>template1</literal>としてハードコードされていました。現在のデフォルトは<literal>postgres</literal>に設定されています。 + </para> + <para> + 4.6より前のバージョンから移行するユーザーは、<xref linkend="guc-recovery-database">を<literal>template1</literal>に設定するか、<literal>postgres</literal>データベースにオンラインリカバリに必要な拡張機能を作成することで互換性を維持できます。 + </para> + </listitem> + + <listitem> + <!-- + 2025-10-14 [b286ce29a] + 2025-10-14 [25ad5e466] + --> + <para> + <varname>logdir</varname>を<xref linkend="guc-work-dir">に名称を変更しました。 (Taiki Koshino) + </para> + <para> + 以前は、<filename>pgpool_status</filename>およびロックファイルを保存するディレクトリは、<varname>logdir</varname>パラメータで指定されていました。 + しかし、<varname>logdir</varname>という名前は誤解を招く恐れがあったため、このパラメータは、わかりやすくするために<xref linkend="guc-work-dir">に変更されました。 + デフォルト値は<literal>/tmp</literal>で、以前のパラメータ<varname>logdir</varname>と同じです。 + </para> + <para> + 互換性のため、古い <varname>logdir</varname>パラメータは引き続きサポートされています。 + 古いパラメータ<varname>logdir</varname>が使用されると、<productname>Pgpool-II</productname>はその値を<xref linkend="guc-work-dir">に設定し、警告メッセージを表示します。 + </para> + </listitem> + + </itemizedlist> + </sect2> + + <sect2> + <title>変更点</title> + <itemizedlist> + + <listitem> + <!-- + 2025-10-03 [df2771637] + 2025-10-05 [020ee7084] + --> + <para> + PostgreSQL 18の新しいパーサーをインポートしました。 (Bo Peng) + </para> + <para> + PostgreSQL 18パーサーの主な変更点は以下の通りです。 + </para> + <itemizedlist> + <listitem> + <para> + 生成列を仮想列として使用可能 + </para> + </listitem> + <listitem> + <para> + DMLクエリのRETURNINGにOLD/NEWのサポートを追加 + </para> + </listitem> + <listitem> + <para> + 各種制約の追加(例:WITHOUT OVERLAPS、ENFORCED/NOT ENFORCED) + </para> + </listitem> + </itemizedlist> + </listitem> + + <listitem> + <!-- + 2025-08-22 [94b62a93c] + 2025-09-01 [f15c8a302] + 2025-09-01 [b9e7b4245] + --> + <para> + watchdogとheartbeat receiverが、設定されたアドレスのみを受け付けるように制限しました。(Bo Peng) + </para> + <para> + 以前は、watchdogプロセスとheartbeat receiverプロセスはどちらもすべてのインターフェースを受け付けていました。 + セキュリティ上の理由から、現在は<varname>hostname</varname>と<varname>heartbeat_hostname</varname>で指定されたアドレスのみを受け付けるようになりました。 + </para> + </listitem> + + <listitem> + <!-- + 2025-08-16 [dfffcddd6] + --> + <para> + watchdogのソースコードを整理しました。 (Tatsuo Ishii) + </para> + <para> + <itemizedlist> + <listitem> + <para> + <function>wd_is_upper_ok()</function>は定義されていないため、<filename>wd_utils.h</filename>から削除しました。 + </para> + </listitem> + <listitem> + <para> + <function>wd_get_ping_result()</function>と<function>wd_issue_ping_command()</function>を静的関数にしました。これは<filename>wd_ping.c</filename>でのみ使用されます。 + </para> + </listitem> + </itemizedlist> + </para> + </listitem> + + <listitem> + <!-- + 2025-08-13 [a85b848cc] + --> + <para> + ライフチェックがまだ開始されていない場合、警告を出力するようになりました。(Tatsuo Ishii) + </para> + <para> + 現在、ライフチェックは、ライフチェックの準備が整った場合にのみログを出力します。 + 管理者は、ライフチェックの準備が整うまでログファイルを監視し続ける必要があるため、不便です。このコミットにより、ライフチェックプロセスは、ライフチェックが開始されるまで定期的に追加の警告を出力するようになります。 + 警告の間隔は<xref linkend="guc-wd-interval"> × 10秒です。 + ただし、ライフチェック開始時の初回は、その時点ではライフチェックの準備が整っていない可能性が高いため、警告は出力されません。 + </para> + </listitem> + + <listitem> + <!-- + 2025-07-09 [766e73811] + 2025-07-15 [523b3d94d] + --> + <para> + フロントエンド/バックエンドプロトコル3.2のサポートを追加しました。(Tatsuo Ishii) + </para> + <itemizedlist> + <listitem> + <para> + NegotiateProtocolVersionメッセージを実装しました。 + </para> + <para> + フロントエンドがプロトコルバージョン3.2(PostgreSQL 18以降または互換クライアント)を要求し、バックエンドがまだ3.0(PostgreSQL 17以前)しかサポートしていない場合に、このメッセージを実装する必要があります。 + </para> + <para> + このコミットは、接続キャッシュが存在しない場合に、バックエンドからフロントエンドへメッセージを転送するようにメッセージを処理します。 + </para> + <para> + コネクションキャッシュが存在する場合、<productname>Pgpool-II</productname>はコネクションキャッシュの作成時に保存されたメッセージをフロントエンドに送信します。 + </para> + <para> + ディスカッション: <ulink url="https://www.postgresql.org/message-id/20250708.112133.1324153277751075866.ishii%40postgresql.org">Feature: implement NegotiateProtocolVersion message</ulink> + </para> + </listitem> + + <listitem> + <para> + プロトコルバージョン3.2にBackendKeyDataとクエリキャンセルメッセージを実装しました。 + </para> + <para> + PostgreSQL 18以降、フロントエンド/バックエンドプロトコルが3.2に変更されました。 + この変更により、BackendKeyDataとクエリキャンセルメッセージが修正され、可変長のキャンセルキーが使用できるようになりました。 + </para> + <para> + 3.2プロトコルを使用してPostgreSQLのフロントエンドとバックエンドに接続できるようになりました。 + </para> + <programlisting> +セッション例: +PGMAXPROTOCOLVERSION="3.2" psql -p 11000 test + </programlisting> + <para> + ディスカッション: <ulink url="https://www.postgresql.org/message-id/20250714.155710.1706961744888449986.ishii%40postgresql.org">Implement protocol 3.2 BackendKeyData and cancel request message</ulink> + </para> + </listitem> + </itemizedlist> + </listitem> + + <listitem> + <!-- + 2025-06-24 [706ca859c] + 2025-07-15 [0e80ac4e5] + 2025-07-15 [f4cfd6188] + --> + <para> + <xref linkend="pgpool-adm-pcp-proc-info">を追加しました。(Tatsuo Ishii) + </para> + <para> + <xref linkend="pgpool-adm-pcp-proc-info">を追加しました。 + また、<xref linkend="pcp-proc-info">と<command>show pool_pools</command>に、client_host、client_port、SQLステートメントという新しいフィールドが追加しました。 + これらの追加により、<productname>Pgpool-II</productname>のクライアント、<productname>Pgpool-II</productname>本体、そしてPostgreSQL間の関係を追跡できます。 + </para> + <para> + pcp_proc_infoを使用して最後に実行されたコマンド(ステートメント)を確認できるようになりました。 + 以前は、<productname>Pgpool-II</productname>のログを確認しない限り、これは不可能でした。 + </para> + <para> + lipcp.so のバージョンが 2.0.0 から 3.0.0 にアップグレードしました。 + </para> + </listitem> + + <listitem> + <!-- + 2025-06-14 [9fc568f00] + --> + <para> + ライフチェックのログを強化しました。 (Tatsuo Ishii) + </para> + <para> + 以前は、<xref linkend="guc-wd-lifecheck-method">が<literal>query</literal>の場合、<xref linkend="guc-log-line-prefix">に「%a」が指定されていると、死活監視はアプリケーション名なしでSQLを出力していました。 + ログの見栄えを良くするために、<varname>application_name</varname>に<literal>lifecheck_ping</literal>を追加しました。 + </para> + <para> + ディスカッション: <ulink url="https://www.pgpool.net/pipermail/pgpool-hackers/2025-June/004604.html">[pgpool-hackers: 4603] life check log is not nicea</ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-06-05 [1a68c6eb0] + --> + <para> + <function>random()</function>を<productname>pg_prng</productname>の<function>random</function>関数に置き換えました。 (Martijn van Duren, Tatsuo Ishii) + </para> + <para> + 以前は、負荷分散ノードの選択に<function>random()</function>を使用していました。 + しかし、<productname>PostgreSQL</productname>にはより優れた乱数生成器<filename>pg_prng.c</filename>があります。 + このファイルをインポートするように変更し、<function>pg_prng_double()</function>を使用して[0.0, 1.0]の範囲の乱数を生成します。 + シードは<function>pg_strong_random()</function>を使用して生成されます。 + </para> + <para> + ディスカッション: <ulink url="https://www.pgpool.net/pipermail/pgpool-hackers/2025-May/004589.html">[pgpool-hackers: 4588] Shuffle random functions and use better random numbers</ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-06-03 [cea80281d] + 2025-06-04 [e058c9334] + --> + <para> + watchdog受信ソケットのバインドを再試行するようにしました。(Tatsuo Ishii) + </para> + <para> + watchdog受信ソケットのバインドに失敗すると、028.watchdog_enable_consensus_with_half_votesがタイムアウトすることがありました。 + バインドを再試行することでこの問題を軽減するようになりました。 + 現在、再試行は最大5回まで実行され、各再試行ごとに1秒間のスリープが行われます。 + </para> + </listitem> + + <listitem> + <!-- + 2025-05-28 [ffd3a5224] + --> + <para> + PostgreSQLから<function>likely/unlikely()</function>を移植しました。(Tatsuo Ishii) + </para> + <para> + <function>likely/unlikely()</function>は正しく使用すれことでパフォーマンス向上に役立つだけでなく、コード内でマクロが時折使用されるため、<productname>PostgreSQL</productname>から<productname>Pgpool-II</productname>へのコードの移植が容易になります。 + </para> + <para> + ディスカッション: <ulink url="https://www.pgpool.net/pipermail/pgpool-hackers/2025-May/004600.html">[pgpool-hackers: 4599] Porting likely/unlikely</ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-05-20 [7abdd48ec] + 2025-05-20 [e14feea1d] + --> + <para> + <function>PostmasterRandmon()</function>を<function>pg_strong_random()</function>に置き換えました。(Tatsuo Ishii) + </para> + <para> + <function>PostmasterRandmon()</function>はかなり以前(2016年)に<productname>PostgreSQL</productname>からインポートされました。 + 同年、<productname>PostgreSQL</productname>は<function>PostmasterRandmon()</function>を<function>pg_strong_random()</function>(src/port/pg_strong_random.c)に置き換えているためこちらに準拠しました。 + </para> + <para> + ディスカッション: <ulink url="https://www.pgpool.net/pipermail/pgpool-hackers/2025-May/004589.html">[pgpool-hackers: 4588] Shuffle random functions and use better random numbers</ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-05-08 [5f7d06d87] + --> + <para> + <filename>.pcppass</filename>ファイルからの読み取りに失敗した場合、パスワードの入力を求めるプロンプトにフォールバックするようになりました。(Bo Peng) + </para> + <para> + <filename>.pcppass</filename>ファイルからのパスワードの読み取りに失敗した場合、<productname>PostgreSQL</productname>が<filename>.pgpass</filename>を処理するのと同様に、ユーザーに入力を求めるプロンプトにフォールバックします。 + </para> + <para> + 以下のメッセージも変更され、<option>-d</option> オプションを必要とせずに表示されます。 + <programlisting> +WARNING: password file \"%s\" is not a plain file +WARNING: password file \"%s\" has group or world access; permissions should be u=rw (0600) or less + </programlisting> + </para> + <para> + ディスカッション: <ulink url="https://www.pgpool.net/pipermail/pgpool-hackers/2025-May/004590.html">[pgpool-hackers: 4589] If reading password from .pcppass file fails, try to read it from prompt.</ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-06-14 [bbe93d86b] + --> + <para> + <productname>Pgpool-II</productname>の起動時に不適切なログメッセージを削除またはダウングレードするようになりました。(Tatsuo Ishii) + </para> + </listitem> + + <listitem> + <!-- + 2025-05-02 [5c41d5338] + --> + <para> + 設定ファイルにメジャーバージョン情報を追加しました。(Bo Peng) + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>ドキュメント修正</title> + <itemizedlist> + <listitem> + <!-- + 2025-07-15 [2a236be3e] + --> + <para> + 文字列として扱われていた列挙型パラメータに関するドキュメントを修正しました。(Taiki Koshino) + </para> + <para> + 6つのパラメータのドキュメントを修正しました: + <programlisting> +log_standby_delay +log_backend_messages +wd_lifecheck_method +memqcache_method +disable_load_balance_on_write +backend_clustering_mode + </programlisting> + </para> + </listitem> + + <listitem> + <!-- + 2025-05-09 [174772d6c] + --> + <para> + クエリキャッシュのドキュメントを改善しました。(Tatsuo Ishii) + </para> + <para> + <productname>Pgpool-II</productname>は、<literal>TIMESTAMP WITH TIMEZONE</literal>、<literal>TIME WITH TIMEZONE</literal> を返す関数を呼び出すクエリのキャッシュを拒否します。 + 同じ名前の関数が複数あり、そのうちの1つが<literal>TIMESTAMP WITH TIMEZONE</literal>、<literal>TIME WITH TIMEZONE</literal> を返す場合、<productname>Pgpool-II</productname> は、そのうちの1つがこれらのデータ型を返さなくてもキャッシュを拒否します。 + そのため、この問題に関するメモと回避策を追加しました。 + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>テストツール修正</title> + <itemizedlist> + <listitem> + <!-- + 2025-08-22 [534e04a0e] + 2025-08-22 [384c17eab] + --> + <para> + <xref linkend="watchdog-setup">でVIPを指定できるようになりました。(Tatsuo Ishii) + </para> + <para> + 新しいオプション<option>-vip [ip]</option>を使用して、<command>watchdog_setup</command>でVIPパラメータ(<varname>delegate_ip</varname>)を指定できるようになりました。 + ipが省略された場合は、<literal>127.0.0.1</literal>が想定されます。 + vip オプションが指定されていても、<productname>Pgpool-II</productname>は実際にはシステムにVIPを設定しません。 + <xref linkend="guc-if-up-cmd">、<xref linkend="guc-if-down-cmd">は、単にechoコマンドに設定され、ログを出力する以外は何も行いません。 + このオプションは、VIP処理に関する<productname>Pgpool-II</productname>の動作をトレースすることを目的としています。 + </para> + <para> + ディスカッション: <ulink url="https://www.postgresql.org/message-id/20250820.151646.1640218512808280876.ishii%40postgresql.org">Enhance watchdog_setup</ulink> + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>回帰テスト修正</title> + <itemizedlist> + <listitem> + <!-- + 2025-06-25 [04e09df17] + 2025-06-27 [b76c6876d] + --> + <para> + 038.pcp_commandsの回帰テストを修正しました。(Tatsuo Ishii) + </para> + <para> + 以前はテスト結果にローカルホストのIPが表示されていました。 + IPはIPv4またはIPv6のどちらでも構いませんが、テストスクリプトではこれを考慮していませんでした。 + これを修正するため、<filename>test.sh</filename>はIPv4とIPv6のIPを<literal>localhost</literal>に変換するようになりました。 + </para> + </listitem> + + <listitem> + <!-- + 2025-06-08 [e30bb2ead] + --> + <para> + 029.cert_passphrase回帰テストを安定化しました。 (Tatsuo Ishii) + </para> + <para> + ssl_passphrase_commandが有効でない場合、エラーメッセージは通常「bad decrypt」ですが、「wrong tag」となる場合もあります。 + </para> + </listitem> + </itemizedlist> + </sect2> +</sect1> diff --git a/doc.ja/src/sgml/release.sgml b/doc.ja/src/sgml/release.sgml index 09de64779..c1b7fedbb 100644 --- a/doc.ja/src/sgml/release.sgml +++ b/doc.ja/src/sgml/release.sgml @@ -92,6 +92,7 @@ For new features, add links to the documentation sections. subsets can easily be copied into back branches. --> + &release-4.7; &release-4.6; &release-4.5; &release-4.4; diff --git a/doc.ja/src/sgml/restrictions.sgml b/doc.ja/src/sgml/restrictions.sgml index 862dc7390..535b60c06 100644 --- a/doc.ja/src/sgml/restrictions.sgml +++ b/doc.ja/src/sgml/restrictions.sgml @@ -182,7 +182,7 @@ In other mode, including Slony mode, large objects are not supported. --> - Slonyモードも含め、その他のモードではラージオブジェクトはサポートされていません。 + その他のモードではラージオブジェクトはサポートされていません。 </para> </listitem> </varlistentry> diff --git a/doc.ja/src/sgml/runtime.sgml b/doc.ja/src/sgml/runtime.sgml index 7bc450b4e..2931dacc9 100644 --- a/doc.ja/src/sgml/runtime.sgml +++ b/doc.ja/src/sgml/runtime.sgml @@ -240,10 +240,6 @@ <entry><literal>logical_replication</literal> </entry> </row> <row> - <entry>slonyモード</entry> - <entry><literal>slony</literal></entry> - </row> - <row> <entry>スナップショットアイソレーションモード</entry> <entry><literal>snapshot_isolation</literal></entry> </row> @@ -313,7 +309,7 @@ </indexterm> <para> - <productname>Pgpool-II</>にはストリーミングレプリケーションモード、ロジカルレプリケーションモード、メインレプリカモード(Slonyモード)、ネイティブレプリケーションモード、スナップショットアイソレーションモード、rawモードの6つの<link linkend="guc-backend-clustering-mode">クラスタリングモード</link>があります。 + <productname>Pgpool-II</>にはストリーミングレプリケーションモード、ロジカルレプリケーションモード、ネイティブレプリケーションモード、スナップショットアイソレーションモード、rawモードの6つの<link linkend="guc-backend-clustering-mode">クラスタリングモード</link>があります。 いずれのモードにおいても、<productname>Pgpool-II</>はコネクションプーリング、自動フェイルオーバの機能を提供します。 ストリーミングレプリケーションモード、ネイティブレプリケーションモード、スナップショットアイソレーションモードでは、更新処理を受け付けながらデータベースノードの同期を取り直すオンラインリカバリが利用可能です。 オンラインリカバリの詳細については<xref linkend="runtime-online-recovery">を参照してください。 @@ -380,26 +376,6 @@ default_transaction_isolation = 'repeatable read' <para> <!-- - The <firstterm>native replication mode</firstterm> mode (slony mode) - can be used with <productname>PostgreSQL</> servers - operating <productname>Slony</>. In this - mode, <productname>Slony</>/<productname>PostgreSQL</> is - responsible for synchronizing - databases. Since <productname>Slony-I</> is being obsoleted by - streaming replication, we do not recommend to use this mode - unless you have specific reason to - use <productname>Slony</>. Load balancing is possible in the - mode. - --> - <firstterm>メインレプリカモード</firstterm>(slonyモード)は<productname>Slony-I</>を使用する<productname>PostgreSQL</>サーバと一緒に使うことができます。 - このモードでは、<productname>Slony</>/<productname>PostgreSQL</>がデータベースを同期する責任を持ちます。 - <productname>Slony</>はストリーミングレプリケーションの登場により廃れつつあるため、<productname>Slony</>を使う特別な理由が無い限りこのモードの使用を推奨しません。 - このモードでは負荷分散が可能です。 - </para> - - - <para> - <!-- In the raw mode, <productname>Pgpool-II</> does not care about the database synchronization. It's user's responsibility to make the whole system does a meaningful thing. Load balancing diff --git a/doc.ja/src/sgml/version.sgml b/doc.ja/src/sgml/version.sgml index a2ce83556..001c98a34 100644 --- a/doc.ja/src/sgml/version.sgml +++ b/doc.ja/src/sgml/version.sgml @@ -1 +1 @@ -<!ENTITY version "4.7devel"> +<!ENTITY version "4.8devel"> diff --git a/doc.ja/src/sgml/watchdog.sgml b/doc.ja/src/sgml/watchdog.sgml index b4eff8db6..1f314020e 100644 --- a/doc.ja/src/sgml/watchdog.sgml +++ b/doc.ja/src/sgml/watchdog.sgml @@ -407,8 +407,8 @@ Default is <literal>''</literal>(empty): which means virtual IP will never be brought up. --> - (アプリケーションサーバなど)クライアントサーバから接続される<productname>Pgpool-II</productname>の仮想IP(VIP) アドレスを指定します。 - <productname>Pgpool-II</productname>がスタンバイからアクティブに切り替わった時、<productname>Pgpool-II</productname>はこのVIPを引き継ぎます。 + (アプリケーションサーバなど)クライアントサーバから接続される<productname>Pgpool-II</productname>の仮想IP(VIP)アドレスを指定します。 + <productname>Pgpool-II</productname>がスタンバイからリーダーに切り替わった時、<productname>Pgpool-II</productname>はこのVIPを引き継ぎます。 <emphasis>クォーラムが存在しなければVIPは立ち上がりません</emphasis>。 デフォルトは<literal>''</literal>(空文字)で、この場合仮想IPは決して立ち上がりません。 </para> @@ -669,7 +669,7 @@ Configuration about behavior when <productname>Pgpool-II</productname> escalates to active (virtual IP holder) --> - <productname>Pgpool-II</productname>がアクティブ(仮想IPを保持しているステータス)に昇格した時の振る舞いを指定します。 + <productname>Pgpool-II</productname>がリーダー(仮想IPを保持しているステータス)に昇格した時の振る舞いを指定します。 </para> <variablelist> @@ -690,8 +690,8 @@ when pgpool-II escalates to active. This prevents the new active <productname>Pgpool-II</productname> from using old query caches inconsistences to the old active. --> - このオプションがonの場合、pgpool-II がアクティブに昇格した時に、共有メモリ上のクエリキャッシュを全て削除します。 - これにより、新しいアクティブの<productname>Pgpool-II</productname>が旧アクティブと非整合な古いクエリキャッシュを使うことを防止します。 + このオプションがonの場合、pgpool-II がリーダーに昇格した時に、共有メモリ上のクエリキャッシュを全て削除します。 + これにより、新しいリーダーの<productname>Pgpool-II</productname>が旧リーダーと非整合な古いクエリキャッシュを使うことを防止します。 </para> <para> <!-- @@ -881,11 +881,11 @@ </para> <para> - <productname>Pgpool-II </productname><emphasis>V4.1</emphasis>以後では、プライマリノードのフェイルオーバに関してwatchdogのリーダノードが合意形成に失敗し、その結果プライマリバックエンドが隔離状態になった場合、そのリーダノードはリーダ/コーディネータの役割を辞退し、次のリーダの選挙の際にwd_priorityを引き下げることにより、クラスタが新しいリーダを選ぶように仕向けます。 + <productname>Pgpool-II </productname><emphasis>V4.1</emphasis>以後では、プライマリノードのフェイルオーバに関してwatchdogのリーダーノードが合意形成に失敗し、その結果プライマリバックエンドが隔離状態になった場合、そのリーダーノードはリーダーの役割を辞退し、次のリーダーの選挙の際にwd_priorityを引き下げることにより、クラスタが新しいリーダーを選ぶように仕向けます。 <note> <para> - スタンバイバックエンドの障害時にリーダノードが合意形成に失敗した場合は、特にアクションは起こしません。 - watchdogリーダが管理する隔離されたスタンバイバックエンドは新しいリーダの選挙を引き起こしません。 + スタンバイバックエンドの障害時にリーダーノードが合意形成に失敗した場合は、特にアクションは起こしません。 + watchdogリーダが管理する隔離されたスタンバイバックエンドは新しいリーダーの選挙を引き起こしません。 </para> </note> </para> @@ -1105,7 +1105,7 @@ このパラメータがオンのときは、split-brainが発生するリスクがあることに注意してください。 たとえば、ノードA, B, C, Dからなる4ノードのクラスタでは、(A, B)と(C, D)の分断された2つのネットワークになる可能性があります。 (A, B)と(C, D)にとっては、それぞれ生きた2つのノードが存在するので、クォーラムは依然として存在します。 - 各々のグループはそれぞれのリーダwatchdogを選び、これはすなわちsplit-brainです。 + 各々のグループはそれぞれのリーダーwatchdogを選び、これはすなわちsplit-brainです。 </para> <para> デフォルト値はオフです。 diff --git a/doc/src/sgml/advanced.sgml b/doc/src/sgml/advanced.sgml index 74cf9f17a..7bfdd069a 100644 --- a/doc/src/sgml/advanced.sgml +++ b/doc/src/sgml/advanced.sgml @@ -129,7 +129,7 @@ </sect2> <sect2 id="tutorial-watchdog-changing-active"> - <title>Changing active/standby state when certain fault is detected</title> + <title>Changing leader/standby state when certain fault is detected</title> <indexterm zone="tutorial-watchdog-changing-active"> <primary>WATCHDOG</primary> @@ -137,9 +137,9 @@ <para> When a fault of <productname>Pgpool-II</productname> is detected, watchdog notifies the other watchdogs of it. - If this is the active <productname>Pgpool-II</productname>, - watchdogs decide the new active <productname>Pgpool-II</productname> - by voting and change active/standby state. + If this is the leader <productname>Pgpool-II</productname>, + watchdogs decide the new leader <productname>Pgpool-II</productname> + by voting and change leader/standby state. </para> </sect2> @@ -150,9 +150,9 @@ <primary>WATCHDOG</primary> </indexterm> <para> - When a standby <productname>Pgpool-II</productname> server promotes to active, - the new active server brings up virtual IP interface. Meanwhile, the previous - active server brings down the virtual IP interface. This enables the active + When a standby <productname>Pgpool-II</productname> server promotes to leader, + the new leader server brings up virtual IP interface. Meanwhile, the previous + leader server brings down the virtual IP interface. This enables the leader <productname>Pgpool-II</productname> to work using the same IP address even when servers are switched. </para> @@ -167,7 +167,7 @@ <para> When the broken server recovers or new server is attached, the watchdog process notifies this to the other watchdogs in the cluster along with the information of the new server, - and the watchdog process receives information on the active server and + and the watchdog process receives information on the leader server and other servers. Then, the attached server is registered as a standby. </para> </sect2> @@ -524,7 +524,7 @@ Thus clients of <productname>Pgpool-II</productname> cannot connect to <productname>Pgpool-II</productname> using the virtual IP any more. This is necessary to avoid split-brain, - that is, situations where there are multiple active + that is, situations where there are multiple leader <productname>Pgpool-II</productname>. </para> </sect2> @@ -561,9 +561,9 @@ <primary>WATCHDOG</primary> </indexterm> <para> - After the active <productname>Pgpool-II</productname> stops, + After the leader <productname>Pgpool-II</productname> stops, it will take a few seconds until the standby <productname>Pgpool-II</productname> - promote to new active, to make sure that the former virtual IP is + promote to new leader, to make sure that the former virtual IP is brought down before a down notification packet is sent to other <productname>Pgpool-II</productname>. </para> @@ -640,7 +640,7 @@ <listitem> <para> - Manages the Virtual-IP on the active/coordinator node and + Manages the Virtual-IP on the leader/coordinator node and allow the users to provide custom scripts for escalation and de-escalation. </para> diff --git a/doc/src/sgml/connection-pooling.sgml b/doc/src/sgml/connection-pooling.sgml index f6ebb773c..982ab1870 100644 --- a/doc/src/sgml/connection-pooling.sgml +++ b/doc/src/sgml/connection-pooling.sgml @@ -881,7 +881,7 @@ <listitem> <para> Setting to on, enable logging about normal PCP Process - fork and exit status. Default is on. + fork and exit status. Default is off. </para> <para> This parameter can be changed by reloading the <productname>Pgpool-II</> configurations. diff --git a/doc/src/sgml/connection-settings.sgml b/doc/src/sgml/connection-settings.sgml index 0f78b9931..97eafa0fb 100644 --- a/doc/src/sgml/connection-settings.sgml +++ b/doc/src/sgml/connection-settings.sgml @@ -1212,35 +1212,6 @@ backend_clustering_mode = logical_replication </sect2> - <sect2 id="runtime-config-slony-mode"> - <title>Slony mode</title> - - <para> - This mode is used to couple <productname>Pgpool-II</productname> - with <acronym>Slony-I</acronym>. Slony-I is responsible for doing - the actual data replication. To enable this mode, use slony for - <varname>backend_clustering_mode</varname>. - <programlisting> -backend_clustering_mode = slony - </programlisting> - In this mode you can have up to 127 replica servers. Also it is - possible not to have replica server at all. - </para> - - <para> - The drawback of this mode is, it is necessary to consider the - replication delay while distributing read queries. The visibility - consistency among nodes is not guaranteed either. Also certain - kind of objects such as DDL and large objects are not replicated. - </para> - - <para> - After streaming replication and logical replication are introduced, - there are few systems that employ Slony-I. If there's no - particular reason, it is not recommended to use this mode. - </para> - </sect2> - <sect2 id="guc-raw-mode" xreflabel="raw mode"> <title>Raw mode</title> <para> diff --git a/doc/src/sgml/example-cluster.sgml b/doc/src/sgml/example-cluster.sgml index 1f9835e0c..49d9e3d6b 100644 --- a/doc/src/sgml/example-cluster.sgml +++ b/doc/src/sgml/example-cluster.sgml @@ -7,8 +7,7 @@ servers to create a robust cluster system and avoid the single point of failure or split brain. </para> <para> - <emphasis><productname>PostgreSQL</productname> 17</emphasis> is used in this configuration example. - All scripts have been tested with <productname>PostgreSQL</productname> 10 and later. + <emphasis><productname>PostgreSQL</productname> 18</emphasis> is used in this configuration example. </para> <sect2 id="example-cluster-requirement"> <title>Requirements</title> @@ -20,7 +19,7 @@ <sect2 id="example-cluster-structure"> <title>Cluster System Configuration</title> <para> - We use three servers with <emphasis>Rocky Linux 9</emphasis> installed and + We use three servers with <emphasis>Rocky Linux 10</emphasis> installed and the hostnames of the three servers are <literal>server1</literal> <literal>server2</literal> and <literal>server3</literal> respectively. We install <productname>PostgreSQL</productname> and <productname>Pgpool-II</productname> on each server. @@ -82,7 +81,7 @@ <tbody> <row> <entry>PostgreSQL Version</entry> - <entry>17.0</entry> + <entry>18.0</entry> <entry>-</entry> </row> <row> @@ -92,7 +91,7 @@ </row> <row> <entry>$PGDATA</entry> - <entry>/var/lib/pgsql/17/data</entry> + <entry>/var/lib/pgsql/18/data</entry> <entry>-</entry> </row> <row> @@ -133,7 +132,7 @@ <tbody> <row> <entry>Pgpool-II Version</entry> - <entry>4.6.0</entry> + <entry>4.6.1</entry> <entry>-</entry> </row> <row> @@ -229,9 +228,9 @@ Install <productname>PostgreSQL</productname> from <productname>PostgreSQL</productname> YUM repository. </para> <programlisting> -[all servers]# dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-9-x86_64/pgdg-redhat-repo-latest.noarch.rpm +[all servers]# dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-10-x86_64/pgdg-redhat-repo-latest.noarch.rpm [all servers]# dnf -qy module disable postgresql -[all servers]# dnf install -y postgresql17-server +[all servers]# dnf install -y postgresql18-server </programlisting> <para> Since <productname>Pgpool-II</productname> related packages are also included in <productname>PostgreSQL</productname> YUM repository, @@ -249,6 +248,10 @@ ... exclude=pgpool* +[pgdg18] +... +exclude=pgpool* + [pgdg17] ... exclude=pgpool* @@ -268,10 +271,6 @@ exclude=pgpool* [pgdg13] ... exclude=pgpool* - -[pgdg12] -... -exclude=pgpool* </programlisting> <para> @@ -285,7 +284,7 @@ exclude=pgpool* </para> <programlisting> [all servers]# dnf install -y https://www.pgpool.net/yum/rpms/4.6/redhat/rhel-9-x86_64/pgpool-II-release-4.6-1.noarch.rpm -[all servers]# dnf install -y --enablerepo=crb pgpool-II-pg17-* +[all servers]# dnf install -y --enablerepo=crb pgpool-II-pg18-* </programlisting> </sect2> @@ -358,7 +357,7 @@ PubkeyAuthentication yes <sect3 id="example-cluster-before-starting-firewall"> <title>Setting up firewall</title> <para> - When connect to <productname>Pgpool-II</productname> and <productname>PostgreSQL</productname> servers, the target port must be accessible by enabling firewall management softwares. Following is an example for <systemitem>Rocky Linux 8/RHEL 8</systemitem>. + When connect to <productname>Pgpool-II</productname> and <productname>PostgreSQL</productname> servers, the target port must be accessible by enabling firewall management softwares. Following is an example for <systemitem>Rocky Linux 10/RHEL 10</systemitem>. </para> <programlisting> [all servers]# firewall-cmd --permanent --zone=public --add-service=postgresql @@ -375,21 +374,21 @@ PubkeyAuthentication yes <para> First, initialize the database cluster. - In <productname>PostgreSQL</productname> 17, the default directory - for creating the database cluster is <filename>/var/lib/pgsql/17/data</filename>, + In <productname>PostgreSQL</productname> 18, the default directory + for creating the database cluster is <filename>/var/lib/pgsql/18/data</filename>, and this is specified in the environment variable <varname>PGDATA</varname> in the <filename>~/.bash_profile</filename> of the <literal>postgres</literal> user. Modify it if you want to change the default path. </para> <para> Run <command>initdb</command> to initialize the database cluster. - Specify <ulink url="https://www.postgresql.org/docs/17/app-initdb.html">options</ulink> + Specify <ulink url="https://www.postgresql.org/docs/18/app-initdb.html">options</ulink> such as <literal>--encoding</literal> and <literal>--locale</literal> if you need to configure the database encoding and locale settings. </para> <programlisting> [root@server1 ~]# su - postgres -[postgres@server1 ~]$ /usr/pgsql-17/bin/initdb +[postgres@server1 ~]$ /usr/pgsql-18/bin/initdb </programlisting> <para> @@ -406,7 +405,7 @@ wal_log_hints = on Start <productname>PostgreSQL</productname> on <literal>server1</literal>. </para> <programlisting> -[postgres@server1 ~]$ /usr/pgsql-17/bin/pg_ctl start +[postgres@server1 ~]$ /usr/pgsql-18/bin/pg_ctl start </programlisting> </sect3> @@ -417,18 +416,43 @@ wal_log_hints = on <itemizedlist> <listitem> <para> - use <command>pg_basebackup</command> to backup the data directory of the primary from the standby. + use <productname>Pgpool-II</productname>'s online recovery feature + (<xref linkend="runtime-online-recovery">) to automatically + setup a standby server. </para> </listitem> <listitem> <para> - use <productname>Pgpool-II</productname>'s online recovery feature - (<xref linkend="runtime-online-recovery">) to automatically - setup a standby server. + use <command>pg_basebackup</command> to backup the data directory of the primary from the standby. </para> </listitem> </itemizedlist> </para> + + <note> + <para> + If you manually set up standby without using online recovery, please note the following: + <itemizedlist> + <listitem> + <para> + You must manually create the replication slots. + </para> + </listitem> + </itemizedlist> + <itemizedlist> + <listitem> + <para> + Do not specify the -R option when running pg_basebackup. + Write <varname>primary_conninfo</varname>, <varname>recovery_target_timeline</varname>, and <varname>primary_slot_name</varname> in <filename>$PGDATA/myrecovery.conf</filename>, not in <filename>postgresql.auto.conf</filename>, and add the following to <filename>postgresql.conf</filename>. + </para> + </listitem> + </itemizedlist> + <programlisting> +include_if_exists = 'myrecovery.conf' + </programlisting> + </para> + </note> + <para> In this example, we use <productname>Pgpool-II</productname>'s online recovery to setup the standby server @@ -751,19 +775,19 @@ health_check_max_retries = 3 backend_hostname0 = 'server1' backend_port0 = 5432 backend_weight0 = 1 -backend_data_directory0 = '/var/lib/pgsql/17/data' +backend_data_directory0 = '/var/lib/pgsql/18/data' backend_flag0 = 'ALLOW_TO_FAILOVER' backend_hostname1 = 'server2' backend_port1 = 5432 backend_weight1 = 1 -backend_data_directory1 = '/var/lib/pgsql/17/data' +backend_data_directory1 = '/var/lib/pgsql/18/data' backend_flag1 = 'ALLOW_TO_FAILOVER' backend_hostname2 = 'server3' backend_port2 = 5432 backend_weight2 = 1 -backend_data_directory2 = '/var/lib/pgsql/17/data' +backend_data_directory2 = '/var/lib/pgsql/18/data' backend_flag2 = 'ALLOW_TO_FAILOVER' </programlisting> <para> @@ -819,8 +843,8 @@ follow_primary_command = '/etc/pgpool-II/follow_primary.sh %d %h %p %D %m %H %M </para> </note> <para> - Sample scripts <ulink url="https://git.postgresql.org/gitweb/?p=pgpool2.git;a=blob_plain;f=src/sample/scripts/failover.sh.sample;hb=refs/heads/V4_6_STABLE">failover.sh</ulink> - and <ulink url="https://git.postgresql.org/gitweb/?p=pgpool2.git;a=blob_plain;f=src/sample/scripts/follow_primary.sh.sample;hb=refs/heads/V4_6_STABLE">follow_primary.sh</ulink> + Sample scripts <ulink url="https://raw.githubusercontent.com/pgpool/pgpool2/refs/heads/master/src/sample/scripts/failover.sh.sample">failover.sh</ulink> + and <ulink url="https://raw.githubusercontent.com/pgpool/pgpool2/refs/heads/master/src/sample/scripts/follow_primary.sh.sample">follow_primary.sh</ulink> are installed in <filename>/etc/pgpool-II/</filename>. Create failover scripts using these sample files. </para> <programlisting> @@ -835,12 +859,12 @@ follow_primary_command = '/etc/pgpool-II/follow_primary.sh %d %h %p %D %m %H %M <programlisting> [root@server1 ~]# vi /etc/pgpool-II/failover.sh ... -PGHOME=/usr/pgsql-17 +PGHOME=/usr/pgsql-18 ... [root@server1 ~]# vi /etc/pgpool-II/follow_primary.sh ... -PGHOME=/usr/pgsql-17 +PGHOME=/usr/pgsql-18 ... </programlisting> @@ -886,8 +910,8 @@ recovery_1st_stage_command = 'recovery_1st_stage' primary server (server1). </para> <para> - The sample scripts of online recovery <ulink url="https://git.postgresql.org/gitweb/?p=pgpool2.git;a=blob_plain;f=src/sample/scripts/recovery_1st_stage.sample;hb=refs/heads/V4_6_STABLE">recovery_1st_stage</ulink> - and <ulink url="https://git.postgresql.org/gitweb/?p=pgpool2.git;a=blob_plain;f=src/sample/scripts/pgpool_remote_start.sample;hb=refs/heads/V4_6_STABLE">pgpool_remote_start</ulink> + The sample scripts of online recovery <ulink url="https://raw.githubusercontent.com/pgpool/pgpool2/refs/heads/master/src/sample/scripts/pgpool_remote_start.sample">recovery_1st_stage</ulink> + and <ulink url="https://raw.githubusercontent.com/pgpool/pgpool2/refs/heads/master/src/sample/scripts/pgpool_remote_start.sample">pgpool_remote_start</ulink> are installed in <filename>/etc/pgpool-II/</filename>. Copy these files to the data directory of the primary server (server1). </para> <programlisting> @@ -898,14 +922,14 @@ recovery_1st_stage_command = 'recovery_1st_stage' Basically, it should work if you change <emphasis>PGHOME</emphasis> according to PostgreSQL installation directory. </para> <programlisting> -[root@server1 ~]# vi /var/lib/pgsql/17/data/recovery_1st_stage +[root@server1 ~]# vi /var/lib/pgsql/18/data/recovery_1st_stage ... -PGHOME=/usr/pgsql-17 +PGHOME=/usr/pgsql-18 ... -[root@server1 ~]# vi /var/lib/pgsql/17/data/pgpool_remote_start +[root@server1 ~]# vi /var/lib/pgsql/18/data/pgpool_remote_start ... -PGHOME=/usr/pgsql-17 +PGHOME=/usr/pgsql-18 ... </programlisting> @@ -1126,7 +1150,7 @@ wd_heartbeat_deadtime = 30 wd_escalation_command = '/etc/pgpool-II/escalation.sh' </programlisting> <para> - The sample script <ulink url="https://git.postgresql.org/gitweb/?p=pgpool2.git;a=blob_plain;f=src/sample/scripts/escalation.sh.sample;hb=refs/heads/V4_6_STABLE">escalation.sh</ulink> is installed in <filename>/etc/pgpool-II/</filename>. + The sample script <ulink url="https://raw.githubusercontent.com/pgpool/pgpool2/refs/heads/master/src/sample/scripts/escalation.sh.sample">escalation.sh</ulink> is installed in <filename>/etc/pgpool-II/</filename>. </para> <programlisting> [root@server1 ~]# cp -p /etc/pgpool-II/sample_scripts/escalation.sh.sample /etc/pgpool-II/escalation.sh @@ -1178,7 +1202,7 @@ CIDR_NETMASK=24 <programlisting> log_destination = 'stderr' logging_collector = on -log_directory = '/var/log/pgpool_log' +log_directory = '/var/log/pgpool' log_filename = 'pgpool-%a.log' log_truncate_on_rotation = on log_rotation_age = 1d @@ -1220,7 +1244,7 @@ log_rotation_age = 1d using the following command. </para> <programlisting> -[root@server1 ~]# su - postgres -c "/usr/pgsql-17/bin/pg_ctl start" +[root@server1 ~]# su - postgres -c "/usr/pgsql-18/bin/pg_ctl start" </programlisting> <para> Start <productname>Pgpool-II</productname> on <literal>server1</literal>, @@ -1377,7 +1401,7 @@ Password for user pgpool: automatically. </para> <programlisting> -[root@server1 ~]# su - postgres -c "/usr/pgsql-17/bin/pg_ctl -m immediate stop" +[root@server1 ~]# su - postgres -c "/usr/pgsql-18/bin/pg_ctl -m immediate stop" </programlisting> <para> After stopping <productname>PostgreSQL</productname> on diff --git a/doc/src/sgml/example-replication-si-mode.sgml b/doc/src/sgml/example-replication-si-mode.sgml index 1100a754e..993ff068a 100644 --- a/doc/src/sgml/example-replication-si-mode.sgml +++ b/doc/src/sgml/example-replication-si-mode.sgml @@ -16,8 +16,7 @@ the visibility consistency among nodes. </para> <para> - <productname>PostgreSQL</productname> 14 is used in this configuration example. - All scripts have been tested with <productname>PostgreSQL</productname> 10 and later. + <productname>PostgreSQL</productname> 18 is used in this configuration example. </para> <sect2 id="example-replication-mode-structure"> @@ -28,7 +27,7 @@ replication. </para> <para> - In this example we use 3 servers with CentOS 7.9 installed. + In this example we use 3 servers with Rocky Linux 10 installed. Let these servers be <literal>server1</literal>, <literal>server2</literal>, <literal>server3</literal>. We install <productname>PostgreSQL</productname> on all servers and @@ -84,7 +83,7 @@ <tbody> <row> <entry>PostgreSQL Version</entry> - <entry>14.0</entry> + <entry>18.0</entry> <entry>-</entry> </row> <row> @@ -94,7 +93,7 @@ </row> <row> <entry>$PGDATA</entry> - <entry>/var/lib/pgsql/14/data</entry> + <entry>/var/lib/pgsql/18/data</entry> <entry>-</entry> </row> <row> @@ -164,8 +163,8 @@ Install <productname>PostgreSQL</productname> from <productname>PostgreSQL</productname> YUM repository. </para> <programlisting> -[all servers]# yum install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm -[all servers]# yum install -y postgresql14-server +[all servers]# yum install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-10-x86_64/pgdg-redhat-repo-latest.noarch.rpm +[all servers]# yum install -y postgresql18-server </programlisting> <para> @@ -184,27 +183,29 @@ ... exclude=pgpool* -[pgdg14] +[pgdg18] ... exclude=pgpool* -[pgdg13] +[pgdg17] ... exclude=pgpool* -[pgdg12] +[pgdg16] ... exclude=pgpool* -[pgdg11] +[pgdg15] ... exclude=pgpool* -[pgdg10] +[pgdg14] ... exclude=pgpool* -[pgdg96] +[pgdg13] +... +exclude=pgpool* ... exclude=pgpool* </programlisting> @@ -212,8 +213,8 @@ exclude=pgpool* Install <productname>Pgpool-II</productname> using Pgpool-II YUM repository. </para> <programlisting> -[all servers]# yum install -y https://www.pgpool.net/yum/rpms/4.4/redhat/rhel-7-x86_64/pgpool-II-release-4.4-1.noarch.rpm -[all servers]# yum install -y pgpool-II-pg14-* +[all servers]# yum install -y https://www.pgpool.net/yum/rpms/4.6/redhat/rhel-10-x86_64/pgpool-II-release-4.6-1.noarch.rpm +[all servers]# yum install -y pgpool-II-pg18-* </programlisting> </sect2> @@ -223,16 +224,6 @@ exclude=pgpool* Before you start the configuration process, please check the following prerequisites. </para> - <sect3 id="example-replication-mode-postgres-password"> - <title>Setting password of postgres user</title> - <para> - Run the following command to set the password of <literal>postgres</literal> user on each server. - </para> - <programlisting> -[all servers]# passwd postgres - </programlisting> - </sect3> - <sect3 id="example-replication-mode-ssh"> <title>Configure passwordless SSH login</title> <para> @@ -245,17 +236,48 @@ exclude=pgpool* </para> <programlisting> [all servers]# su - postgres -[all servers]$ cd ~/.ssh -[all servers]$ ssh-keygen -t rsa -f id_rsa_pgpool -[all servers]$ ssh-copy-id -i id_rsa_pgpool.pub postgres@server1 -[all servers]$ ssh-copy-id -i id_rsa_pgpool.pub postgres@server2 -[all servers]$ ssh-copy-id -i id_rsa_pgpool.pub postgres@server3 +[all servers]$ mkdir ~/.ssh && chmod 700 ~/.ssh +[all servers]$ ssh-keygen -t rsa -f ~/.ssh/id_rsa_pgpool </programlisting> <para> - After setting SSH, use <command>ssh postgres@serverX -i ~/.ssh/id_rsa_pgpool</command> command to - make sure that you can log in without entering a password. Edit <filename>/etc/ssh/sshd_config</filename> - if necessary and restart sshd. + Then add the public key <filename>id_rsa_pgpool.pub</filename> to + <filename>/var/lib/pgsql/.ssh/authorized_keys</filename> file + on each server. </para> + <para> + After setting SSH, make sure that you can run + <command>ssh postgres@serverX -i ~/.ssh/id_rsa_pgpool</command> command + as <literal>postgres</literal> user to login to each server + without entering a password. + </para> + + <note> + <para> + If you failed to login using SSH public key authentication, please check the following: + <itemizedlist> + <listitem> + <para> + Ensure the public key authentication option <literal>PubkeyAuthentication</literal> are allowed in <filename>/etc/ssh/sshd_config</filename>: + </para> + </listitem> + </itemizedlist> + <programlisting> +PubkeyAuthentication yes + </programlisting> + <itemizedlist> + <listitem> + <para> + If SELinux is enabled, SSH public key authentication (passwordless SSH) may fail. + You need to run the following command on all servers. + </para> + </listitem> + </itemizedlist> + <programlisting> +[all servers]# su - postgres +[all servers]$ restorecon -Rv ~/.ssh + </programlisting> + </para> + </note> </sect3> <sect3 id="example-replication-mode-pgpass"> @@ -268,21 +290,21 @@ exclude=pgpool* </para> <programlisting> [all servers]# su - postgres -[all servers]$ vi /var/lib/pgsql/.pgpass +[all servers]$ vi ~/.pgpass server1:5432:replication:repl:<repl user password> server2:5432:replication:repl:<repl user password> server3:5432:replication:repl:<repl user password> server1:5432:postgres:postgres:<postgres user password> server2:5432:postgres:postgres:<postgres user password> server3:5432:postgres:postgres:<postgres user password> -[all servers]$ chmod 600 /var/lib/pgsql/.pgpass +[all servers]$ chmod 600 ~/.pgpass </programlisting> </sect3> <sect3 id="example-replication-mode-firewall"> <title>Configure firewall</title> <para> - When connect to <productname>Pgpool-II</productname> and <productname>PostgreSQL</productname> servers, the target port must be accessible by enabling firewall management softwares. Following is an example for <systemitem>CentOS/RHEL7</systemitem>. + When connect to <productname>Pgpool-II</productname> and <productname>PostgreSQL</productname> servers, the target port must be accessible by enabling firewall management softwares. Following is an example for <systemitem>Rocky Linux 10</systemitem>. </para> <programlisting> [all servers]# firewall-cmd --permanent --zone=public --add-service=postgresql @@ -322,7 +344,7 @@ server3:5432:postgres:postgres:<postgres user password> </para> <programlisting> [server1]# su - postgres -[server1]$ /usr/pgsql-14/bin/initdb -E UTF8 --no-locale +[server1]$ /usr/pgsql-18/bin/initdb -E UTF8 --no-locale </programlisting> <para> Then edit <filename>$PGDATA/postgresql.conf</filename> on server1. @@ -349,7 +371,7 @@ host replication all samenet scram-sha-256 Run the following command to start PostgreSQL server. </para> <programlisting> -[server1]$ /usr/pgsql-14/bin/pg_ctl start +[server1]$ /usr/pgsql-18/bin/pg_ctl start </programlisting> <para> @@ -492,19 +514,19 @@ health_check_max_retries = 3 backend_hostname0 = 'server1' backend_port0 = 5432 backend_weight0 = 1 -backend_data_directory0 = '/var/lib/pgsql/14/data' +backend_data_directory0 = '/var/lib/pgsql/18/data' backend_flag0 = 'ALLOW_TO_FAILOVER' backend_hostname1 = 'server2' backend_port1 = 5432 backend_weight1 = 1 -backend_data_directory1 = '/var/lib/pgsql/14/data' +backend_data_directory1 = '/var/lib/pgsql/18/data' backend_flag1 = 'ALLOW_TO_FAILOVER' backend_hostname2 = 'server3' backend_port2 = 5432 backend_weight2 = 1 -backend_data_directory2 = '/var/lib/pgsql/14/data' +backend_data_directory2 = '/var/lib/pgsql/18/data' backend_flag2 = 'ALLOW_TO_FAILOVER' </programlisting> </sect3> @@ -525,36 +547,36 @@ recovery_1st_stage_command = 'recovery_1st_stage' recovery_2nd_stage_command = 'recovery_2nd_stage' </programlisting> The sample scripts - <ulink url="https://git.postgresql.org/gitweb/?p=pgpool2.git;a=blob_plain;f=src/sample/scripts/replication_mode_recovery_1st_stage.sample;hb=refs/heads/V4_4_STABLE">replication_mode_recovery_1st_stage.sample</ulink>, - <ulink url="https://git.postgresql.org/gitweb/?p=pgpool2.git;a=blob_plain;f=src/sample/scripts/replication_mode_recovery_2nd_stage.sample;hb=refs/heads/V4_4_STABLE">replication_mode_recovery_2nd_stage.sample</ulink> + <ulink url="https://raw.githubusercontent.com/pgpool/pgpool2/refs/heads/master/src/sample/scripts/replication_mode_recovery_1st_stage.sample">replication_mode_recovery_1st_stage.sample</ulink>, + <ulink url="https://raw.githubusercontent.com/pgpool/pgpool2/refs/heads/master/src/sample/scripts/replication_mode_recovery_2nd_stage.sample">replication_mode_recovery_2nd_stage.sample</ulink> and - <ulink url="https://git.postgresql.org/gitweb/?p=pgpool2.git;a=blob_plain;f=src/sample/scripts/pgpool_remote_start.sample;hb=refs/heads/V4_4_STABLE">pgpool_remote_start.sample</ulink> + <ulink url="https://raw.githubusercontent.com/pgpool/pgpool2/refs/heads/master/src/sample/scripts/pgpool_remote_start.sample">pgpool_remote_start.sample</ulink> are installed in <filename>/etc/pgpool-II/</filename>. Create the scripts used by online recovery command from sample scripts and copy these files to the database cluster directory. </para> <programlisting> -[server1]# cp -p /etc/pgpool-II/sample_scripts/replication_mode_recovery_1st_stage.sample /var/lib/pgsql/14/data/recovery_1st_stage -[server1]# cp -p /etc/pgpool-II/sample_scripts/replication_mode_recovery_2nd_stage.sample /var/lib/pgsql/14/data/recovery_2nd_stage -[server1]# cp -p /etc/pgpool-II/sample_scripts/pgpool_remote_start.sample /var/lib/pgsql/14/data/pgpool_remote_start -[server1]# chown postgres:postgres /var/lib/pgsql/14/data/{recovery_1st_stage,recovery_2nd_stage,pgpool_remote_start} +[server1]# cp -p /etc/pgpool-II/sample_scripts/replication_mode_recovery_1st_stage.sample /var/lib/pgsql/18/data/recovery_1st_stage +[server1]# cp -p /etc/pgpool-II/sample_scripts/replication_mode_recovery_2nd_stage.sample /var/lib/pgsql/18/data/recovery_2nd_stage +[server1]# cp -p /etc/pgpool-II/sample_scripts/pgpool_remote_start.sample /var/lib/pgsql/18/data/pgpool_remote_start +[server1]# chown postgres:postgres /var/lib/pgsql/18/data/{recovery_1st_stage,recovery_2nd_stage,pgpool_remote_start} </programlisting> <para> Basically, it should work if you change <emphasis>PGHOME</emphasis> according to PostgreSQL installation directory. </para> <programlisting> -[server1]# vi /var/lib/pgsql/14/data/recovery_1st_stage +[server1]# vi /var/lib/pgsql/18/data/recovery_1st_stage ... -PGHOME=/usr/pgsql-14 +PGHOME=/usr/pgsql-18 ... -[server1]# vi /var/lib/pgsql/14/data/recovery_2nd_stage +[server1]# vi /var/lib/pgsql/18/data/recovery_2nd_stage ... -PGHOME=/usr/pgsql-14 +PGHOME=/usr/pgsql-18 ... -[server1]# vi /var/lib/pgsql/14/data/pgpool_remote_start +[server1]# vi /var/lib/pgsql/18/data/pgpool_remote_start ... -PGHOME=/usr/pgsql-14 +PGHOME=/usr/pgsql-18 ... </programlisting> @@ -665,7 +687,7 @@ postgres:AESHs/pWL5rtXy2IwuzroHfqg== <programlisting> log_destination = 'stderr' logging_collector = on -log_directory = '/var/log/pgpool_log' +log_directory = '/var/log/pgpool' log_filename = 'pgpool-%Y-%m-%d_%H%M%S.log' log_truncate_on_rotation = on log_rotation_age = 1d @@ -763,15 +785,15 @@ Password for user pgpool: Next, let's verify the replication functionality using a benchmark tool pgbench. </para> <programlisting> -[server1]# /usr/pgsql-14/bin/createdb test -U postgres -p 9999 -[server1]# /usr/pgsql-14/bin/pgbench -h server1 -U postgres -i -p 9999 test +[server1]# /usr/pgsql-18/bin/createdb test -U postgres -p 9999 +[server1]# /usr/pgsql-18/bin/pgbench -h server1 -U postgres -i -p 9999 test </programlisting> <para> To check if the replication works correctly, directly connect to each PostgreSQL server to see if they return identical results. </para> <programlisting> -[server1]# /usr/pgsql-14/bin/psql -h server1 -U postgres -p 5432 test +[server1]# /usr/pgsql-18/bin/psql -h server1 -U postgres -p 5432 test test=# \d List of relations Schema | Name | Type | Owner @@ -782,7 +804,7 @@ test=# \d public | pgbench_tellers | table | postgres (4 rows) -[server1]# /usr/pgsql-14/bin/psql -h server2 -U postgres -p 5432 test +[server1]# /usr/pgsql-18/bin/psql -h server2 -U postgres -p 5432 test test=# \d List of relations Schema | Name | Type | Owner @@ -793,7 +815,7 @@ test=# \d public | pgbench_tellers | table | postgres (4 rows) -[server1]# /usr/pgsql-14/bin/psql -h server3 -U postgres -p 5432 test +[server1]# /usr/pgsql-18/bin/psql -h server3 -U postgres -p 5432 test test=# \d List of relations Schema | Name | Type | Owner @@ -811,27 +833,27 @@ test=# \d Next, let's run pgbench for a while and check to results. </para> <programlisting> -[server1]# /usr/pgsql-14/bin/pgbench -h server1 -U postgres -p 9999 -T 10 test +[server1]# /usr/pgsql-18/bin/pgbench -h server1 -U postgres -p 9999 -T 10 test </programlisting> <para> All PostgreSQL servers return identical results. </para> <programlisting> -[server1]# /usr/pgsql-14/bin/psql -h server1 -U postgres -p 5432 test -c "SELECT sum(abalance) FROM pgbench_accounts" +[server1]# /usr/pgsql-18/bin/psql -h server1 -U postgres -p 5432 test -c "SELECT sum(abalance) FROM pgbench_accounts" Password for user postgres: sum -------- -99710 (1 row) -[server1]# /usr/pgsql-14/bin/psql -h server2 -U postgres -p 5432 test -c "SELECT sum(abalance) FROM pgbench_accounts" +[server1]# /usr/pgsql-18/bin/psql -h server2 -U postgres -p 5432 test -c "SELECT sum(abalance) FROM pgbench_accounts" Password for user postgres: sum -------- -99710 (1 row) -[server1]# /usr/pgsql-14/bin/psql -h server3 -U postgres -p 5432 test -c "SELECT sum(abalance) FROM pgbench_accounts" +[server1]# /usr/pgsql-18/bin/psql -h server3 -U postgres -p 5432 test -c "SELECT sum(abalance) FROM pgbench_accounts" Password for user postgres: sum -------- @@ -847,7 +869,7 @@ Password for user postgres: and verify the switchover of the main node. </para> <programlisting> -[server1]# su - postgres -c "/usr/pgsql-14/bin/pg_ctl -m i stop" +[server1]# su - postgres -c "/usr/pgsql-18/bin/pg_ctl -m i stop" </programlisting> <para> After stopping <productname>PostgreSQL</productname> on <literal>server1</literal>, diff --git a/doc/src/sgml/filelist.sgml b/doc/src/sgml/filelist.sgml index 292239b58..2247e15d0 100644 --- a/doc/src/sgml/filelist.sgml +++ b/doc/src/sgml/filelist.sgml @@ -53,6 +53,7 @@ <!-- appendixes --> <!ENTITY release SYSTEM "release.sgml"> +<!ENTITY release-4.7 SYSTEM "release-4.7.sgml"> <!ENTITY release-4.6 SYSTEM "release-4.6.sgml"> <!ENTITY release-4.5 SYSTEM "release-4.5.sgml"> <!ENTITY release-4.4 SYSTEM "release-4.4.sgml"> diff --git a/doc/src/sgml/installation-rpm.sgml b/doc/src/sgml/installation-rpm.sgml index 65002d089..1a88ea4d1 100644 --- a/doc/src/sgml/installation-rpm.sgml +++ b/doc/src/sgml/installation-rpm.sgml @@ -7,7 +7,7 @@ If you are going to install from the source code, please check <xref linkend="install-source">. </para> <para> - <productname>Pgpool-II</productname> community provides RPM packages for RHEL9/8/7 + <productname>Pgpool-II</productname> community provides RPM packages for RHEL10/9/8 and the operating system which is compatible with RHEL. You can download package files from <ulink url="https://www.pgpool.net/yum/">official Pgpool-II repository</ulink>. @@ -39,11 +39,11 @@ </row> <row> <entry>pgpool-II-pgXX-debugsource</entry> - <entry>Only for RHEL8/9. Debug symbols for debugging</entry> + <entry>Only for RHEL10/9/8. Debug symbols for debugging</entry> </row> <row> <entry>pgpool-II-pgXX-extensions-debuginfo</entry> - <entry>Only for RHEL8/9. Debug symbols for debugging</entry> + <entry>Only for RHEL10/9/8. Debug symbols for debugging</entry> </row> <row> <entry>pgpool-II-pgXX-devel</entry> @@ -60,7 +60,7 @@ <productname>Pgpool-II</productname> provides separate packages for each PostgreSQL version. "XX" in the above package is a two-digit number representing the version of PostgreSQL. Choose <productname>Pgpool-II</productname> RPM corresponding to your PostgreSQL version. - (For example, if you are using PostgreSQL 17, you need to install <filename>pgpool-II-pg17</filename>) + (For example, if you are using PostgreSQL 18, you need to install <filename>pgpool-II-pg18</filename>) </para> <sect2 id="before-installing"> @@ -86,6 +86,10 @@ vi /etc/yum.repos.d/pgdg-redhat-all.repo ... exclude=pgpool* +[pgdg18] +... +exclude=pgpool* + [pgdg17] ... exclude=pgpool* @@ -105,14 +109,6 @@ exclude=pgpool* [pgdg13] ... exclude=pgpool* - -[pgdg12] -... -exclude=pgpool* - -[pgdg11] -... -exclude=pgpool* </programlisting> </sect2> @@ -124,25 +120,25 @@ exclude=pgpool* </para> <para> - The following commands assume that you are using Pgpool-II 4.6.x for PostgreSQL 17 on RHEL9. + The following commands assume that you are using Pgpool-II 4.6.x for PostgreSQL 18 on RHEL10. If you are using other versions, replace "pgXX" with your PostgreSQL version. </para> <para> First, install the repository corresponding to your <productname>Pgpool-II</productname> version and distribution. - For REHL7/8, see <ulink url="https://www.pgpool.net/mediawiki/index.php/Yum_Repository">here</ulink>. + For REHL9/8, see <ulink url="https://www.pgpool.net/mediawiki/index.php/Yum_Repository">here</ulink>. </para> <programlisting> -dnf install https://www.pgpool.net/yum/rpms/4.6/redhat/rhel-9-x86_64/pgpool-II-release-4.6-1.noarch.rpm +dnf install https://www.pgpool.net/yum/rpms/4.6/redhat/rhel-10-x86_64/pgpool-II-release-4.6-1.noarch.rpm </programlisting> <para> Then, install <productname>Pgpool-II</productname>. </para> <programlisting> -dnf install pgpool-II-pg17 +dnf install pgpool-II-pg18 </programlisting> <para> - To use online recovery feature, install <filename>pgpool-II-pg17-extensions</filename> + To use online recovery feature, install <filename>pgpool-II-pg18-extensions</filename> on <emphasis>all PostgreSQL servers</emphasis>. Because <filename>pgpool-II-pgXX-extensions</filename> depends on <filename>pgpool-II-pgXX</filename> package, @@ -160,14 +156,14 @@ dnf install pgpool-II-pg17 </para> </note> <programlisting> -dnf install pgpool-II-pg17-extensions pgpool-II-pg17 +dnf install pgpool-II-pg18-extensions pgpool-II-pg18 </programlisting> <para> Optionally you can install debuginfo and devel packages for developers if necessary. </para> <programlisting> -dnf install pgpool-II-pg17-debuginfo pgpool-II-pg17-devel +dnf install pgpool-II-pg18-debuginfo pgpool-II-pg18-devel </programlisting> </sect2> @@ -184,7 +180,7 @@ dnf install pgpool-II-pg17-debuginfo pgpool-II-pg17-devel <sect2 id="start-rpm"> <title>Starting/stopping Pgpool-II</title> <para> - On RHEL9/8/7, do this once, if set the automatic startup of <productname>Pgpool-II</productname>. + On RHEL10/9/8, do this once, if set the automatic startup of <productname>Pgpool-II</productname>. <programlisting> systemctl enable pgpool.service </programlisting> diff --git a/doc/src/sgml/installation-tips.sgml b/doc/src/sgml/installation-tips.sgml index e7dd81a39..8c9c61043 100644 --- a/doc/src/sgml/installation-tips.sgml +++ b/doc/src/sgml/installation-tips.sgml @@ -33,7 +33,7 @@ </para> <para> - Here is an example for CentOS/RHEL7 when access + Here is an example for Rocky Linux/RHEL10 when access to <productname>PostgreSQL</productname> is required. <programlisting> diff --git a/doc/src/sgml/misc-config.sgml b/doc/src/sgml/misc-config.sgml index eb48b99f7..d4c20fd99 100644 --- a/doc/src/sgml/misc-config.sgml +++ b/doc/src/sgml/misc-config.sgml @@ -260,10 +260,10 @@ </listitem> </varlistentry> - <varlistentry id="guc-logdir" xreflabel="logdir"> - <term><varname>logdir</varname> (<type>string</type>) + <varlistentry id="guc-work-dir" xreflabel="work_dir"> + <term><varname>work_dir</varname> (<type>string</type>) <indexterm> - <primary><varname>logdir</varname> configuration parameter</primary> + <primary><varname>work_dir</varname> configuration parameter</primary> </indexterm> </term> <listitem> @@ -298,7 +298,7 @@ enables the testing facility of health checking. In this case the health check process looks into <filename>backend_down_request</filename> - under <xref linkend="guc-logdir">. The file may contain multiple + under <xref linkend="guc-work-dir">. The file may contain multiple lines, and each line corresponds to each backend. A line in the file starts with backend id (must be a decimal number starting with zero), then a TAB, and ends with "down". The backend is diff --git a/doc/src/sgml/performance.sgml b/doc/src/sgml/performance.sgml index 8657ea97d..be9f0c72f 100644 --- a/doc/src/sgml/performance.sgml +++ b/doc/src/sgml/performance.sgml @@ -202,7 +202,7 @@ <para> If there are multiple <productname>PostgreSQL</productname> nodes and <productname>Pgpool-II</productname> operates in - streaming replication mode, logical replication mode, slony mode + streaming replication mode, logical replication mode, or replication mode (for those running mode see <xref linkend="running-mode"> for more details), it is possible to distribute read queries among those database nodes diff --git a/doc/src/sgml/ref/pgpool_setup.sgml b/doc/src/sgml/ref/pgpool_setup.sgml index 57d735a90..ab8fd2771 100644 --- a/doc/src/sgml/ref/pgpool_setup.sgml +++ b/doc/src/sgml/ref/pgpool_setup.sgml @@ -73,7 +73,7 @@ Pgpool-II documentation Specifies the running mode. <replaceable>mode</replaceable> can be <literal>r</literal> (native replication mode), <literal>s</literal> (streaming replication mode), <literal>n</literal> (raw mode), <literal>l</literal> - (logical replication mode), <literal>y</literal> (slony mode) or <literal>i</literal> (snapshot isolation mode). If this is + (logical replication mode), or <literal>i</literal> (snapshot isolation mode). If this is omitted, <literal>s</literal> is assumed. </para> </listitem> diff --git a/doc/src/sgml/ref/watchdog_setup.sgml b/doc/src/sgml/ref/watchdog_setup.sgml index 18f27958b..76d7f2f03 100644 --- a/doc/src/sgml/ref/watchdog_setup.sgml +++ b/doc/src/sgml/ref/watchdog_setup.sgml @@ -42,7 +42,6 @@ Pgpool-II documentation <para> <application>watchdog_setup</application> is for testing purpose only and should not be used to create production installations. - Also please note that heartbeat is not used. </para> <para> @@ -113,6 +112,28 @@ Pgpool-II documentation </varlistentry> <varlistentry> + <term><option>-vip [<replaceable class="parameter">ip</replaceable>]</option></term> + <listitem> + <para> + Specify the virtual IP. If ip is omitted, it is assumed that + '127.0.0.1' is specified. The specified virtual IP is set + to <xref linkend="guc-delegate-ip"> parameter. Even if virtual + IP is specified, it will not be set to the system: just you + could confirm the action trying to set the virtual IP + in <xref linkend="PCP-WATCHDOG-INFO">, or the log file, yet + this is useful how <productname>Pgpool-II</productname> reacts + trying to set the virtual IP. In additioin to delegate_ip, + following parameters will be set too. + <programlisting> + if_up_cmd = '/usr/bin/echo "if_up_cmd executed"' + if_down_cmd = 'usr/bin/echo "if_down_cmd executed"' + arping_cmd = '/usr/bin/true' + </programlisting> + </para> + </listitem> + </varlistentry> + + <varlistentry> <term><option>--no-stop</option></term> <listitem> <para> diff --git a/doc/src/sgml/release-3.6.sgml b/doc/src/sgml/release-3.6.sgml index 1869c2774..b92c24634 100644 --- a/doc/src/sgml/release-3.6.sgml +++ b/doc/src/sgml/release-3.6.sgml @@ -1741,7 +1741,7 @@ 2019-01-03 [79ef2b0] --> <para> - Doc: fix typo in <xref linkend="GUC-LOGDIR"> description. (<ulink url="http://www.pgpool.net/mantisbt/view.php?id=453">bug 453</ulink>) (Tatsuo Ishii) + Doc: fix typo in <link linkend="GUC-WORK-DIR">logdir</link> description. (<ulink url="http://www.pgpool.net/mantisbt/view.php?id=453">bug 453</ulink>) (Tatsuo Ishii) </para> </listitem> diff --git a/doc/src/sgml/release-3.7.sgml b/doc/src/sgml/release-3.7.sgml index fa26fec97..87a13b25a 100644 --- a/doc/src/sgml/release-3.7.sgml +++ b/doc/src/sgml/release-3.7.sgml @@ -2691,7 +2691,7 @@ 2019-01-03 [520649b] --> <para> - Doc: fix typo in <xref linkend="GUC-LOGDIR"> description. (<ulink url="http://www.pgpool.net/mantisbt/view.php?id=453">bug 453</ulink>) (Tatsuo Ishii) + Doc: fix typo in <link linkend="GUC-WORK-DIR">logdir</link> description. (<ulink url="http://www.pgpool.net/mantisbt/view.php?id=453">bug 453</ulink>) (Tatsuo Ishii) </para> </listitem> diff --git a/doc/src/sgml/release-4.0.sgml b/doc/src/sgml/release-4.0.sgml index 4160ab654..62439b143 100644 --- a/doc/src/sgml/release-4.0.sgml +++ b/doc/src/sgml/release-4.0.sgml @@ -3707,7 +3707,7 @@ 2019-01-03 [de632ca] --> <para> - Doc: fix typo in <xref linkend="GUC-LOGDIR"> description. (<ulink url="http://www.pgpool.net/mantisbt/view.php?id=453">bug 453</ulink>) (Tatsuo Ishii) + Doc: fix typo in <link linkend="GUC-WORK-DIR">logdir</link> description. (<ulink url="http://www.pgpool.net/mantisbt/view.php?id=453">bug 453</ulink>) (Tatsuo Ishii) </para> </listitem> diff --git a/doc/src/sgml/release-4.2.sgml b/doc/src/sgml/release-4.2.sgml index 94af553da..054315ba3 100644 --- a/doc/src/sgml/release-4.2.sgml +++ b/doc/src/sgml/release-4.2.sgml @@ -1,6 +1,465 @@ <!-- doc/src/sgml/release-4.2.sgml --> <!-- See header comment in release.sgml about typical markup --> +<sect1 id="release-4-2-24"> + <title>Release 4.2.24</title> + <note> + <title>Release Date</title> + <simpara>2025-11-25</simpara> + </note> + + <sect2> + <title>Changes</title> + <itemizedlist> + <listitem> + <!-- + 2025-11-07 [4fabca331] + --> + <para> + Remove unnecessary <varname>application_name</varname> treatment. (Tatsuo Ishii) + </para> + <para> + A previous commit added a step to set <varname>application_name</varname> when reusing existing connections. + However, this is unnecessary because DISCARD ALL automatically resets <varname>application_name</varname>, + and <function>send_params()</function> already sends all necessary parameter status messages, including <varname>application_name</varname>, to the frontend. + Removing this redundant step also improves performance, particularly for backend nodes that are geographically distant. + </para> + <para> + Discussion: <ulink url="https://github.com/pgpool/pgpool2/issues/130">Severely degraded performance of pgPool in geo-distributed configurations</ulink> + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>Bug fixes</title> + <itemizedlist> + <listitem> + <!-- + 2025-11-16 [b113027dd] + --> + <para> + Fix segfault with <command>CopyOut</command>. (Tatsuo Ishii) + </para> + <para> + When <command>COPY relname TO STDOUT</command> is executed in the extended query + protocol mode, pgpool segfaulted. + </para> + <para> + This problem is reported by <ulink url="https://github.com/tetesh">https://github.com/tetesh</ulink>. + </para> + <para> + Discussion: <ulink url="https://github.com/pgpool/pgpool2/issues/133">datanymizer and pg-pool segmentation fault</ulink> + </para> + </listitem> + <listitem> + <!-- + 2025-10-03 [b84553bf0] + --> + <para> + Prevent watchdog split-brain scenario in some corner cases. (Tatsuo Ishii) + </para> + <para> + Watchdog uses both beacon messages and heartbeat for communication. + If the heartbeat is not yet active, missing beacon messages + for over 30 seconds can cause a split-brain scenario, + where the old leader remains active while a new leader is elected. + This change prevents two leaders from existing simultaneously by revoking the old leader. + When a node detects that it has missed beacon messages from the leader more than twice, + the leader is set to LOST and a new leader election is triggered via set_state(WD_JOINING). + </para> + </listitem> + + <listitem> + <!-- + 2025-10-03 [ef8ccb9e7] + --> + <para> + Prevent FATAL error when non-existing prepared statement is given. (Tatsuo Ishii) + </para> + <para> + Previously, <function>Bind()</function> raised a FATAL error when a non-existing prepared statement was used, unlike PostgreSQL. + This change changes <function>Bind()</function> to check for the statement's existence and send an ERROR message to the frontend if it does not exist. + Note that no log is written, as logging this is not currently possible. + </para> + </listitem> + + <listitem> + <!-- + 2025-09-24 [59a359eef] + --> + <para> + Fix <xref linkend="pg-enc"> not working if both -p and -P are provided. (Tatsuo Ishii) + </para> + <para> + The original report showed that running pg_enc -p -P prompted for a password and encryption key, + but failed if the key was not provided. + </para> + <para> + Discussion: <ulink url="https://www.postgresql.org/message-id/7f18c30b.237.1997555ca11.Coremail.liujy%40highgo.com">pg_enc</ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-09-18 [f20f7041c] + --> + <para> + Fix compiling issue on 32-bit environments. (Tatsuo Ishii) + </para> + <para> + On 32-bit systems, compiling src/parser/snprintf.c fails due to undefined functions <function>isnan()</function> and <function>isinf()</function>, which come from math.h. + This change includes math.h and also reorders the include files for clarity. + The file was originally imported from PostgreSQL, where math.h was already included. + This fix was provided via pull request: https://github.com/pgpool/pgpool2/pull/128 + </para> + <para> + Discussion: <ulink url="https://www.postgresql.org/message-id/20250917.194736.353755422175293639.ishii%40postgresql.org">Compiling issues for 32-bit targets</ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-09-10 [0a6868d40] + --> + <para> + Fix safer directory deletion in Bash in recovery_1st_stage.sample. (Taiki Koshino) + </para> + <para> + Quote variables in rm commands to avoid accidental deletion: + <command>rm -rf "${DEST_NODE_PGDATA}"</command> + + If the variable is empty, rm could delete unexpected files or directories. + </para> + </listitem> + + <listitem> + <!-- + 2025-09-05 [441f338ab] + --> + <para> + Fix the compilation error when building without the <option>--with-memcached</option> option. (Tatsuo Ishii) + </para> + <para> + A compiler error occurred when configuring without <option>--with-memcached</option>. + The issue arose because the compiler could not determine that ptr would only be freed when memcached is enabled. + To fix this, the relevant code block was wrapped with #ifdef USE_MEMCACHED. + </para> + <para> + Problem reported by Bo Peng. + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>Documents</title> + <itemizedlist> + <listitem> + <!-- + 2025-09-17 [1a975b539] + --> + <para> + Update doc about "Setting up PostgreSQL standby" in <ulink url="https://www.pgpool.net/docs/latest/ja/html/example-cluster.html">8.2. Pgpool-II + Watchdog Setup Example</ulink>. (Taiki Koshino) + </para> + <para> + Add a note that when setting up a standby without online recovery, do not write <varname>primary_conninfo</varname> to postgresql.auto.conf. + </para> + <para> + Discussion: <ulink url="https://github.com/pgpool/pgpool2/issues/67">Follow primary command not fixing postgresql.auto.conf</ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-08-22 [5bd535792] + --> + <para> + Fix watchdog_setup manual. (Tatsuo Ishii) + </para> + <para> + It mistakenly stated that heartbeart is not setup in watchdog_setup. + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>Regression Tests</title> + <itemizedlist> + <listitem> + <!-- + 2025-09-30 [3ddbc64f1] + --> + <para> + Adapt 023.ssl_connection to PostgreSQL 18. (Tatsuo Ishii) + </para> + <para> + PostgreSQL 18 heavily changed psql's \conninfo output format, which + made the test fail because the test relies on \conninfo. This change + makes the test script aware the PostgreSQL version to fix the issue. + </para> + </listitem> + + <listitem> + <!-- + 2025-08-29 [b4043e6c3] + --> + <para> + Fix ruby script in 010.rewrite_timestamp. (Tatsuo Ishii) + </para> + <para> + The ruby script used "File.exists", which is said to be obsoleted in + newer version of Ruby. Replace it with "File.exist". + </para> + </listitem> + + <listitem> + <!-- + 2025-08-29 [9c901e60a] + --> + <para> + Tweak timeout in 034 and 075 tests. (Tatsuo Ishii) + </para> + <para> + 034.promote_node and 075.detach_primary_left_down_node set the timeout + 60 seconds for finishing follow primary script. It turns out that + these timeout values are not long enough, and sometimes caused false + errors. So make them from 60 seconds to 120 seconds. + </para> + </listitem> + + <listitem> + <!-- + 2025-08-27 [42b177614] + --> + <para> + Add ssl_ecdh_curve test to 023.ssl_connection. (Tatsuo Ishii) + </para> + <para> + 023.ssl_connection did not cover the test for ssl_ecdh_curve. This + commit tests it using bad ssl_ecdh_curve parameter to see if connection + between frontend and pgpool fails. + </para> + </listitem> + </itemizedlist> + </sect2> +</sect1> + +<sect1 id="release-4-2-23"> + <title>Release 4.2.23</title> + <note> + <title>Release Date</title> + <simpara>2025-08-21</simpara> + </note> + + <sect2> + <title>Bug fixes</title> + <itemizedlist> + <listitem> + <!-- + 2025-07-25 [75d905ff9] + --> + <para> + Fix watchdog to print inappropriate NOTICE message. (Tatsuo Ishii) + </para> + <para> + <function>read_ipc_socket_and_process()</function> printed a notice message every time when + it wrote commands to IPC socket even if it was successful. Fix this to + print the notice message only when the write failed. + + The reason why this bug was not recognized is, the message appears + only when <varname>log_min_messages</varname> is set to notice or higher. + </para> + <para> + Discussion: <ulink url="https://github.com/pgpool/pgpool2/issues/121">pgpool IPC socket connection issue</ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-07-19 [d05de5c73] + --> + <!-- + 2025-07-19 [ed57af34e] + --> + <para> + Fix resource leak while reading startup packet. (Tatsuo Ishii) + </para> + <para> + Fix resource leak in pool_push_pending_data. + </para> + </listitem> + + <listitem> + <!-- + 2025-06-30 [bac455b2f] + --> + <para> + Fix broken scram-sha-256 authentication on big-endian machines. (Tatsuo Ishii) + </para> + <para> + When <literal>scram-sha-256</literal> authentication is performed, a hash function + <function>pg_sha_256_final</function> is used. It was imported from <productname>PostgreSQL</productname> and it uses + preprocessor define WORDS_BIGENDIAN to judge host machine's + endianness. Although WORDS_BIGENDIAN should be defined while + configure, this part was missed when <function>pg_sha_256_final</function> (and others) was + imported from <productname>PostgreSQL</productname>. As a result, <literal>scram-sha-256</literal> worked only in + little endian machines. Fixed the issue by adding + AC_C_BIGENDIAN macro to configure.ac. + </para> + <para> + Problem reported by Christoph Berg and analyzed by pranavkaruvally. + </para> + <para> + Discussion: <ulink url="https://github.com/pgpool/pgpool2/issues/106">4.6.1 fails on big-endian s390x: backend response with kind 'E' when expecting 'R'</ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-06-23 [2721c7b76] + --> + <para> + Fix source code typos. (Bo Peng) + </para> + </listitem> + + <listitem> + <!-- + 2025-06-09 [4305c42d6] + --> + <para> + Fix heartbeat device treatment. (Tatsuo Ishii) + </para> + <para> + While processing <filename>pgpool.conf</filename>, <varname>heartbeat_device</varname> was mistakenly treated + and the first device was ignored. + </para> + <para> + Problem analyzed by Bo Peng. + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>Documents</title> + <itemizedlist> + <listitem> + <!-- + 2025-08-04 [e2f24fec8] + --> + <para> + Fix documentation for parameters that are not reflected by reload. (Taiki Koshino) + </para> + <para> + "authentication_timeout" and "memqcache_oiddir" is not reflected by reload. + The documentation is changed to "This parameter can only be set at server start.". + </para> + </listitem> + + <listitem> + <!-- + 2025-07-24 [bc5fa5e7e] + --> + <!-- + 2025-07-23 [1e8963554] + --> + <para> + Unify watchdog leader terms (followup). (Tatsuo Ishii) + </para> + </listitem> + + <listitem> + <!-- + 2025-08-06 [31eee18d7] + --> + <!-- + 2025-07-16 [34b07c2d5] + --> + <para> + Fix example script link. (Taiki Koshino) + </para> + <para> + Modified the sample script in the section "<ulink url="https://www.pgpool.net/docs/46/en/html/example-cluster.html">8.2. Pgpool-II + Watchdog Setup Example</ulink>" + </para> + </listitem> + + <listitem> + <!-- + 2025-06-18 [f4ae9f39e] + 2025-06-18 [7a20dc419] + --> + <para> + Fix load balance explanation missed logical replication mode and Slony mode. (Tatsuo Ishii) + </para> + </listitem> + + <listitem> + <!-- + 2025-06-08 [59f9df005] + --> + <para> + Add section of kernel resources. (Tatsuo Ishii) + </para> + <para> + <productname>Pgpool-II</productname> uses System V shared memory and semaphores. It's better to + describe the requirements in the docs. + </para> + </listitem> + + <listitem> + <!-- + 2025-06-07 [40617fd90] + --> + <para> + Add description for <option>--with-ldap</option> option of configure. (Tatsuo Ishii) + </para> + <para> + It was missed when LDAP support was introduced in v4.2 + </para> + </listitem> + + <listitem> + <!-- + 2025-06-04 [ff60bf930] + --> + <para> + Clarify supported platforms for <productname>Pgpool-II</productname>. (Tatsuo Ishii) + </para> + </listitem> + + <listitem> + <!-- + 2025-06-03 [cc4da5979] + --> + <para> + Enhance <xref linkend="guc-child-life-time"> document. (Tatsuo Ishii) + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>Regression Tests</title> + <itemizedlist> + <listitem> + <!-- + 2025-06-08 [78e45decf] + --> + <para> + Stabilize 029.cert_passphrase regression test. (Tatsuo Ishii) + </para> + <para> + When <varname>ssl_passphrase_command</varname> is not valid, the error message is + typically "bad decrypt" but it seems sometimes "wrong tag". + </para> + </listitem> + </itemizedlist> + </sect2> +</sect1> + <sect1 id="release-4-2-22"> <title>Release 4.2.22</title> <note> diff --git a/doc/src/sgml/release-4.3.sgml b/doc/src/sgml/release-4.3.sgml index 733e5db53..40d80ce8d 100644 --- a/doc/src/sgml/release-4.3.sgml +++ b/doc/src/sgml/release-4.3.sgml @@ -1,6 +1,570 @@ <!-- doc/src/sgml/release-4.3.sgml --> <!-- See header comment in release.sgml about typical markup --> +<sect1 id="release-4-3-18"> + <title>Release 4.3.18</title> + <note> + <title>Release Date</title> + <simpara>2025-12-15</simpara> + </note> + + <sect2> + <title>Changes</title> + <itemizedlist> + <listitem> + <!-- + 2025-12-08 [5bd10177c] + --> + <para> + Use "grep -E" instead of deprecated "egrep" in pgpool_setup. (Bo Peng) + </para> + <para> + Replace "egrep" with "grep -E" to avoid obsolescence warnings on newer GNU grep versions. + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>Bug fixes</title> + <itemizedlist> + <listitem> + <!-- + 2025-12-08 [8deccc15e] + --> + <para> + Fix buffer overflow error in show pool_status. (Tatsuo Ishii) + </para> + <para> + "show pool_status", "pgpool show" and pcp_pool_status could cause a + buffer overflow error. If backend_flag is set to "ALWAYS_PRIMARY", + pool_flag_to_str(), which is responsible to produce printable format + of backend_flag, wrote data past to the end of static buffer. + </para> + <para> + Problem reported by zam bak and reviewed by Bo Peng. + </para> + <para> + Discussion: <ulink url="https://www.postgresql.org/message-id/20251202.140205.427777414210613577.ishii%40postgresql.org">Re: "buffer overflow detected" when running SHOW POOL_STATUS</ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-12-02 [c8865c703] + --> + <para> + Fix memqcache_stats_start_time shown in "show pool_status". (Tatsuo Ishii) + </para> + <para> + get_config() uses ctime() to generate printable form of + memqcache_stats_start_time. But it did not take into account that + ctime() adds newline at the end of result. As a result, not only the + output of memqcache_stats_start_time was with unnecessary newline but + next row printed empty items. + </para> + <para> + Discussion: <ulink url="https://www.postgresql.org/message-id/20251130.102712.131456481338876013.ishii%40postgresql.org">Re: "buffer overflow detected" when running SHOW POOL_STATUS</ulink> + </para> + </listitem> + </itemizedlist> + </sect2> +</sect1> + +<sect1 id="release-4-3-17"> + <title>Release 4.3.17</title> + <note> + <title>Release Date</title> + <simpara>2025-11-25</simpara> + </note> + + <sect2> + <title>Changes</title> + <itemizedlist> + <listitem> + <!-- + 2025-11-07 [4fabca331] + --> + <para> + Remove unnecessary <varname>application_name</varname> treatment. (Tatsuo Ishii) + </para> + <para> + A previous commit added a step to set <varname>application_name</varname> when reusing existing connections. + However, this is unnecessary because DISCARD ALL automatically resets <varname>application_name</varname>, + and <function>send_params()</function> already sends all necessary parameter status messages, including <varname>application_name</varname>, to the frontend. + Removing this redundant step also improves performance, particularly for backend nodes that are geographically distant. + </para> + <para> + Discussion: <ulink url="https://github.com/pgpool/pgpool2/issues/130">Severely degraded performance of pgPool in geo-distributed configurations</ulink> + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>Bug fixes</title> + <itemizedlist> + <listitem> + <!-- + 2025-11-16 [b113027dd] + --> + <para> + Fix segfault with <command>CopyOut</command>. (Tatsuo Ishii) + </para> + <para> + When <command>COPY relname TO STDOUT</command> is executed in the extended query + protocol mode, pgpool segfaulted. + </para> + <para> + This problem is reported by <ulink url="https://github.com/tetesh">https://github.com/tetesh</ulink>. + </para> + <para> + Discussion: <ulink url="https://github.com/pgpool/pgpool2/issues/133">datanymizer and pg-pool segmentation fault</ulink> + </para> + </listitem> + <listitem> + <!-- + 2025-10-03 [b84553bf0] + --> + <para> + Prevent watchdog split-brain scenario in some corner cases. (Tatsuo Ishii) + </para> + <para> + Watchdog uses both beacon messages and heartbeat for communication. + If the heartbeat is not yet active, missing beacon messages + for over 30 seconds can cause a split-brain scenario, + where the old leader remains active while a new leader is elected. + This change prevents two leaders from existing simultaneously by revoking the old leader. + When a node detects that it has missed beacon messages from the leader more than twice, + the leader is set to LOST and a new leader election is triggered via set_state(WD_JOINING). + </para> + </listitem> + + <listitem> + <!-- + 2025-10-03 [ef8ccb9e7] + --> + <para> + Prevent FATAL error when non-existing prepared statement is given. (Tatsuo Ishii) + </para> + <para> + Previously, <function>Bind()</function> raised a FATAL error when a non-existing prepared statement was used, unlike PostgreSQL. + This change changes <function>Bind()</function> to check for the statement's existence and send an ERROR message to the frontend if it does not exist. + Note that no log is written, as logging this is not currently possible. + </para> + </listitem> + + <listitem> + <!-- + 2025-09-24 [59a359eef] + --> + <para> + Fix <xref linkend="pg-enc"> not working if both -p and -P are provided. (Tatsuo Ishii) + </para> + <para> + The original report showed that running pg_enc -p -P prompted for a password and encryption key, + but failed if the key was not provided. + </para> + <para> + Discussion: <ulink url="https://www.postgresql.org/message-id/7f18c30b.237.1997555ca11.Coremail.liujy%40highgo.com">pg_enc</ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-09-18 [f20f7041c] + --> + <para> + Fix compiling issue on 32-bit environments. (Tatsuo Ishii) + </para> + <para> + On 32-bit systems, compiling src/parser/snprintf.c fails due to undefined functions <function>isnan()</function> and <function>isinf()</function>, which come from math.h. + This change includes math.h and also reorders the include files for clarity. + The file was originally imported from PostgreSQL, where math.h was already included. + This fix was provided via pull request: https://github.com/pgpool/pgpool2/pull/128 + </para> + <para> + Discussion: <ulink url="https://www.postgresql.org/message-id/20250917.194736.353755422175293639.ishii%40postgresql.org">Compiling issues for 32-bit targets</ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-09-10 [0a6868d40] + --> + <para> + Fix safer directory deletion in Bash in recovery_1st_stage.sample. (Taiki Koshino) + </para> + <para> + Quote variables in rm commands to avoid accidental deletion: + <command>rm -rf "${DEST_NODE_PGDATA}"</command> + + If the variable is empty, rm could delete unexpected files or directories. + </para> + </listitem> + + <listitem> + <!-- + 2025-09-05 [441f338ab] + --> + <para> + Fix the compilation error when building without the <option>--with-memcached</option> option. (Tatsuo Ishii) + </para> + <para> + A compiler error occurred when configuring without <option>--with-memcached</option>. + The issue arose because the compiler could not determine that ptr would only be freed when memcached is enabled. + To fix this, the relevant code block was wrapped with #ifdef USE_MEMCACHED. + </para> + <para> + Problem reported by Bo Peng. + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>Documents</title> + <itemizedlist> + <listitem> + <!-- + 2025-09-17 [1a975b539] + --> + <para> + Update doc about "Setting up PostgreSQL standby" in <ulink url="https://www.pgpool.net/docs/latest/ja/html/example-cluster.html">8.2. Pgpool-II + Watchdog Setup Example</ulink>. (Taiki Koshino) + </para> + <para> + Add a note that when setting up a standby without online recovery, do not write <varname>primary_conninfo</varname> to postgresql.auto.conf. + </para> + <para> + Discussion: <ulink url="https://github.com/pgpool/pgpool2/issues/67">Follow primary command not fixing postgresql.auto.conf</ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-08-22 [5bd535792] + --> + <para> + Fix watchdog_setup manual. (Tatsuo Ishii) + </para> + <para> + It mistakenly stated that heartbeart is not setup in watchdog_setup. + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>Regression Tests</title> + <itemizedlist> + <listitem> + <!-- + 2025-09-30 [3ddbc64f1] + --> + <para> + Adapt 023.ssl_connection to PostgreSQL 18. (Tatsuo Ishii) + </para> + <para> + PostgreSQL 18 heavily changed psql's \conninfo output format, which + made the test fail because the test relies on \conninfo. This change + makes the test script aware the PostgreSQL version to fix the issue. + </para> + </listitem> + + <listitem> + <!-- + 2025-08-29 [b4043e6c3] + --> + <para> + Fix ruby script in 010.rewrite_timestamp. (Tatsuo Ishii) + </para> + <para> + The ruby script used "File.exists", which is said to be obsoleted in + newer version of Ruby. Replace it with "File.exist". + </para> + </listitem> + + <listitem> + <!-- + 2025-08-29 [9c901e60a] + --> + <para> + Tweak timeout in 034 and 075 tests. (Tatsuo Ishii) + </para> + <para> + 034.promote_node and 075.detach_primary_left_down_node set the timeout + 60 seconds for finishing follow primary script. It turns out that + these timeout values are not long enough, and sometimes caused false + errors. So make them from 60 seconds to 120 seconds. + </para> + </listitem> + + <listitem> + <!-- + 2025-08-27 [42b177614] + --> + <para> + Add ssl_ecdh_curve test to 023.ssl_connection. (Tatsuo Ishii) + </para> + <para> + 023.ssl_connection did not cover the test for ssl_ecdh_curve. This + commit tests it using bad ssl_ecdh_curve parameter to see if connection + between frontend and pgpool fails. + </para> + </listitem> + </itemizedlist> + </sect2> +</sect1> + +<sect1 id="release-4-3-16"> + <title>Release 4.3.16</title> + <note> + <title>Release Date</title> + <simpara>2025-08-21</simpara> + </note> + + <sect2> + <title>Bug fixes</title> + <itemizedlist> + <listitem> + <!-- + 2025-07-25 [75d905ff9] + --> + <para> + Fix watchdog to print inappropriate NOTICE message. (Tatsuo Ishii) + </para> + <para> + <function>read_ipc_socket_and_process()</function> printed a notice message every time when + it wrote commands to IPC socket even if it was successful. Fix this to + print the notice message only when the write failed. + + The reason why this bug was not recognized is, the message appears + only when <varname>log_min_messages</varname> is set to notice or higher. + </para> + <para> + Discussion: <ulink url="https://github.com/pgpool/pgpool2/issues/121">pgpool IPC socket connection issue</ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-07-19 [d05de5c73] + --> + <!-- + 2025-07-19 [ed57af34e] + --> + <para> + Fix resource leak while reading startup packet. (Tatsuo Ishii) + </para> + <para> + Fix resource leak in pool_push_pending_data. + </para> + </listitem> + + <listitem> + <!-- + 2025-06-30 [bac455b2f] + --> + <para> + Fix broken scram-sha-256 authentication on big-endian machines. (Tatsuo Ishii) + </para> + <para> + When <literal>scram-sha-256</literal> authentication is performed, a hash function + <function>pg_sha_256_final</function> is used. It was imported from <productname>PostgreSQL</productname> and it uses + preprocessor define WORDS_BIGENDIAN to judge host machine's + endianness. Although WORDS_BIGENDIAN should be defined while + configure, this part was missed when <function>pg_sha_256_final</function> (and others) was + imported from <productname>PostgreSQL</productname>. As a result, <literal>scram-sha-256</literal> worked only in + little endian machines. Fixed the issue by adding + AC_C_BIGENDIAN macro to configure.ac. + </para> + <para> + Problem reported by Christoph Berg and analyzed by pranavkaruvally. + </para> + <para> + Discussion: <ulink url="https://github.com/pgpool/pgpool2/issues/106">4.6.1 fails on big-endian s390x: backend response with kind 'E' when expecting 'R'</ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-06-23 [2721c7b76] + --> + <para> + Fix source code typos. (Bo Peng) + </para> + </listitem> + + <listitem> + <!-- + 2025-06-09 [4305c42d6] + --> + <para> + Fix heartbeat device treatment. (Tatsuo Ishii) + </para> + <para> + While processing <filename>pgpool.conf</filename>, <varname>heartbeat_device</varname> was mistakenly treated + and the first device was ignored. + </para> + <para> + Problem analyzed by Bo Peng. + </para> + </listitem> + + <listitem> + <!-- + 2025-06-02 [06ba7dde4] + --> + <para> + Fix typo in the comments of <filename>pgpool.conf</filename>. (Tatsuo Ishii) + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>Documents</title> + <itemizedlist> + <listitem> + <!-- + 2025-08-15 [a54f5d1ad] + --> + <para> + Enhance "8.3. Replication Mode and Snapshot Isolation Mode Configuration Example" Document. (Taiki Koshino) + </para> + <para> + Updated the link to the example script and the explanation in the "8.3.3. Before you begin" section. + </para> + </listitem> + + <listitem> + <!-- + 2025-08-04 [e2f24fec8] + --> + <para> + Fix documentation for parameters that are not reflected by reload. (Taiki Koshino) + </para> + <para> + "authentication_timeout" and "memqcache_oiddir" is not reflected by reload. + The documentation is changed to "This parameter can only be set at server start.". + </para> + </listitem> + + <listitem> + <!-- + 2025-07-24 [bc5fa5e7e] + --> + <!-- + 2025-07-23 [1e8963554] + --> + <para> + Unify watchdog leader terms (followup). (Tatsuo Ishii) + </para> + </listitem> + + <listitem> + <!-- + 2025-08-06 [31eee18d7] + --> + <!-- + 2025-07-16 [34b07c2d5] + --> + <para> + Fix example script link. (Taiki Koshino) + </para> + <para> + Modified the sample script in the section "<ulink url="https://www.pgpool.net/docs/46/en/html/example-cluster.html">8.2. Pgpool-II + Watchdog Setup Example</ulink>" + </para> + </listitem> + + <listitem> + <!-- + 2025-06-18 [f4ae9f39e] + 2025-06-18 [7a20dc419] + --> + <para> + Fix load balance explanation missed logical replication mode and Slony mode. (Tatsuo Ishii) + </para> + </listitem> + + <listitem> + <!-- + 2025-06-18 [9d2e4e692] + --> + <para> + Enhance <xref linkend="pcp-node-info"> document. (Bo Peng) + </para> + <para> + Clarify that each <varname>backend_application_nameX</varname> must match the value specified + in the <varname>application_name</varname> of <varname>primary_conninfo</varname> to correctly display + "<varname>replication_state</varname>" and "<varname>replication_sync_state</varname>". + </para> + </listitem> + + <listitem> + <!-- + 2025-06-08 [59f9df005] + --> + <para> + Add section of kernel resources. (Tatsuo Ishii) + </para> + <para> + <productname>Pgpool-II</productname> uses System V shared memory and semaphores. It's better to + describe the requirements in the docs. + </para> + </listitem> + + <listitem> + <!-- + 2025-06-07 [40617fd90] + --> + <para> + Add description for <option>--with-ldap</option> option of configure. (Tatsuo Ishii) + </para> + <para> + It was missed when LDAP support was introduced in v4.2 + </para> + </listitem> + + <listitem> + <!-- + 2025-06-04 [ff60bf930] + --> + <para> + Clarify supported platforms for <productname>Pgpool-II</productname>. (Tatsuo Ishii) + </para> + </listitem> + + <listitem> + <!-- + 2025-06-03 [cc4da5979] + --> + <para> + Enhance <xref linkend="guc-child-life-time"> document. (Tatsuo Ishii) + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>Regression Tests</title> + <itemizedlist> + <listitem> + <!-- + 2025-06-08 [78e45decf] + --> + <para> + Stabilize 029.cert_passphrase regression test. (Tatsuo Ishii) + </para> + <para> + When <varname>ssl_passphrase_command</varname> is not valid, the error message is + typically "bad decrypt" but it seems sometimes "wrong tag". + </para> + </listitem> + </itemizedlist> + </sect2> +</sect1> + <sect1 id="release-4-3-15"> <title>Release 4.3.15</title> <note> diff --git a/doc/src/sgml/release-4.4.sgml b/doc/src/sgml/release-4.4.sgml index 5a05025e6..ac6fdf400 100644 --- a/doc/src/sgml/release-4.4.sgml +++ b/doc/src/sgml/release-4.4.sgml @@ -1,6 +1,586 @@ <!-- doc/src/sgml/release-4.4.sgml --> <!-- See header comment in release.sgml about typical markup --> +<sect1 id="release-4-4-15"> + <title>Release 4.4.15</title> + <note> + <title>Release Date</title> + <simpara>2025-12-15</simpara> + </note> + + <sect2> + <title>Changes</title> + <itemizedlist> + <listitem> + <!-- + 2025-12-08 [5bd10177c] + --> + <para> + Use "grep -E" instead of deprecated "egrep" in pgpool_setup. (Bo Peng) + </para> + <para> + Replace "egrep" with "grep -E" to avoid obsolescence warnings on newer GNU grep versions. + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>Bug fixes</title> + <itemizedlist> + <listitem> + <!-- + 2025-12-08 [8deccc15e] + --> + <para> + Fix buffer overflow error in show pool_status. (Tatsuo Ishii) + </para> + <para> + "show pool_status", "pgpool show" and pcp_pool_status could cause a + buffer overflow error. If backend_flag is set to "ALWAYS_PRIMARY", + pool_flag_to_str(), which is responsible to produce printable format + of backend_flag, wrote data past to the end of static buffer. + </para> + <para> + Problem reported by zam bak and reviewed by Bo Peng. + </para> + <para> + Discussion: <ulink url="https://www.postgresql.org/message-id/20251202.140205.427777414210613577.ishii%40postgresql.org">Re: "buffer overflow detected" when running SHOW POOL_STATUS</ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-12-02 [c8865c703] + --> + <para> + Fix memqcache_stats_start_time shown in "show pool_status". (Tatsuo Ishii) + </para> + <para> + get_config() uses ctime() to generate printable form of + memqcache_stats_start_time. But it did not take into account that + ctime() adds newline at the end of result. As a result, not only the + output of memqcache_stats_start_time was with unnecessary newline but + next row printed empty items. + </para> + <para> + Discussion: <ulink url="https://www.postgresql.org/message-id/20251130.102712.131456481338876013.ishii%40postgresql.org">Re: "buffer overflow detected" when running SHOW POOL_STATUS</ulink> + </para> + </listitem> + </itemizedlist> + </sect2> +</sect1> + +<sect1 id="release-4-4-14"> + <title>Release 4.4.14</title> + <note> + <title>Release Date</title> + <simpara>2025-11-25</simpara> + </note> + + <sect2> + <title>Changes</title> + <itemizedlist> + <listitem> + <!-- + 2025-11-07 [4fabca331] + --> + <para> + Remove unnecessary <varname>application_name</varname> treatment. (Tatsuo Ishii) + </para> + <para> + A previous commit added a step to set <varname>application_name</varname> when reusing existing connections. + However, this is unnecessary because DISCARD ALL automatically resets <varname>application_name</varname>, + and <function>send_params()</function> already sends all necessary parameter status messages, including <varname>application_name</varname>, to the frontend. + Removing this redundant step also improves performance, particularly for backend nodes that are geographically distant. + </para> + <para> + Discussion: <ulink url="https://github.com/pgpool/pgpool2/issues/130">Severely degraded performance of pgPool in geo-distributed configurations</ulink> + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>Bug fixes</title> + <itemizedlist> + <listitem> + <!-- + 2025-11-16 [b113027dd] + --> + <para> + Fix segfault with <command>CopyOut</command>. (Tatsuo Ishii) + </para> + <para> + When <command>COPY relname TO STDOUT</command> is executed in the extended query + protocol mode, pgpool segfaulted. + </para> + <para> + This problem is reported by <ulink url="https://github.com/tetesh">https://github.com/tetesh</ulink>. + </para> + <para> + Discussion: <ulink url="https://github.com/pgpool/pgpool2/issues/133">datanymizer and pg-pool segmentation fault</ulink> + </para> + </listitem> + <listitem> + <!-- + 2025-10-03 [b84553bf0] + --> + <para> + Prevent watchdog split-brain scenario in some corner cases. (Tatsuo Ishii) + </para> + <para> + Watchdog uses both beacon messages and heartbeat for communication. + If the heartbeat is not yet active, missing beacon messages + for over 30 seconds can cause a split-brain scenario, + where the old leader remains active while a new leader is elected. + This change prevents two leaders from existing simultaneously by revoking the old leader. + When a node detects that it has missed beacon messages from the leader more than twice, + the leader is set to LOST and a new leader election is triggered via set_state(WD_JOINING). + </para> + </listitem> + + <listitem> + <!-- + 2025-10-03 [ef8ccb9e7] + --> + <para> + Prevent FATAL error when non-existing prepared statement is given. (Tatsuo Ishii) + </para> + <para> + Previously, <function>Bind()</function> raised a FATAL error when a non-existing prepared statement was used, unlike PostgreSQL. + This change changes <function>Bind()</function> to check for the statement's existence and send an ERROR message to the frontend if it does not exist. + Note that no log is written, as logging this is not currently possible. + </para> + </listitem> + + <listitem> + <!-- + 2025-09-24 [59a359eef] + --> + <para> + Fix <xref linkend="pg-enc"> not working if both -p and -P are provided. (Tatsuo Ishii) + </para> + <para> + The original report showed that running pg_enc -p -P prompted for a password and encryption key, + but failed if the key was not provided. + </para> + <para> + Discussion: <ulink url="https://www.postgresql.org/message-id/7f18c30b.237.1997555ca11.Coremail.liujy%40highgo.com">pg_enc</ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-09-18 [f20f7041c] + --> + <para> + Fix compiling issue on 32-bit environments. (Tatsuo Ishii) + </para> + <para> + On 32-bit systems, compiling src/parser/snprintf.c fails due to undefined functions <function>isnan()</function> and <function>isinf()</function>, which come from math.h. + This change includes math.h and also reorders the include files for clarity. + The file was originally imported from PostgreSQL, where math.h was already included. + This fix was provided via pull request: https://github.com/pgpool/pgpool2/pull/128 + </para> + <para> + Discussion: <ulink url="https://www.postgresql.org/message-id/20250917.194736.353755422175293639.ishii%40postgresql.org">Compiling issues for 32-bit targets</ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-09-10 [0a6868d40] + --> + <para> + Fix safer directory deletion in Bash in recovery_1st_stage.sample. (Taiki Koshino) + </para> + <para> + Quote variables in rm commands to avoid accidental deletion: + <command>rm -rf "${DEST_NODE_PGDATA}"</command> + + If the variable is empty, rm could delete unexpected files or directories. + </para> + </listitem> + + <listitem> + <!-- + 2025-09-05 [441f338ab] + --> + <para> + Fix the compilation error when building without the <option>--with-memcached</option> option. (Tatsuo Ishii) + </para> + <para> + A compiler error occurred when configuring without <option>--with-memcached</option>. + The issue arose because the compiler could not determine that ptr would only be freed when memcached is enabled. + To fix this, the relevant code block was wrapped with #ifdef USE_MEMCACHED. + </para> + <para> + Problem reported by Bo Peng. + </para> + </listitem> + <listitem> + <!-- + 2025-09-04 [9e0324575] + --> + <para> + Fix query cache lock file handling. (Tatsuo Ishii) + </para> + <para> + The query cache module creates a lock file in <varname>logdir</varname> for concurrency control, + but two bugs existed: the main pgpool process could create a stray "QUERY_CACHE_LOCK_FILE", + and the lock file was not removed on shutdown. This change fixes both issues. + </para> + <para> + Problem reported and analyzed by Bo Peng. + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>Documents</title> + <itemizedlist> + <listitem> + <!-- + 2025-09-17 [1a975b539] + --> + <para> + Update doc about "Setting up PostgreSQL standby" in <ulink url="https://www.pgpool.net/docs/latest/ja/html/example-cluster.html">8.2. Pgpool-II + Watchdog Setup Example</ulink>. (Taiki Koshino) + </para> + <para> + Add a note that when setting up a standby without online recovery, do not write <varname>primary_conninfo</varname> to postgresql.auto.conf. + </para> + <para> + Discussion: <ulink url="https://github.com/pgpool/pgpool2/issues/67">Follow primary command not fixing postgresql.auto.conf</ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-08-22 [5bd535792] + --> + <para> + Fix watchdog_setup manual. (Tatsuo Ishii) + </para> + <para> + It mistakenly stated that heartbeart is not setup in watchdog_setup. + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>Regression Tests</title> + <itemizedlist> + <listitem> + <!-- + 2025-09-30 [3ddbc64f1] + --> + <para> + Adapt 023.ssl_connection to PostgreSQL 18. (Tatsuo Ishii) + </para> + <para> + PostgreSQL 18 heavily changed psql's \conninfo output format, which + made the test fail because the test relies on \conninfo. This change + makes the test script aware the PostgreSQL version to fix the issue. + </para> + </listitem> + + <listitem> + <!-- + 2025-08-29 [b4043e6c3] + --> + <para> + Fix ruby script in 010.rewrite_timestamp. (Tatsuo Ishii) + </para> + <para> + The ruby script used "File.exists", which is said to be obsoleted in + newer version of Ruby. Replace it with "File.exist". + </para> + </listitem> + + <listitem> + <!-- + 2025-08-29 [9c901e60a] + --> + <para> + Tweak timeout in 034 and 075 tests. (Tatsuo Ishii) + </para> + <para> + 034.promote_node and 075.detach_primary_left_down_node set the timeout + 60 seconds for finishing follow primary script. It turns out that + these timeout values are not long enough, and sometimes caused false + errors. So make them from 60 seconds to 120 seconds. + </para> + </listitem> + + <listitem> + <!-- + 2025-08-27 [42b177614] + --> + <para> + Add ssl_ecdh_curve test to 023.ssl_connection. (Tatsuo Ishii) + </para> + <para> + 023.ssl_connection did not cover the test for ssl_ecdh_curve. This + commit tests it using bad ssl_ecdh_curve parameter to see if connection + between frontend and pgpool fails. + </para> + </listitem> + </itemizedlist> + </sect2> +</sect1> + +<sect1 id="release-4-4-13"> + <title>Release 4.4.13</title> + <note> + <title>Release Date</title> + <simpara>2025-08-21</simpara> + </note> + + <sect2> + <title>Bug fixes</title> + <itemizedlist> + <listitem> + <!-- + 2025-07-25 [75d905ff9] + --> + <para> + Fix watchdog to print inappropriate NOTICE message. (Tatsuo Ishii) + </para> + <para> + <function>read_ipc_socket_and_process()</function> printed a notice message every time when + it wrote commands to IPC socket even if it was successful. Fix this to + print the notice message only when the write failed. + + The reason why this bug was not recognized is, the message appears + only when <varname>log_min_messages</varname> is set to notice or higher. + </para> + <para> + Discussion: <ulink url="https://github.com/pgpool/pgpool2/issues/121">pgpool IPC socket connection issue</ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-07-19 [d05de5c73] + --> + <!-- + 2025-07-19 [ed57af34e] + --> + <para> + Fix resource leak while reading startup packet. (Tatsuo Ishii) + </para> + <para> + Fix resource leak in pool_push_pending_data. + </para> + </listitem> + + <listitem> + <!-- + 2025-06-30 [bac455b2f] + --> + <para> + Fix broken scram-sha-256 authentication on big-endian machines. (Tatsuo Ishii) + </para> + <para> + When <literal>scram-sha-256</literal> authentication is performed, a hash function + <function>pg_sha_256_final</function> is used. It was imported from <productname>PostgreSQL</productname> and it uses + preprocessor define WORDS_BIGENDIAN to judge host machine's + endianness. Although WORDS_BIGENDIAN should be defined while + configure, this part was missed when <function>pg_sha_256_final</function> (and others) was + imported from <productname>PostgreSQL</productname>. As a result, <literal>scram-sha-256</literal> worked only in + little endian machines. Fixed the issue by adding + AC_C_BIGENDIAN macro to configure.ac. + </para> + <para> + Problem reported by Christoph Berg and analyzed by pranavkaruvally. + </para> + <para> + Discussion: <ulink url="https://github.com/pgpool/pgpool2/issues/106">4.6.1 fails on big-endian s390x: backend response with kind 'E' when expecting 'R'</ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-06-23 [2721c7b76] + --> + <para> + Fix source code typos. (Bo Peng) + </para> + </listitem> + + <listitem> + <!-- + 2025-06-09 [4305c42d6] + --> + <para> + Fix heartbeat device treatment. (Tatsuo Ishii) + </para> + <para> + While processing <filename>pgpool.conf</filename>, <varname>heartbeat_device</varname> was mistakenly treated + and the first device was ignored. + </para> + <para> + Problem analyzed by Bo Peng. + </para> + </listitem> + + <listitem> + <!-- + 2025-06-02 [06ba7dde4] + --> + <para> + Fix typo in the comments of <filename>pgpool.conf</filename>. (Tatsuo Ishii) + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>Documents</title> + <itemizedlist> + <listitem> + <!-- + 2025-08-15 [a54f5d1ad] + --> + <para> + Enhance "8.3. Replication Mode and Snapshot Isolation Mode Configuration Example" Document. (Taiki Koshino) + </para> + <para> + Updated the link to the example script and the explanation in the "8.3.3. Before you begin" section. + </para> + </listitem> + + <listitem> + <!-- + 2025-08-04 [e2f24fec8] + --> + <para> + Fix documentation for parameters that are not reflected by reload. (Taiki Koshino) + </para> + <para> + "authentication_timeout" and "memqcache_oiddir" is not reflected by reload. + The documentation is changed to "This parameter can only be set at server start.". + </para> + </listitem> + + <listitem> + <!-- + 2025-07-24 [bc5fa5e7e] + --> + <!-- + 2025-07-23 [1e8963554] + --> + <para> + Unify watchdog leader terms (followup). (Tatsuo Ishii) + </para> + </listitem> + + <listitem> + <!-- + 2025-08-06 [31eee18d7] + --> + <!-- + 2025-07-16 [34b07c2d5] + --> + <para> + Fix example script link. (Taiki Koshino) + </para> + <para> + Modified the sample script in the section "<ulink url="https://www.pgpool.net/docs/46/en/html/example-cluster.html">8.2. Pgpool-II + Watchdog Setup Example</ulink>" + </para> + </listitem> + + <listitem> + <!-- + 2025-06-18 [f4ae9f39e] + 2025-06-18 [7a20dc419] + --> + <para> + Fix load balance explanation missed logical replication mode and Slony mode. (Tatsuo Ishii) + </para> + </listitem> + + <listitem> + <!-- + 2025-06-18 [9d2e4e692] + --> + <para> + Enhance <xref linkend="pcp-node-info"> document. (Bo Peng) + </para> + <para> + Clarify that each <varname>backend_application_nameX</varname> must match the value specified + in the <varname>application_name</varname> of <varname>primary_conninfo</varname> to correctly display + "<varname>replication_state</varname>" and "<varname>replication_sync_state</varname>". + </para> + </listitem> + + <listitem> + <!-- + 2025-06-08 [59f9df005] + --> + <para> + Add section of kernel resources. (Tatsuo Ishii) + </para> + <para> + <productname>Pgpool-II</productname> uses System V shared memory and semaphores. It's better to + describe the requirements in the docs. + </para> + </listitem> + + <listitem> + <!-- + 2025-06-07 [40617fd90] + --> + <para> + Add description for <option>--with-ldap</option> option of configure. (Tatsuo Ishii) + </para> + <para> + It was missed when LDAP support was introduced in v4.2 + </para> + </listitem> + + <listitem> + <!-- + 2025-06-04 [ff60bf930] + --> + <para> + Clarify supported platforms for <productname>Pgpool-II</productname>. (Tatsuo Ishii) + </para> + </listitem> + + <listitem> + <!-- + 2025-06-03 [cc4da5979] + --> + <para> + Enhance <xref linkend="guc-child-life-time"> document. (Tatsuo Ishii) + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>Regression Tests</title> + <itemizedlist> + <listitem> + <!-- + 2025-06-08 [78e45decf] + --> + <para> + Stabilize 029.cert_passphrase regression test. (Tatsuo Ishii) + </para> + <para> + When <varname>ssl_passphrase_command</varname> is not valid, the error message is + typically "bad decrypt" but it seems sometimes "wrong tag". + </para> + </listitem> + </itemizedlist> + </sect2> +</sect1> + <sect1 id="release-4-4-12"> <title>Release 4.4.12</title> <note> diff --git a/doc/src/sgml/release-4.5.sgml b/doc/src/sgml/release-4.5.sgml index 2f3966018..8a9073117 100644 --- a/doc/src/sgml/release-4.5.sgml +++ b/doc/src/sgml/release-4.5.sgml @@ -1,3 +1,604 @@ +<sect1 id="release-4-5-10"> + <title>Release 4.5.10</title> + <note> + <title>Release Date</title> + <simpara>2025-12-15</simpara> + </note> + + <sect2> + <title>Changes</title> + <itemizedlist> + <listitem> + <!-- + 2025-12-08 [5bd10177c] + --> + <para> + Use "grep -E" instead of deprecated "egrep" in pgpool_setup. (Bo Peng) + </para> + <para> + Replace "egrep" with "grep -E" to avoid obsolescence warnings on newer GNU grep versions. + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>Bug fixes</title> + <itemizedlist> + <listitem> + <!-- + 2025-12-08 [8deccc15e] + --> + <para> + Fix buffer overflow error in show pool_status. (Tatsuo Ishii) + </para> + <para> + "show pool_status", "pgpool show" and pcp_pool_status could cause a + buffer overflow error. If backend_flag is set to "ALWAYS_PRIMARY", + pool_flag_to_str(), which is responsible to produce printable format + of backend_flag, wrote data past to the end of static buffer. + </para> + <para> + Problem reported by zam bak and reviewed by Bo Peng. + </para> + <para> + Discussion: <ulink url="https://www.postgresql.org/message-id/20251202.140205.427777414210613577.ishii%40postgresql.org">Re: "buffer overflow detected" when running SHOW POOL_STATUS</ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-12-02 [c8865c703] + --> + <para> + Fix memqcache_stats_start_time shown in "show pool_status". (Tatsuo Ishii) + </para> + <para> + get_config() uses ctime() to generate printable form of + memqcache_stats_start_time. But it did not take into account that + ctime() adds newline at the end of result. As a result, not only the + output of memqcache_stats_start_time was with unnecessary newline but + next row printed empty items. + </para> + <para> + Discussion: <ulink url="https://www.postgresql.org/message-id/20251130.102712.131456481338876013.ishii%40postgresql.org">Re: "buffer overflow detected" when running SHOW POOL_STATUS</ulink> + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>Regression Tests</title> + <itemizedlist> + <listitem> + <!-- + 2025-11-25 [0c45a1e01] + --> + <para> + Test: stabilize 037.failover_session. (Tatsuo Ishii) + </para> + <para> + On some platform (in my case Rocky Linux 10 running on VitualBox) + fails to finish shutdownall after test1. This could be caused by the + failover in the test to fail to restore the signal handler which + should accept shutdown signal from shutdownall. Adding "sleep 5" + before shutdownall seems to mitigate the problem. + </para> + </listitem> + </itemizedlist> + </sect2> +</sect1> + +<sect1 id="release-4-5-9"> + <title>Release 4.5.9</title> + <note> + <title>Release Date</title> + <simpara>2025-11-25</simpara> + </note> + + <sect2> + <title>Changes</title> + <itemizedlist> + <listitem> + <!-- + 2025-11-07 [4fabca331] + --> + <para> + Remove unnecessary <varname>application_name</varname> treatment. (Tatsuo Ishii) + </para> + <para> + A previous commit added a step to set <varname>application_name</varname> when reusing existing connections. + However, this is unnecessary because DISCARD ALL automatically resets <varname>application_name</varname>, + and <function>send_params()</function> already sends all necessary parameter status messages, including <varname>application_name</varname>, to the frontend. + Removing this redundant step also improves performance, particularly for backend nodes that are geographically distant. + </para> + <para> + Discussion: <ulink url="https://github.com/pgpool/pgpool2/issues/130">Severely degraded performance of pgPool in geo-distributed configurations</ulink> + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>Bug fixes</title> + <itemizedlist> + <listitem> + <!-- + 2025-11-16 [b113027dd] + --> + <para> + Fix segfault with <command>CopyOut</command>. (Tatsuo Ishii) + </para> + <para> + When <command>COPY relname TO STDOUT</command> is executed in the extended query + protocol mode, pgpool segfaulted. + </para> + <para> + This problem is reported by <ulink url="https://github.com/tetesh">https://github.com/tetesh</ulink>. + </para> + <para> + Discussion: <ulink url="https://github.com/pgpool/pgpool2/issues/133">datanymizer and pg-pool segmentation fault</ulink> + </para> + </listitem> + <listitem> + <!-- + 2025-10-03 [b84553bf0] + --> + <para> + Prevent watchdog split-brain scenario in some corner cases. (Tatsuo Ishii) + </para> + <para> + Watchdog uses both beacon messages and heartbeat for communication. + If the heartbeat is not yet active, missing beacon messages + for over 30 seconds can cause a split-brain scenario, + where the old leader remains active while a new leader is elected. + This change prevents two leaders from existing simultaneously by revoking the old leader. + When a node detects that it has missed beacon messages from the leader more than twice, + the leader is set to LOST and a new leader election is triggered via set_state(WD_JOINING). + </para> + </listitem> + + <listitem> + <!-- + 2025-10-03 [ef8ccb9e7] + --> + <para> + Prevent FATAL error when non-existing prepared statement is given. (Tatsuo Ishii) + </para> + <para> + Previously, <function>Bind()</function> raised a FATAL error when a non-existing prepared statement was used, unlike PostgreSQL. + This change changes <function>Bind()</function> to check for the statement's existence and send an ERROR message to the frontend if it does not exist. + Note that no log is written, as logging this is not currently possible. + </para> + </listitem> + + <listitem> + <!-- + 2025-09-24 [59a359eef] + --> + <para> + Fix <xref linkend="pg-enc"> not working if both -p and -P are provided. (Tatsuo Ishii) + </para> + <para> + The original report showed that running pg_enc -p -P prompted for a password and encryption key, + but failed if the key was not provided. + </para> + <para> + Discussion: <ulink url="https://www.postgresql.org/message-id/7f18c30b.237.1997555ca11.Coremail.liujy%40highgo.com">pg_enc</ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-09-18 [f20f7041c] + --> + <para> + Fix compiling issue on 32-bit environments. (Tatsuo Ishii) + </para> + <para> + On 32-bit systems, compiling src/parser/snprintf.c fails due to undefined functions <function>isnan()</function> and <function>isinf()</function>, which come from math.h. + This change includes math.h and also reorders the include files for clarity. + The file was originally imported from PostgreSQL, where math.h was already included. + This fix was provided via pull request: https://github.com/pgpool/pgpool2/pull/128 + </para> + <para> + Discussion: <ulink url="https://www.postgresql.org/message-id/20250917.194736.353755422175293639.ishii%40postgresql.org">Compiling issues for 32-bit targets</ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-09-10 [0a6868d40] + --> + <para> + Fix safer directory deletion in Bash in recovery_1st_stage.sample. (Taiki Koshino) + </para> + <para> + Quote variables in rm commands to avoid accidental deletion: + <command>rm -rf "${DEST_NODE_PGDATA}"</command> + + If the variable is empty, rm could delete unexpected files or directories. + </para> + </listitem> + + <listitem> + <!-- + 2025-09-05 [441f338ab] + --> + <para> + Fix the compilation error when building without the <option>--with-memcached</option> option. (Tatsuo Ishii) + </para> + <para> + A compiler error occurred when configuring without <option>--with-memcached</option>. + The issue arose because the compiler could not determine that ptr would only be freed when memcached is enabled. + To fix this, the relevant code block was wrapped with #ifdef USE_MEMCACHED. + </para> + <para> + Problem reported by Bo Peng. + </para> + </listitem> + <listitem> + <!-- + 2025-09-04 [9e0324575] + --> + <para> + Fix query cache lock file handling. (Tatsuo Ishii) + </para> + <para> + The query cache module creates a lock file in <varname>logdir</varname> for concurrency control, + but two bugs existed: the main pgpool process could create a stray "QUERY_CACHE_LOCK_FILE", + and the lock file was not removed on shutdown. This change fixes both issues. + </para> + <para> + Problem reported and analyzed by Bo Peng. + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>Documents</title> + <itemizedlist> + <listitem> + <!-- + 2025-09-17 [1a975b539] + --> + <para> + Update doc about "Setting up PostgreSQL standby" in <ulink url="https://www.pgpool.net/docs/latest/ja/html/example-cluster.html">8.2. Pgpool-II + Watchdog Setup Example</ulink>. (Taiki Koshino) + </para> + <para> + Add a note that when setting up a standby without online recovery, do not write <varname>primary_conninfo</varname> to postgresql.auto.conf. + </para> + <para> + Discussion: <ulink url="https://github.com/pgpool/pgpool2/issues/67">Follow primary command not fixing postgresql.auto.conf</ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-08-22 [5bd535792] + --> + <para> + Fix watchdog_setup manual. (Tatsuo Ishii) + </para> + <para> + It mistakenly stated that heartbeart is not setup in watchdog_setup. + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>Regression Tests</title> + <itemizedlist> + <listitem> + <!-- + 2025-09-30 [3ddbc64f1] + --> + <para> + Adapt 023.ssl_connection to PostgreSQL 18. (Tatsuo Ishii) + </para> + <para> + PostgreSQL 18 heavily changed psql's \conninfo output format, which + made the test fail because the test relies on \conninfo. This change + makes the test script aware the PostgreSQL version to fix the issue. + </para> + </listitem> + + <listitem> + <!-- + 2025-08-29 [b4043e6c3] + --> + <para> + Fix ruby script in 010.rewrite_timestamp. (Tatsuo Ishii) + </para> + <para> + The ruby script used "File.exists", which is said to be obsoleted in + newer version of Ruby. Replace it with "File.exist". + </para> + </listitem> + + <listitem> + <!-- + 2025-08-29 [9c901e60a] + --> + <para> + Tweak timeout in 034 and 075 tests. (Tatsuo Ishii) + </para> + <para> + 034.promote_node and 075.detach_primary_left_down_node set the timeout + 60 seconds for finishing follow primary script. It turns out that + these timeout values are not long enough, and sometimes caused false + errors. So make them from 60 seconds to 120 seconds. + </para> + </listitem> + + <listitem> + <!-- + 2025-08-27 [42b177614] + --> + <para> + Add ssl_ecdh_curve test to 023.ssl_connection. (Tatsuo Ishii) + </para> + <para> + 023.ssl_connection did not cover the test for ssl_ecdh_curve. This + commit tests it using bad ssl_ecdh_curve parameter to see if connection + between frontend and pgpool fails. + </para> + </listitem> + </itemizedlist> + </sect2> +</sect1> + +<sect1 id="release-4-5-8"> + <title>Release 4.5.8</title> + <note> + <title>Release Date</title> + <simpara>2025-08-21</simpara> + </note> + + <sect2> + <title>Bug fixes</title> + <itemizedlist> + <listitem> + <!-- + 2025-07-25 [75d905ff9] + --> + <para> + Fix watchdog to print inappropriate NOTICE message. (Tatsuo Ishii) + </para> + <para> + <function>read_ipc_socket_and_process()</function> printed a notice message every time when + it wrote commands to IPC socket even if it was successful. Fix this to + print the notice message only when the write failed. + + The reason why this bug was not recognized is, the message appears + only when <varname>log_min_messages</varname> is set to notice or higher. + </para> + <para> + Discussion: <ulink url="https://github.com/pgpool/pgpool2/issues/121">pgpool IPC socket connection issue</ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-07-19 [d05de5c73] + --> + <!-- + 2025-07-19 [ed57af34e] + --> + <para> + Fix resource leak while reading startup packet. (Tatsuo Ishii) + </para> + <para> + Fix resource leak in pool_push_pending_data. + </para> + </listitem> + + <listitem> + <!-- + 2025-06-30 [bac455b2f] + --> + <para> + Fix broken scram-sha-256 authentication on big-endian machines. (Tatsuo Ishii) + </para> + <para> + When <literal>scram-sha-256</literal> authentication is performed, a hash function + <function>pg_sha_256_final</function> is used. It was imported from <productname>PostgreSQL</productname> and it uses + preprocessor define WORDS_BIGENDIAN to judge host machine's + endianness. Although WORDS_BIGENDIAN should be defined while + configure, this part was missed when <function>pg_sha_256_final</function> (and others) was + imported from <productname>PostgreSQL</productname>. As a result, <literal>scram-sha-256</literal> worked only in + little endian machines. Fixed the issue by adding + AC_C_BIGENDIAN macro to configure.ac. + </para> + <para> + Problem reported by Christoph Berg and analyzed by pranavkaruvally. + </para> + <para> + Discussion: <ulink url="https://github.com/pgpool/pgpool2/issues/106">4.6.1 fails on big-endian s390x: backend response with kind 'E' when expecting 'R'</ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-06-23 [2721c7b76] + --> + <para> + Fix source code typos. (Bo Peng) + </para> + </listitem> + + <listitem> + <!-- + 2025-06-09 [4305c42d6] + --> + <para> + Fix heartbeat device treatment. (Tatsuo Ishii) + </para> + <para> + While processing <filename>pgpool.conf</filename>, <varname>heartbeat_device</varname> was mistakenly treated + and the first device was ignored. + </para> + <para> + Problem analyzed by Bo Peng. + </para> + </listitem> + + <listitem> + <!-- + 2025-06-02 [06ba7dde4] + --> + <para> + Fix typo in the comments of <filename>pgpool.conf</filename>. (Tatsuo Ishii) + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>Documents</title> + <itemizedlist> + <listitem> + <!-- + 2025-08-15 [a54f5d1ad] + --> + <para> + Enhance "8.3. Replication Mode and Snapshot Isolation Mode Configuration Example" Document. (Taiki Koshino) + </para> + <para> + Updated the link to the example script and the explanation in the "8.3.3. Before you begin" section. + </para> + </listitem> + + <listitem> + <!-- + 2025-08-04 [e2f24fec8] + --> + <para> + Fix documentation for parameters that are not reflected by reload. (Taiki Koshino) + </para> + <para> + "authentication_timeout" and "memqcache_oiddir" is not reflected by reload. + The documentation is changed to "This parameter can only be set at server start.". + </para> + </listitem> + + <listitem> + <!-- + 2025-07-24 [bc5fa5e7e] + --> + <!-- + 2025-07-23 [1e8963554] + --> + <para> + Unify watchdog leader terms (followup). (Tatsuo Ishii) + </para> + </listitem> + + <listitem> + <!-- + 2025-08-06 [31eee18d7] + --> + <!-- + 2025-07-16 [34b07c2d5] + --> + <para> + Fix example script link. (Taiki Koshino) + </para> + <para> + Modified the sample script in the section "<ulink url="https://www.pgpool.net/docs/46/en/html/example-cluster.html">8.2. Pgpool-II + Watchdog Setup Example</ulink>" + </para> + </listitem> + + <listitem> + <!-- + 2025-06-18 [f4ae9f39e] + 2025-06-18 [7a20dc419] + --> + <para> + Fix load balance explanation missed logical replication mode and Slony mode. (Tatsuo Ishii) + </para> + </listitem> + + <listitem> + <!-- + 2025-06-18 [9d2e4e692] + --> + <para> + Enhance <xref linkend="pcp-node-info"> document. (Bo Peng) + </para> + <para> + Clarify that each <varname>backend_application_nameX</varname> must match the value specified + in the <varname>application_name</varname> of <varname>primary_conninfo</varname> to correctly display + "<varname>replication_state</varname>" and "<varname>replication_sync_state</varname>". + </para> + </listitem> + + <listitem> + <!-- + 2025-06-08 [59f9df005] + --> + <para> + Add section of kernel resources. (Tatsuo Ishii) + </para> + <para> + <productname>Pgpool-II</productname> uses System V shared memory and semaphores. It's better to + describe the requirements in the docs. + </para> + </listitem> + + <listitem> + <!-- + 2025-06-07 [40617fd90] + --> + <para> + Add description for <option>--with-ldap</option> option of configure. (Tatsuo Ishii) + </para> + <para> + It was missed when LDAP support was introduced in v4.2 + </para> + </listitem> + + <listitem> + <!-- + 2025-06-04 [ff60bf930] + --> + <para> + Clarify supported platforms for <productname>Pgpool-II</productname>. (Tatsuo Ishii) + </para> + </listitem> + + <listitem> + <!-- + 2025-06-03 [cc4da5979] + --> + <para> + Enhance <xref linkend="guc-child-life-time"> document. (Tatsuo Ishii) + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>Regression Tests</title> + <itemizedlist> + <listitem> + <!-- + 2025-06-08 [78e45decf] + --> + <para> + Stabilize 029.cert_passphrase regression test. (Tatsuo Ishii) + </para> + <para> + When <varname>ssl_passphrase_command</varname> is not valid, the error message is + typically "bad decrypt" but it seems sometimes "wrong tag". + </para> + </listitem> + </itemizedlist> + </sect2> +</sect1> + <sect1 id="release-4-5-7"> <title>Release 4.5.7</title> <note> diff --git a/doc/src/sgml/release-4.6.sgml b/doc/src/sgml/release-4.6.sgml index eb196bfa9..299d9423a 100644 --- a/doc/src/sgml/release-4.6.sgml +++ b/doc/src/sgml/release-4.6.sgml @@ -1,7 +1,783 @@ -<sect1 id="release-4-6-2"> - <title>Release 4.6.2</title> +<sect1 id="release-4-6-5"> + <title>Release 4.6.5</title> + <note> + <title>Release Date</title> + <simpara>2025-12-15</simpara> + </note> + + <sect2> + <title>Changes</title> + <itemizedlist> + <listitem> + <!-- + 2025-12-08 [5bd10177c] + --> + <para> + Use "grep -E" instead of deprecated "egrep" in pgpool_setup. (Bo Peng) + </para> + <para> + Replace "egrep" with "grep -E" to avoid obsolescence warnings on newer GNU grep versions. + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>Bug fixes</title> + <itemizedlist> + <listitem> + <!-- + 2025-12-08 [8deccc15e] + --> + <para> + Fix buffer overflow error in show pool_status. (Tatsuo Ishii) + </para> + <para> + "show pool_status", "pgpool show" and pcp_pool_status could cause a + buffer overflow error. If backend_flag is set to "ALWAYS_PRIMARY", + pool_flag_to_str(), which is responsible to produce printable format + of backend_flag, wrote data past to the end of static buffer. + </para> + <para> + Problem reported by zam bak and reviewed by Bo Peng. + </para> + <para> + Discussion: <ulink url="https://www.postgresql.org/message-id/20251202.140205.427777414210613577.ishii%40postgresql.org">Re: "buffer overflow detected" when running SHOW POOL_STATUS</ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-12-02 [c8865c703] + --> + <para> + Fix memqcache_stats_start_time shown in "show pool_status". (Tatsuo Ishii) + </para> + <para> + get_config() uses ctime() to generate printable form of + memqcache_stats_start_time. But it did not take into account that + ctime() adds newline at the end of result. As a result, not only the + output of memqcache_stats_start_time was with unnecessary newline but + next row printed empty items. + </para> + <para> + Discussion: <ulink url="https://www.postgresql.org/message-id/20251130.102712.131456481338876013.ishii%40postgresql.org">Re: "buffer overflow detected" when running SHOW POOL_STATUS</ulink> + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>Regression Tests</title> + <itemizedlist> + <listitem> + <!-- + 2025-11-25 [0c45a1e01] + --> + <para> + Test: stabilize 037.failover_session. (Tatsuo Ishii) + </para> + <para> + On some platform (in my case Rocky Linux 10 running on VitualBox) + fails to finish shutdownall after test1. This could be caused by the + failover in the test to fail to restore the signal handler which + should accept shutdown signal from shutdownall. Adding "sleep 5" + before shutdownall seems to mitigate the problem. + </para> + </listitem> + </itemizedlist> + </sect2> +</sect1> + +<sect1 id="release-4-6-4"> + <title>Release 4.6.4</title> + <note> + <title>Release Date</title> + <simpara>2025-11-25</simpara> + </note> + + <sect2> + <title>Changes</title> + <itemizedlist> + <listitem> + <!-- + 2025-11-07 [4fabca331] + --> + <para> + Remove unnecessary <varname>application_name</varname> treatment. (Tatsuo Ishii) + </para> + <para> + A previous commit added a step to set <varname>application_name</varname> when reusing existing connections. + However, this is unnecessary because DISCARD ALL automatically resets <varname>application_name</varname>, + and <function>send_params()</function> already sends all necessary parameter status messages, including <varname>application_name</varname>, to the frontend. + Removing this redundant step also improves performance, particularly for backend nodes that are geographically distant. + </para> + <para> + Discussion: <ulink url="https://github.com/pgpool/pgpool2/issues/130">Severely degraded performance of pgPool in geo-distributed configurations</ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-10-09 [f91abf862] + --> + <para> + Make time calculations always long long. (Tatsuo Ishii) + </para> + <para> + Previously, <productname>Pgpool-II</productname> treated time_t as a simple long, which caused compile-time warnings on some systems, + such as OpenBSD, where time_t is __int64. This change upcasts the calculations to long long, + preventing truncation and ensuring pgpool continues to work correctly after Y2038 on 64-bit clean time_t systems. + Additionally, json_get_long_value_for_key has been changed to json_get_llong_value_for_key + with a long long parameter, aligning it with _json_value's int64 type. This improves + integer handling on 32-bit platforms and helps avoid potential integer overflow issues. + </para> + <para> + Problem analyzed by Tatsuo Ishii and Gyorgy Sarvari. + </para> + <para> + Discussion: <ulink url="https://www.pgpool.net/pipermail/pgpool-hackers/2025-May/004584.html">Fix time_t warnings on OpenBSD</ulink> + </para> + <para> + Discussion: <ulink url="https://www.postgresql.org/message-id/20251003.211957.2067537305399895611.ishii%40postgresql.org">Fix time_t warnings on OpenBSD</ulink> + </para> + <para> + Discussion: <ulink url="https://github.com/pgpool/pgpool2/issues/128">fix compiling issues for 32-bit targets</ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-08-31 [dced45a52] + --> + <para> + Allow to compile against gcc 15 (C23). (Tatsuo Ishii) + </para> + <para> + This change includes several fixes to compile <productname>Pgpool-II</productname> on Fedora 42 with gcc 15 (C23). + It updates pool_type.h to use stdbool.h and defines TRUE/FALSE as (bool) 1/0, aligning with C99 standards. + Function pointer arguments were corrected to match their prototypes, + and <function>pool_create_relcache()</function>'s prototype was updated. + Calls to <function>walker()</function> in <function>raw_expression_tree_walker()</function> were adjusted to cast the first argument to (Node *) via the WALK macro. + Note that OpenSSL warnings on Fedora 42 remain and will be addressed in the future. + </para> + <para> + Discussion: <ulink url="https://github.com/pgpool/pgpool2/issues/124">4.6.X build issue against GCC 15</ulink> + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>Bug fixes</title> + <itemizedlist> + <listitem> + <!-- + 2025-11-16 [b113027dd] + --> + <para> + Fix segfault with <command>CopyOut</command>. (Tatsuo Ishii) + </para> + <para> + When <command>COPY relname TO STDOUT</command> is executed in the extended query + protocol mode, pgpool segfaulted. + </para> + <para> + This problem is reported by <ulink url="https://github.com/tetesh">https://github.com/tetesh</ulink>. + </para> + <para> + Discussion: <ulink url="https://github.com/pgpool/pgpool2/issues/133">datanymizer and pg-pool segmentation fault</ulink> + </para> + </listitem> + <listitem> + <!-- + 2025-10-03 [b84553bf0] + --> + <para> + Prevent watchdog split-brain scenario in some corner cases. (Tatsuo Ishii) + </para> + <para> + Watchdog uses both beacon messages and heartbeat for communication. + If the heartbeat is not yet active, missing beacon messages + for over 30 seconds can cause a split-brain scenario, + where the old leader remains active while a new leader is elected. + This change prevents two leaders from existing simultaneously by revoking the old leader. + When a node detects that it has missed beacon messages from the leader more than twice, + the leader is set to LOST and a new leader election is triggered via set_state(WD_JOINING). + </para> + </listitem> + + <listitem> + <!-- + 2025-10-03 [ef8ccb9e7] + --> + <para> + Prevent FATAL error when non-existing prepared statement is given. (Tatsuo Ishii) + </para> + <para> + Previously, <function>Bind()</function> raised a FATAL error when a non-existing prepared statement was used, unlike PostgreSQL. + This change changes <function>Bind()</function> to check for the statement's existence and send an ERROR message to the frontend if it does not exist. + Note that no log is written, as logging this is not currently possible. + </para> + </listitem> + + <listitem> + <!-- + 2025-09-24 [59a359eef] + --> + <para> + Fix <xref linkend="pg-enc"> not working if both -p and -P are provided. (Tatsuo Ishii) + </para> + <para> + The original report showed that running pg_enc -p -P prompted for a password and encryption key, + but failed if the key was not provided. + </para> + <para> + Discussion: <ulink url="https://www.postgresql.org/message-id/7f18c30b.237.1997555ca11.Coremail.liujy%40highgo.com">pg_enc</ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-09-18 [f20f7041c] + --> + <para> + Fix compiling issue on 32-bit environments. (Tatsuo Ishii) + </para> + <para> + On 32-bit systems, compiling src/parser/snprintf.c fails due to undefined functions <function>isnan()</function> and <function>isinf()</function>, which come from math.h. + This change includes math.h and also reorders the include files for clarity. + The file was originally imported from PostgreSQL, where math.h was already included. + This fix was provided via pull request: https://github.com/pgpool/pgpool2/pull/128 + </para> + <para> + Discussion: <ulink url="https://www.postgresql.org/message-id/20250917.194736.353755422175293639.ishii%40postgresql.org">Compiling issues for 32-bit targets</ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-09-10 [0a6868d40] + --> + <para> + Fix safer directory deletion in Bash in recovery_1st_stage.sample. (Taiki Koshino) + </para> + <para> + Quote variables in rm commands to avoid accidental deletion: + <command>rm -rf "${DEST_NODE_PGDATA}"</command> + + If the variable is empty, rm could delete unexpected files or directories. + </para> + </listitem> + + <listitem> + <!-- + 2025-09-05 [1793db95f] + --> + <para> + Fix point less warning in query cache invalidation. (Tatsuo Ishii) + </para> + <para> + When memcached support is disabled, query cache invalidation by query + emitted point less warning. This makes 006.memcached regression test + failed. + </para> + </listitem> + + <listitem> + <!-- + 2025-09-05 [441f338ab] + --> + <para> + Fix the compilation error when building without the <option>--with-memcached</option> option. (Tatsuo Ishii) + </para> + <para> + A compiler error occurred when configuring without <option>--with-memcached</option>. + The issue arose because the compiler could not determine that ptr would only be freed when memcached is enabled. + To fix this, the relevant code block was wrapped with #ifdef USE_MEMCACHED. + </para> + <para> + Problem reported by Bo Peng. + </para> + </listitem> + <listitem> + <!-- + 2025-09-04 [9e0324575] + --> + <para> + Fix query cache lock file handling. (Tatsuo Ishii) + </para> + <para> + The query cache module creates a lock file in <varname>logdir</varname> for concurrency control, + but two bugs existed: the main pgpool process could create a stray "QUERY_CACHE_LOCK_FILE", + and the lock file was not removed on shutdown. This change fixes both issues. + </para> + <para> + Problem reported and analyzed by Bo Peng. + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>Documents</title> + <itemizedlist> + <listitem> + <!-- + 2025-09-17 [1a975b539] + --> + <para> + Update doc about "Setting up PostgreSQL standby" in <ulink url="https://www.pgpool.net/docs/latest/ja/html/example-cluster.html">8.2. Pgpool-II + Watchdog Setup Example</ulink>. (Taiki Koshino) + </para> + <para> + Add a note that when setting up a standby without online recovery, do not write <varname>primary_conninfo</varname> to postgresql.auto.conf. + </para> + <para> + Discussion: <ulink url="https://github.com/pgpool/pgpool2/issues/67">Follow primary command not fixing postgresql.auto.conf</ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-08-22 [5bd535792] + --> + <para> + Fix watchdog_setup manual. (Tatsuo Ishii) + </para> + <para> + It mistakenly stated that heartbeart is not setup in watchdog_setup. + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>Regression Tests</title> + <itemizedlist> + <listitem> + <!-- + 2025-09-30 [3ddbc64f1] + --> + <para> + Adapt 023.ssl_connection to PostgreSQL 18. (Tatsuo Ishii) + </para> + <para> + PostgreSQL 18 heavily changed psql's \conninfo output format, which + made the test fail because the test relies on \conninfo. This change + makes the test script aware the PostgreSQL version to fix the issue. + </para> + </listitem> + + <listitem> + <!-- + 2025-08-31 [3897b7afd] + --> + <para> + Unbreak 039.log_backend_messages. (Tatsuo Ishii) + </para> + <para> + Commit 8ff2b9f6e mistakenly put synchronous commit parameters in + pgpool.conf. Unbreak the test by putting the parameters in + postgresql.conf. Also check if clustering mode is streaming + replication. Because that parameters causes suspends PostgreSQL if + clustering mode is other than streaming replication. + </para> + </listitem> + + <listitem> + <!-- + 2025-08-31 [0f19fc60a] + --> + <para> + Stabilize 039.log_backend_messages test. (Tatsuo Ishii) + </para> + <para> + In the test a query is sent to standby server right after rows are + inserted into primary server. Due to a replication lag, the inserted + rows could not be found on the standby in slower machines. This + change tries to fix the issue by using synchronous replication with + <varname>remote_apply</varname> option. + </para> + </listitem> + + <listitem> + <!-- + 2025-08-29 [b4043e6c3] + --> + <para> + Fix ruby script in 010.rewrite_timestamp. (Tatsuo Ishii) + </para> + <para> + The ruby script used "File.exists", which is said to be obsoleted in + newer version of Ruby. Replace it with "File.exist". + </para> + </listitem> + + <listitem> + <!-- + 2025-08-29 [9c901e60a] + --> + <para> + Tweak timeout in 034 and 075 tests. (Tatsuo Ishii) + </para> + <para> + 034.promote_node and 075.detach_primary_left_down_node set the timeout + 60 seconds for finishing follow primary script. It turns out that + these timeout values are not long enough, and sometimes caused false + errors. So make them from 60 seconds to 120 seconds. + </para> + </listitem> + + <listitem> + <!-- + 2025-08-27 [42b177614] + --> + <para> + Add ssl_ecdh_curve test to 023.ssl_connection. (Tatsuo Ishii) + </para> + <para> + 023.ssl_connection did not cover the test for ssl_ecdh_curve. This + commit tests it using bad ssl_ecdh_curve parameter to see if connection + between frontend and pgpool fails. + </para> + </listitem> + </itemizedlist> + </sect2> +</sect1> + +<sect1 id="release-4-6-3"> + <title>Release 4.6.3</title> <note> <title>Release Date</title> + <simpara>2025-08-21</simpara> + </note> + + <sect2> + <title>Changes</title> + <itemizedlist> + <listitem> + <!-- + 2025-06-13 [ebfd2423c] + --> + <para> + Enhance connecting process to backend. (Tatsuo Ishii) + </para> + <para> + In certain environment (especially k8s), DNS look up is unstable and + connecting to backend process fails. This occurs in call to + <function>getaddrinfo()</function> in <function>connect_inet_domain_socket_by_port()</function>. To enhance the + situation, retry up to 5 times (at each retry, sleep 1 second) if + <function>getaddrinfo()</function> fails with EAI_AGAIN. Note that if + <function>connect_inet_domain_socket_by_port()</function> is called with "retry" argument + is false, the retry will not happen. Health check calls + <function>connect_inet_domain_socket_by_port()</function> with the retry flag to false so + that retrying is controlled health check's own parameters. + </para> + <para> + Discussion: <ulink url="https://github.com/pgpool/pgpool2/issues/104">A single DNS lookup failure will trigger backend failover</ulink> + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>Bug fixes</title> + <itemizedlist> + <listitem> + <!-- + 2025-07-25 [75d905ff9] + --> + <para> + Fix watchdog to print inappropriate NOTICE message. (Tatsuo Ishii) + </para> + <para> + <function>read_ipc_socket_and_process()</function> printed a notice message every time when + it wrote commands to IPC socket even if it was successful. Fix this to + print the notice message only when the write failed. + + The reason why this bug was not recognized is, the message appears + only when <varname>log_min_messages</varname> is set to notice or higher. + </para> + <para> + Discussion: <ulink url="https://github.com/pgpool/pgpool2/issues/121">pgpool IPC socket connection issue</ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-07-19 [d05de5c73] + --> + <!-- + 2025-07-19 [ed57af34e] + --> + <para> + Fix resource leak while reading startup packet. (Tatsuo Ishii) + </para> + <para> + Fix resource leak in pool_push_pending_data. + </para> + </listitem> + + <listitem> + <!-- + 2025-06-30 [bac455b2f] + --> + <para> + Fix broken scram-sha-256 authentication on big-endian machines. (Tatsuo Ishii) + </para> + <para> + When <literal>scram-sha-256</literal> authentication is performed, a hash function + <function>pg_sha_256_final</function> is used. It was imported from <productname>PostgreSQL</productname> and it uses + preprocessor define WORDS_BIGENDIAN to judge host machine's + endianness. Although WORDS_BIGENDIAN should be defined while + configure, this part was missed when <function>pg_sha_256_final</function> (and others) was + imported from <productname>PostgreSQL</productname>. As a result, <literal>scram-sha-256</literal> worked only in + little endian machines. Fixed the issue by adding + AC_C_BIGENDIAN macro to configure.ac. + </para> + <para> + Problem reported by Christoph Berg and analyzed by pranavkaruvally. + </para> + <para> + Discussion: <ulink url="https://github.com/pgpool/pgpool2/issues/106">4.6.1 fails on big-endian s390x: backend response with kind 'E' when expecting 'R'</ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-06-23 [2721c7b76] + --> + <para> + Fix source code typos. (Bo Peng) + </para> + </listitem> + + <listitem> + <!-- + 2025-06-14 [f88b1c18f] + --> + <para> + Fix heartbeat device treatment. (Tatsuo Ishii) + </para> + <para> + Fix <function>wd_create_hb_recv_socket()</function> and <function>wd_create_hb_send_socket()</function> + to pass a null-terminated device name string to setsockopt(SO_BINDTODEVICE) + instead of incorrectly passing a struct ifreq. + </para> + <para> + Discussion: <ulink url="https://www.pgpool.net/pipermail/pgpool-hackers/2025-May/004603.html">[pgpool-hackers: 4602] heartbeat and SO_BINDTODEVICE</ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-06-14 [73bcbd96e] + --> + <para> + Fix resource leak in hearbeat receiver process. (Tatsuo Ishii) + </para> + </listitem> + + <listitem> + <!-- + 2025-06-09 [4305c42d6] + --> + <para> + Fix heartbeat device treatment. (Tatsuo Ishii) + </para> + <para> + While processing <filename>pgpool.conf</filename>, <varname>heartbeat_device</varname> was mistakenly treated + and the first device was ignored. + </para> + <para> + Problem analyzed by Bo Peng. + </para> + </listitem> + + <listitem> + <!-- + 2025-06-05 [b249a118c] + --> + <para> + Fix heartbeat receiver not working. (Tatsuo Ishii) + </para> + <para> + IPv6 support for heartbeat was added in version 4.6, + but the receive process mistakenly bound only to loopback addresses, + preventing reception from other nodes. + Adding the AI_PASSIVE flag to <function>getaddrinfo()</function> fixes this by binding to all network interfaces. + </para> + <para> + Problem analyzed by Bo Peng. + </para> + </listitem> + + <listitem> + <!-- + 2025-06-02 [06ba7dde4] + --> + <para> + Fix typo in the comments of <filename>pgpool.conf</filename>. (Tatsuo Ishii) + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>Documents</title> + <itemizedlist> + <listitem> + <!-- + 2025-08-15 [a54f5d1ad] + --> + <para> + Enhance "8.3. Replication Mode and Snapshot Isolation Mode Configuration Example" Document. (Taiki Koshino) + </para> + <para> + Updated the link to the example script and the explanation in the "8.3.3. Before you begin" section. + </para> + </listitem> + + <listitem> + <!-- + 2025-08-04 [e2f24fec8] + --> + <para> + Fix documentation for parameters that are not reflected by reload. (Taiki Koshino) + </para> + <para> + "authentication_timeout" and "memqcache_oiddir" is not reflected by reload. + The documentation is changed to "This parameter can only be set at server start.". + </para> + </listitem> + + <listitem> + <!-- + 2025-07-24 [bc5fa5e7e] + --> + <!-- + 2025-07-23 [1e8963554] + --> + <para> + Unify watchdog leader terms (followup). (Tatsuo Ishii) + </para> + </listitem> + + <listitem> + <!-- + 2025-08-06 [31eee18d7] + --> + <!-- + 2025-07-16 [34b07c2d5] + --> + <para> + Fix example script link. (Taiki Koshino) + </para> + <para> + Modified the sample script in the section "<ulink url="https://www.pgpool.net/docs/46/en/html/example-cluster.html">8.2. Pgpool-II + Watchdog Setup Example</ulink>" + </para> + </listitem> + + <listitem> + <!-- + 2025-06-18 [f4ae9f39e] + 2025-06-18 [7a20dc419] + --> + <para> + Fix load balance explanation missed logical replication mode and Slony mode. (Tatsuo Ishii) + </para> + </listitem> + + <listitem> + <!-- + 2025-06-18 [9d2e4e692] + --> + <para> + Enhance <xref linkend="pcp-node-info"> document. (Bo Peng) + </para> + <para> + Clarify that each <varname>backend_application_nameX</varname> must match the value specified + in the <varname>application_name</varname> of <varname>primary_conninfo</varname> to correctly display + "<varname>replication_state</varname>" and "<varname>replication_sync_state</varname>". + </para> + </listitem> + + <listitem> + <!-- + 2025-06-08 [59f9df005] + --> + <para> + Add section of kernel resources. (Tatsuo Ishii) + </para> + <para> + <productname>Pgpool-II</productname> uses System V shared memory and semaphores. It's better to + describe the requirements in the docs. + </para> + </listitem> + + <listitem> + <!-- + 2025-06-07 [40617fd90] + --> + <para> + Add description for <option>--with-ldap</option> option of configure. (Tatsuo Ishii) + </para> + <para> + It was missed when LDAP support was introduced in v4.2 + </para> + </listitem> + + <listitem> + <!-- + 2025-06-05 [9ee9eb164] + --> + <para> + Fix command in "8.2. <productname>Pgpool-II</productname> + Watchdog Setup Example" to escape $PGDATA. (Bo Peng) + </para> + </listitem> + + <listitem> + <!-- + 2025-06-04 [ff60bf930] + --> + <para> + Clarify supported platforms for <productname>Pgpool-II</productname>. (Tatsuo Ishii) + </para> + </listitem> + + <listitem> + <!-- + 2025-06-03 [cc4da5979] + --> + <para> + Enhance <xref linkend="guc-child-life-time"> document. (Tatsuo Ishii) + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>Regression Tests</title> + <itemizedlist> + <listitem> + <!-- + 2025-06-08 [78e45decf] + --> + <para> + Stabilize 029.cert_passphrase regression test. (Tatsuo Ishii) + </para> + <para> + When <varname>ssl_passphrase_command</varname> is not valid, the error message is + typically "bad decrypt" but it seems sometimes "wrong tag". + </para> + </listitem> + </itemizedlist> + </sect2> +</sect1> + +<sect1 id="release-4-6-2"> + <title>Release 4.6.2</title> + <note> <title>Release Date</title> <simpara>2025-05-30</simpara> </note> diff --git a/doc/src/sgml/release-4.7.sgml b/doc/src/sgml/release-4.7.sgml new file mode 100644 index 000000000..552111dae --- /dev/null +++ b/doc/src/sgml/release-4.7.sgml @@ -0,0 +1,581 @@ +<sect1 id="release-4-7-0"> + <title>Release 4.7.0</title> + <note> + <title>Release Date</title> + <simpara>2025-12-23</simpara> + </note> + + <sect2> + <title>Overview</title> + <para> + This release of <productname>Pgpool-II</productname> includes several enhancements, + such as the removal of the legacy Slony mode, strengthened security, + enhanced frontend/backend protocol compatibility, and improved operational + transparency. + </para> + + <para> + Major enhancements are as follows: + </para> + + <itemizedlist> + + <listitem> + <para> + Retire Slony mode. + </para> + </listitem> + + <listitem> + <para> + Rename <varname>logdir</varname> parameter to <varname>work_dir</varname>. + </para> + </listitem> + + <listitem> + <para> + Add support for frontend/backend protocol version 3.2. + </para> + </listitem> + + <listitem> + <para> + Enhance security for watchdog and heartbeat receiver. + </para> + </listitem> + + <listitem> + <para> + Add new fields to <command>pcp_proc_info</command> and + <command>show pool_pools</command> to display client information, + and add <function>pgpool_adm_pcp_proc_info</function> extension function. + </para> + </listitem> + + <listitem> + <para> + Make online recovery database configurable. + </para> + </listitem> + + <listitem> + <para> + Import PostgreSQL 18's SQL parser. + </para> + </listitem> + + </itemizedlist> + </sect2> + + <sect2 id="migration-4-7-0"> + <title>Migration to Version 4.7</title> + <itemizedlist> + + <listitem> + <!-- + 2025-10-29 [b402dbc09] + --> + <para> + Retire <literal>Slony</literal> mode. (Tatsuo Ishii) + </para> + <para> + Previously <productname>Pgpool-II</productname> accepted <literal>slony</literal> + mode as one of the <xref linkend="guc-backend-clustering-mode"> to support + <literal>Slony-I</literal> + (https://www.slony.info/). However the latest <literal>Slony-I</literal> was + released in 2022, nearly 3 years ago at this point. And we heard nothing from + users about retiring <literal>Slony</literal> mode. This suggests that there + would be no active <literal>Slony-I</literal> mode users. + So let's drop <literal>Slony-I</literal> support. + </para> + <para> + Discussion: <ulink url="https://www.pgpool.net/pipermail/pgpool-general/2025-May/009489.html">[pgpool-general: 9486] Retiring slony mode</ulink> + </para> + <para> + Discussion: <ulink url="https://www.postgresql.org/message-id/20250722.153130.1007226654125839063.ishii%40postgresql.org">https://www.postgresql.org/message-id/20250722.153130.1007226654125839063.ishii%40postgresql.org</ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-08-15 [579306dbc] + --> + <para> + Change <xref linkend="guc-log-pcp-processes"> default to <literal>off</literal>. (Tatsuo Ishii) + </para> + <para> + Previously <varname>log_pcp_processes</varname> default was <literal>on</literal>, + and it could produce excessive log lines if admins use pcp commands frequently to + monitor pgpool status. Also the log is kind of debugging message, thus it is + best to change its default value to <literal>off</literal>. + </para> + <para> + Discussion: <ulink url="https://www.postgresql.org/message-id/20250815.111100.2261166502134199972.ishii%40postgresql.org">https://www.postgresql.org/message-id/20250815.111100.2261166502134199972.ishii%40postgresql.org</ulink> + </para> + </listitem> + <listitem> + <!-- + 2025-07-17 [3cc3d2d84] + 2025-07-25 [a16b63b8d] + --> + <para> + Make online recovery database configurable. (Bo Peng) + </para> + <para> + A new configuration parameter <xref linkend="guc-recovery-database"> + has been added to allow users to specify the database used for online recovery. + Previously, this value was hardcoded as <literal>template1</literal>. + The default is now set to <literal>postgres</literal>. + </para> + <para> + For users migrating from versions earlier than 4.6, compatibility can be + maintained by setting <varname>recovery_database = 'template1'</varname>, + or by creating the necessary extension for online recovery in the + <literal>postgres</literal> database. + </para> + </listitem> + <listitem> + <!-- + 2025-10-14 [b286ce29a] + 2025-10-14 [25ad5e466] + --> + <para> + Rename <varname>logdir</varname> parameter to <xref linkend="guc-work-dir">. (Taiki Koshino) + </para> + <para> + Previously, the directory for storing <filename>pgpool_status</filename> and + lock files was specified by the <varname>logdir</varname> parameter. + However, since the name <varname>logdir</varname> was misleading, the parameter + has been renamed to <varname>work_dir</varname> for clarity. + The default value is <literal>/tmp</literal>, which is the same as the + previous parameter <varname>logdir</varname>. + </para> + <para> + For backward compatibility, the old <varname>logdir</varname> parameter + is still supported. If the old parameter <varname>logdir</varname> is used, + <productname>Pgpool-II</productname> will set its value to + <varname>work_dir</varname> and throw a warning message. + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>Changes</title> + <itemizedlist> + + <listitem> + <!-- + 2025-10-03 [df2771637] + 2025-10-05 [020ee7084] + --> + <para> + Import PostgreSQL 18 new parser. (Bo Peng) + </para> + <para> + Major changes of PostgreSQL 18 parser include: + </para> + <itemizedlist> + <listitem> + <para> + Allow generated columns to be virtual + </para> + </listitem> + <listitem> + <para> + Add OLD/NEW support to RETURNING in DML queries + </para> + </listitem> + <listitem> + <para> + Addition of various constraints (e.g. WITHOUT OVERLAPS, ENFORCED / NOT ENFORCED) + </para> + </listitem> + <listitem> + <para> + etc. + </para> + </listitem> + </itemizedlist> + </listitem> + + <listitem> + <!-- + 2025-08-22 [94b62a93c] + 2025-09-01 [f15c8a302] + 2025-09-01 [b9e7b4245] + --> + <para> + Restrict watchdog and heartbeat receiver to listen only on configured addresses. (Bo Peng) + </para> + <para> + Previously, both the watchdog and heartbeat receiver processes + listen on all interfaces. + For security reasons, they now listen only on the addresses + specified by <varname>hostname</varname> and <varname>heartbeat_hostname</varname>. + </para> + </listitem> + + <listitem> + <!-- + 2025-08-16 [dfffcddd6] + --> + <para> + Cleanup watchdog source code. (Tatsuo Ishii) + </para> + <para> + <itemizedlist> + <listitem> + <para> + Remove wd_is_upper_ok() from wd_utils.h because there's no actual + definition for it. + </para> + </listitem> + <listitem> + <para> + Make wd_get_ping_result() and wd_issue_ping_command() static. It's + only used in wd_ping.c. + </para> + </listitem> + </itemizedlist> + </para> + </listitem> + + <listitem> + <!-- + 2025-08-13 [a85b848cc] + --> + <para> + Emit warning if life check has not started yet. (Tatsuo Ishii) + </para> + <para> + Currently lifecheck emits a log only when life check becomes + ready. This is inconvenient for admins since they need to keep on + watching log file until life check is ready. This commit makes the + life check process to emit additional warnings periodically until life + check has started. The interval of the warnings is wd_interval * 10 + seconds. However for the first time at lifecheck starting, no warning + is emitted since it is likely that lifecheck is not ready at that + point. + </para> + </listitem> + + <listitem> + <!-- + 2025-07-09 [766e73811] + 2025-07-15 [523b3d94d] + --> + <para> + Add support for frontend/backend protocol 3.2. (Tatsuo Ishii) + </para> + <itemizedlist> + <listitem> + <para> + Implement NegotiateProtocolVersion message. + </para> + <para> + Implementing the message is necessary when frontend requests the + protocol version 3.2 (i.e. PostgreSQL 18+ or compatible clients), + while backend still only supports 3.0 (i.e. backend is PostgreSQL 17 + or before). + </para> + <para> + This commit handles the message so that the message is forwarded from + backend to frontend when there's no connection cache exists. + </para> + <para> + If connection cache exists, pgpool sends the message, which has been + saved at the time when the connection cache was created, to frontend. + </para> + <para> + Discussion: <ulink url="https://www.postgresql.org/message-id/20250708.112133.1324153277751075866.ishii%40postgresql.org">https://www.postgresql.org/message-id/20250708.112133.1324153277751075866.ishii%40postgresql.org</ulink> + </para> + </listitem> + + <listitem> + <para> + Implement protocol version 3.2 BackendKeyData and query cancel message. + </para> + <para> + Starting from PostgreSQL 18, frontend/backend protocol has been + changed to 3.2. In the changes the BackendKeyData and query cancel + message are modified to allow variable length cancel key. + </para> + <para> + This commit implements the changes and now we can connect to + PostgreSQL frontend and backend using 3.2 protocol. + </para> + <programlisting> +Example session is: +PGMAXPROTOCOLVERSION="3.2" psql -p 11000 test + </programlisting> + <para> + Discussion: <ulink url="https://www.postgresql.org/message-id/20250714.155710.1706961744888449986.ishii%40postgresql.org">https://www.postgresql.org/message-id/20250714.155710.1706961744888449986.ishii%40postgresql.org</ulink> + </para> + </listitem> + </itemizedlist> + </listitem> + + <listitem> + <!-- + 2025-06-24 [706ca859c] + 2025-07-15 [0e80ac4e5] + 2025-07-15 [f4cfd6188] + --> + <para> + Add <xref linkend="pgpool-adm-pcp-proc-info">. (Tatsuo Ishii) + </para> + <para> + This commit adds new pgpool_adm extension function: + pcp_proc_info. Also add new fields: client_host, client_port and SQL + statement to pcp_proc_info and "show pool_pools". With these additions + now it is possible to track the relationship among clients of pgpool, + pgpool itself and PostgreSQL. + </para> + <para> + Moreover the commit allows to know what commands (statements) are last + executed by using pcp_proc_info. Previously it was not possible unless + looking into the pgpool log. + </para> + <para> + lipcp.so version is bumped from 2.0.0 to 3.0.0. + </para> + </listitem> + + <listitem> + <!-- + 2025-06-14 [9fc568f00] + --> + <para> + Enhance lifecheck log. (Tatsuo Ishii) + </para> + <para> + Previously when wd_lifecheck_method = 'query', life checking prints + SQL without application name if "%a" is specified in + log_line_prefix. This commit add application_name "lifecheck_ping" to + make the log looks better. Since this changes user visible behavior, + I do not apply this to stable branches. + </para> + <para> + Discussion: <ulink url="https://www.pgpool.net/pipermail/pgpool-hackers/2025-June/004604.html">[pgpool-hackers: 4603] life check log is not nicea</ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-06-05 [1a68c6eb0] + --> + <para> + Replace random() with pg_prng random function. (Martijn van Duren, Tatsuo Ishii) + </para> + <para> + Previously we used random() for choosing load balancing node. However + PostgreSQL has better random number generator: pg_prng.c. This commit + imports the file and use pg_prng_double() to generate random number in + range [0.0, 1.0). The seed is generated using pg_strong_random(). + </para> + <para> + Discussion: <ulink url="https://www.pgpool.net/pipermail/pgpool-hackers/2025-May/004589.html">[pgpool-hackers: 4588] Shuffle random functions and use better random numbers</ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-06-03 [cea80281d] + 2025-06-04 [e058c9334] + --> + <para> + Retry bind on watchdog receive socket. (Tatsuo Ishii) + </para> + <para> + Occasionally 028.watchdog_enable_consensus_with_half_votes times out + due to failure on binding watchdog receive socket. This commit tries + to mitigate the issue by retrying bind. Currently the retry is + performed up to 5 times and each retry is with 1 second sleep. + </para> + </listitem> + + <listitem> + <!-- + 2025-05-28 [ffd3a5224] + --> + <para> + Import likely/unlikely from PostgreSQL. (Tatsuo Ishii) + </para> + <para> + These macros are not only useful to enhance performance (if correctly + used) but make porting codes from PostgreSQL to pgpool easier since + the macros occasionally used in the code. + </para> + <para> + Discussion: <ulink url="https://www.pgpool.net/pipermail/pgpool-hackers/2025-May/004600.html">[pgpool-hackers: 4599] Porting likely/unlikely</ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-05-20 [7abdd48ec] + 2025-05-20 [e14feea1d] + --> + <para> + Replace PostmasterRandom() with pg_strong_random(). (Tatsuo Ishii) + </para> + <para> + Our PostmasterRandmon() was imported from PostgreSQL long time ago (in + 2016). In the same year PostgreSQL replaced PostmasterRandmon() with + pg_strong_random()(src/port/pg_strong_random.c). This commit follows + it. + </para> + <para> + Discussion: <ulink url="https://www.pgpool.net/pipermail/pgpool-hackers/2025-May/004589.html">[pgpool-hackers: 4588] Shuffle random functions and use better random numbers</ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-05-08 [5f7d06d87] + --> + <para> + Fall back to prompting for password if reading from <filename>.pcppass</filename> file fails. (Bo Peng) + </para> + <para> + If reading password from <filename>.pcppass</filename> file fails, + it should fall back to prompting the user for input, + similar to how PostgreSQL handles <filename>.pgpass</filename>. + </para> + <para> + This commit also changes the following messages to be displayed + without requiring the <option>-d</option> option: + <programlisting> +WARNING: password file \"%s\" is not a plain file +WARNING: password file \"%s\" has group or world access; permissions should be u=rw (0600) or less + </programlisting> + </para> + <para> + Discussion: <ulink url="https://www.pgpool.net/pipermail/pgpool-hackers/2025-May/004590.html">[pgpool-hackers: 4589] If reading password from .pcppass file fails, try to read it from prompt.</ulink> + </para> + </listitem> + + <listitem> + <!-- + 2025-06-14 [bbe93d86b] + --> + <para> + Remove or downgrade inappropriate log messages at pgpool startup. (Tatsuo Ishii) + </para> + </listitem> + + <listitem> + <!-- + 2025-05-02 [5c41d5338] + --> + <para> + Add major version information to the configuration file. (Bo Peng) + </para> + </listitem> + + </itemizedlist> + </sect2> + + <sect2> + <title>Documents</title> + <itemizedlist> + <listitem> + <!-- + 2025-07-15 [2a236be3e] + --> + <para> + Fix documentation for <literal>enum</literal> parameters reported as <literal>strings</literal>. (Taiki Koshino) + </para> + <para> + Fix documentations for 6 parameters: + <programlisting> +log_standby_delay +log_backend_messages +wd_lifecheck_method +memqcache_method +disable_load_balance_on_write +backend_clustering_mode + </programlisting> + </para> + </listitem> + <listitem> + <!-- + 2025-05-09 [174772d6c] + --> + <para> + Enhance query cache doc. (Tatsuo Ishii) + </para> + <para> + Pgpool refuses to cache a query calling functions returning + <literal>TIMESTAMP WITH TIMEZONE</literal>, <literal>TIME WITH TIMEZONE</literal>. + If there are multiple functions having same name and one of them returns + <literal>TIMESTAMP WITH TIMEZONE</literal>, <literal>TIME WITH TIMEZONE</literal>, + pgpool refuses to cache even if one of them does not + return the data types. So add a note on this along with workaround. + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>Test Tools</title> + <itemizedlist> + <listitem> + <!-- + 2025-08-22 [534e04a0e] + 2025-08-22 [384c17eab] + --> + <para> + Allow to specify VIP in <xref linkend="watchdog-setup">. (Tatsuo Ishii) + </para> + <para> + This commit allows to specify VIP parameter (<varname>delegate_ip</varname>) + in <command>watchdog_setup</command> using new option <option>-vip [ip]</option>. + If ip is omitted, <literal>127.0.0.1</literal> is assumed. Even if vip option + is specified, pgpool will not actually set the VIP to the system: + <xref linkend="guc-if-up-cmd">, <xref linkend="guc-if-down-cmd"> are + just set to echo command and do nothing except emit a log. This option + is intended to trace the action of <productname>Pgpool-II</productname> + regarding VIP handling. + </para> + <para> + Discussion: <ulink url="https://www.postgresql.org/message-id/20250820.151646.1640218512808280876.ishii%40postgresql.org">https://www.postgresql.org/message-id/20250820.151646.1640218512808280876.ishii%40postgresql.org</ulink> + </para> + </listitem> + </itemizedlist> + </sect2> + + <sect2> + <title>Regression Tests</title> + <itemizedlist> + <listitem> + <!-- + 2025-06-25 [04e09df17] + 2025-06-27 [b76c6876d] + --> + <para> + Fix 038.pcp_commands regression test. (Tatsuo Ishii) + </para> + <para> + The result of the test showed local host IP. Although the IP can be + either IPv4 or IPv6, the test script hadn't considered it. To fix + this, now test.sh converts IPv4 and IPv6 IP to "localhost". + </para> + </listitem> + + <listitem> + <!-- + 2025-06-08 [e30bb2ead] + --> + <para> + Stabilize 029.cert_passphrase regression test. (Tatsuo Ishii) + </para> + <para> + When ssl_passphrase_command is not valid, the error message is + typically "bad decrypt" but it seems sometimes "wrong tag". + </para> + </listitem> + </itemizedlist> + </sect2> +</sect1> diff --git a/doc/src/sgml/release.sgml b/doc/src/sgml/release.sgml index f0bb3bb48..f2c6d2f6c 100644 --- a/doc/src/sgml/release.sgml +++ b/doc/src/sgml/release.sgml @@ -72,6 +72,7 @@ For new features, add links to the documentation sections. subsets can easily be copied into back branches. --> + &release-4.7; &release-4.6; &release-4.5; &release-4.4; diff --git a/doc/src/sgml/restrictions.sgml b/doc/src/sgml/restrictions.sgml index f1f5eb687..c8444b5c4 100644 --- a/doc/src/sgml/restrictions.sgml +++ b/doc/src/sgml/restrictions.sgml @@ -124,7 +124,7 @@ supported, however. </para> <para> - In other mode, including Slony mode, large + In other mode, large objects are not supported. </para> </listitem> diff --git a/doc/src/sgml/runtime.sgml b/doc/src/sgml/runtime.sgml index 0fe7ecabc..077b0e014 100644 --- a/doc/src/sgml/runtime.sgml +++ b/doc/src/sgml/runtime.sgml @@ -168,10 +168,6 @@ <entry><literal>logical_replication</literal> </entry> </row> <row> - <entry>Slony mode</entry> - <entry><literal>slony</literal></entry> - </row> - <row> <entry>Snapshot isolation mode</entry> <entry><literal>snapshot_isolation</literal></entry> </row> @@ -221,7 +217,7 @@ <para> There are six different <link linkend="guc-backend-clustering-mode">clustering modes</link> in <productname>Pgpool-II</>: streaming replication mode, logical - replication mode, main replica mode (slony mode), native + replication mode, native replication mode, raw mode and snapshot isolation mode. In any mode, <productname>Pgpool-II</> provides connection pooling, and automatic fail over. Online recovery can be used only with @@ -306,19 +302,6 @@ default_transaction_isolation = 'repeatable read' </para> <para> - The <firstterm>main replica mode</firstterm> (slony mode) - can be used with <productname>PostgreSQL</> servers - operating <productname>Slony</>. In this - mode, <productname>Slony</>/<productname>PostgreSQL</> is - responsible for synchronizing - databases. Since <productname>Slony-I</> is being obsoleted by - streaming replication, we do not recommend to use this mode - unless you have specific reason to - use <productname>Slony</>. Load balancing is possible in the - mode. - </para> - - <para> In the <firstterm>raw mode</firstterm>, <productname>Pgpool-II</> does not care about the database synchronization. It's user's responsibility to make diff --git a/doc/src/sgml/version.sgml b/doc/src/sgml/version.sgml index a2ce83556..001c98a34 100644 --- a/doc/src/sgml/version.sgml +++ b/doc/src/sgml/version.sgml @@ -1 +1 @@ -<!ENTITY version "4.7devel"> +<!ENTITY version "4.8devel"> diff --git a/doc/src/sgml/watchdog.sgml b/doc/src/sgml/watchdog.sgml index 86812ce32..6c8074984 100644 --- a/doc/src/sgml/watchdog.sgml +++ b/doc/src/sgml/watchdog.sgml @@ -283,7 +283,7 @@ pgpool_port2 = 9999 <productname>Pgpool-II</productname> that is connected from client servers (application servers etc.). When a <productname>Pgpool-II</productname> is switched from standby to - active, the <productname>Pgpool-II</productname> takes over this + leader, the <productname>Pgpool-II</productname> takes over this VIP. <emphasis>VIP will not be brought up in case the quorum does not exist</emphasis>. Default is <literal>''</literal>(empty): which means virtual IP will never be brought up. @@ -449,7 +449,7 @@ pgpool_port2 = 9999 <para> Configuration about behavior when <productname>Pgpool-II</productname> - escalates to active (virtual IP holder) + escalates to leader (virtual IP holder) </para> <variablelist> @@ -463,8 +463,8 @@ pgpool_port2 = 9999 <listitem> <para> When set to on, watchdog clears all the query cache in the shared memory - when pgpool-II escalates to active. This prevents the new active <productname>Pgpool-II</productname> - from using old query caches inconsistent to the old active. + when pgpool-II escalates to leader. This prevents the new leader <productname>Pgpool-II</productname> + from using old query caches inconsistent to the old leader. </para> <para> Default is on. @@ -626,7 +626,7 @@ pgpool_port2 = 9999 <para> From <productname>Pgpool-II </productname><emphasis>V4.1</emphasis> onward, if the watchdog-leader node fails to build the consensus for primary backend node failover and the primary backend node gets into a - quarantine state, then it resigns from its leader/coordinator responsibilities and lowers its wd_priority + quarantine state, then it resigns from its leader responsibilities and lowers its wd_priority for next leader election and let the cluster elect some different new leader. <note> <para> diff --git a/src/config/pool_config.l b/src/config/pool_config.l index b16130293..a75cedb16 100644 --- a/src/config/pool_config.l +++ b/src/config/pool_config.l @@ -6,7 +6,7 @@ * pgpool: a language independent connection pool server for PostgreSQL * written by Tatsuo Ishii * - * Copyright (c) 2003-2024 PgPool Global Development Group + * Copyright (c) 2003-2025 PgPool Global Development Group * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby @@ -654,7 +654,7 @@ char *pool_flag_to_str(unsigned short flag) if (*buf == '\0') snprintf(buf, sizeof(buf), "ALWAYS_PRIMARY"); else - snprintf(buf+strlen(buf), sizeof(buf), "|ALWAYS_PRIMARY"); + strncat(buf, "|ALWAYS_PRIMARY", 16); } return buf; diff --git a/src/config/pool_config_variables.c b/src/config/pool_config_variables.c index 31f42caa9..2c5b9c86d 100644 --- a/src/config/pool_config_variables.c +++ b/src/config/pool_config_variables.c @@ -4,7 +4,7 @@ * pgpool: a language independent connection pool server for PostgreSQL * written by Tatsuo Ishii * - * Copyright (c) 2003-2024 PgPool Global Development Group + * Copyright (c) 2003-2025 PgPool Global Development Group * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby @@ -142,6 +142,7 @@ static bool BackendSlotEmptyCheckFunc(int index); /*variable custom assign functions */ static bool FailOverOnBackendErrorAssignMessage(ConfigContext scontext, bool newval, int elevel); static bool DelegateIPAssignMessage(ConfigContext scontext, char *newval, int elevel); +static bool LogDirAssignMessage(ConfigContext scontext, char *newval, int elevel); static bool BackendPortAssignFunc(ConfigContext context, int newval, int index, int elevel); static bool BackendHostAssignFunc(ConfigContext context, char *newval, int index, int elevel); static bool BackendDataDirAssignFunc(ConfigContext context, char *newval, int index, int elevel); @@ -231,7 +232,6 @@ static const struct config_enum_entry backend_clustering_mode_options[] = { {"streaming_replication", CM_STREAMING_REPLICATION, false}, {"native_replication", CM_NATIVE_REPLICATION, false}, {"logical_replication", CM_LOGICAL_REPLICATION, false}, - {"slony", CM_SLONY, false}, {"raw", CM_RAW, false}, {"snapshot_isolation", CM_SNAPSHOT_ISOLATION, false}, {NULL, 0, false} @@ -480,7 +480,7 @@ static struct config_bool ConfigureNamesBool[] = CONFIG_VAR_TYPE_BOOL, false, 0 }, &g_pool_config.log_pcp_processes, - true, + false, NULL, NULL, NULL }, @@ -1353,13 +1353,24 @@ static struct config_string ConfigureNamesString[] = { {"logdir", CFGCXT_INIT, LOGGING_CONFIG, - "PgPool status file logging directory.", + "Old config parameter for work_dir.", + CONFIG_VAR_TYPE_STRING, false, VAR_HIDDEN_IN_SHOW_ALL + }, + NULL, + "", + LogDirAssignMessage, NULL, NULL, NULL + }, + + { + {"work_dir", CFGCXT_INIT, LOGGING_CONFIG, + "directory to create pgpool_status and lock files.", CONFIG_VAR_TYPE_STRING, false, 0 }, - &g_pool_config.logdir, + &g_pool_config.work_dir, DEFAULT_LOGDIR, NULL, NULL, NULL, NULL }, + { {"log_directory", CFGCXT_RELOAD, LOGGING_CONFIG, "directory where log files are written.", @@ -4556,7 +4567,7 @@ BackendFlagsShowFunc(int index) if (*buffer == '\0') snprintf(buffer, sizeof(buffer), "ALWAYS_PRIMARY"); else - snprintf(buffer + strlen(buffer), sizeof(buffer), "|ALWAYS_PRIMARY"); + strncat(buffer, "|ALWAYS_PRIMARY", 16); } return buffer; } @@ -4826,7 +4837,32 @@ DelegateIPAssignMessage(ConfigContext scontext, char *newval, int elevel) ereport(WARNING, (errmsg("delegate_IP is changed to delegate_ip"), errdetail("if delegate_IP is specified, the value will be set to delegate_ip"))); - g_pool_config.delegate_ip = newval; + if (g_pool_config.delegate_ip) + pfree(g_pool_config.delegate_ip); + if (newval) + g_pool_config.delegate_ip = pstrdup(newval); + else + g_pool_config.delegate_ip = NULL; + return true; +} + +/* + * Throws warning for if someone uses the removed logdir + * configuration parameter and set the value to work_dir + */ +static bool +LogDirAssignMessage(ConfigContext scontext, char *newval, int elevel) +{ + if (scontext != CFGCXT_BOOT) + ereport(WARNING, + (errmsg("logdir is changed to work_dir"), + errdetail("if logdir is specified, the value will be set to work_dir"))); + if (g_pool_config.work_dir) + pfree(g_pool_config.work_dir); + if (newval) + g_pool_config.work_dir = pstrdup(newval); + else + g_pool_config.work_dir = NULL; return true; } @@ -5335,14 +5371,17 @@ SetPgpoolNodeId(int elevel) static bool SetHBDestIfFunc(int elevel) { - int idx = 0; + int dest_if_idx = 0; + int local_if_idx = 0; char **addrs; char **if_names; int i, j, + k, n_addr, n_if_name; + g_pool_config.num_hb_local_if = 0; g_pool_config.num_hb_dest_if = 0; if (g_pool_config.wd_lifecheck_method != LIFECHECK_BY_HB) @@ -5352,22 +5391,14 @@ SetHBDestIfFunc(int elevel) /* * g_pool_config.hb_ifs is the information for sending/receiving heartbeat - * for all nodes specified in pgpool.conf. If it is local pgpool node - * information, set dest_port to g_pool_config.wd_heartbeat_port and - * ignore addr and if_name. g_pool_config.hb_dest_if is the heartbeat + * for all nodes specified in pgpool.conf. g_pool_config.hb_local_if is + * the local node information. g_pool_config.hb_dest_if is the heartbeat * destination information. */ for (i = 0; i < WD_MAX_IF_NUM; i++) { if (g_pool_config.hb_ifs[i].dest_port > 0) { - /* Ignore local pgpool node */ - if (i == g_pool_config.pgpool_node_id) - { - g_pool_config.wd_heartbeat_port = g_pool_config.hb_ifs[i].dest_port; - continue; - } - WdHbIf *hbNodeInfo = &g_pool_config.hb_ifs[i]; addrs = get_list_from_string(hbNodeInfo->addr, ";", &n_addr); @@ -5375,7 +5406,10 @@ SetHBDestIfFunc(int elevel) if (!addrs || n_addr < 0) { - g_pool_config.hb_dest_if[idx].addr[0] = '\0'; + if (i == g_pool_config.pgpool_node_id) + g_pool_config.hb_local_if[local_if_idx].addr[0] = '\0'; + else + g_pool_config.hb_dest_if[dest_if_idx].addr[0] = '\0'; if (addrs) pfree(addrs); @@ -5391,19 +5425,46 @@ SetHBDestIfFunc(int elevel) for (j = 0; j < n_addr; j++) { - strlcpy(g_pool_config.hb_dest_if[idx].addr, addrs[j], WD_MAX_HOST_NAMELEN - 1); - g_pool_config.hb_dest_if[idx].dest_port = hbNodeInfo->dest_port; - if (n_if_name > j) + /* local pgpool node */ + if (i == g_pool_config.pgpool_node_id) { - strlcpy(g_pool_config.hb_dest_if[idx].if_name, if_names[j], WD_MAX_IF_NAME_LEN - 1); - pfree(if_names[j]); + for (k = 0; k < g_pool_config.wd_nodes.num_wd - 1; k++) + { + strlcpy(g_pool_config.hb_local_if[local_if_idx].addr, addrs[j], WD_MAX_HOST_NAMELEN - 1); + g_pool_config.hb_local_if[local_if_idx].dest_port = hbNodeInfo->dest_port; + + if (n_if_name > j) + strlcpy(g_pool_config.hb_local_if[local_if_idx].if_name, if_names[j], WD_MAX_IF_NAME_LEN - 1); + else + g_pool_config.hb_local_if[local_if_idx].if_name[0] = '\0'; + + g_pool_config.num_hb_local_if = local_if_idx + 1; + local_if_idx++; + } + + if (n_if_name > j) + pfree(if_names[j]); + + pfree(addrs[j]); + } + /* destination pgpool node */ else - g_pool_config.hb_dest_if[idx].if_name[0] = '\0'; + { + strlcpy(g_pool_config.hb_dest_if[dest_if_idx].addr, addrs[j], WD_MAX_HOST_NAMELEN - 1); + g_pool_config.hb_dest_if[dest_if_idx].dest_port = hbNodeInfo->dest_port; + if (n_if_name > j) + { + strlcpy(g_pool_config.hb_dest_if[dest_if_idx].if_name, if_names[j], WD_MAX_IF_NAME_LEN - 1); + pfree(if_names[j]); + } + else + g_pool_config.hb_dest_if[dest_if_idx].if_name[0] = '\0'; - g_pool_config.num_hb_dest_if = idx + 1; - idx++; - pfree(addrs[j]); + g_pool_config.num_hb_dest_if = dest_if_idx + 1; + dest_if_idx++; + pfree(addrs[j]); + } } if (addrs) diff --git a/src/context/pool_query_context.c b/src/context/pool_query_context.c index a4800d94b..1a13168c6 100644 --- a/src/context/pool_query_context.c +++ b/src/context/pool_query_context.c @@ -1983,7 +1983,7 @@ dml_adaptive(Node *node, char *query) /* * Decide the backend node to be sent in streaming replication mode, logical - * replication mode and slony mode. Called by pool_where_to_send. + * replication mode. Called by pool_where_to_send. */ static void where_to_send_main_replica(POOL_QUERY_CONTEXT *query_context, char *query, Node *node) diff --git a/src/include/main/health_check.h b/src/include/main/health_check.h index 29f59b7fd..f8369aa1e 100644 --- a/src/include/main/health_check.h +++ b/src/include/main/health_check.h @@ -3,7 +3,7 @@ * pgpool: a language independent connection pool server for PostgreSQL * written by Tatsuo Ishii * - * Copyright (c) 2003-2020 PgPool Global Development Group + * Copyright (c) 2003-2025 PgPool Global Development Group * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby @@ -53,7 +53,7 @@ typedef struct extern volatile POOL_HEALTH_CHECK_STATISTICS *health_check_stats; /* health check stats * area in shared memory */ -extern void do_health_check_child(int *node_id); +extern void do_health_check_child(void *params); extern size_t health_check_stats_shared_memory_size(void); extern void health_check_stats_init(POOL_HEALTH_CHECK_STATISTICS *addr); diff --git a/src/include/parser/gramparse.h b/src/include/parser/gramparse.h index 9571a5ee3..c375cb860 100644 --- a/src/include/parser/gramparse.h +++ b/src/include/parser/gramparse.h @@ -8,8 +8,8 @@ * Definitions that are needed outside the core parser should be in parser.h. * * - * Portions Copyright (c) 2003-2024, PgPool Global Development Group - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2003-2025, PgPool Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/parser/gramparse.h diff --git a/src/include/parser/keywords.h b/src/include/parser/keywords.h index 9a989763f..a56380499 100644 --- a/src/include/parser/keywords.h +++ b/src/include/parser/keywords.h @@ -4,8 +4,8 @@ * PostgreSQL's list of SQL keywords * * - * Portions Copyright (c) 2003-2024, PgPool Global Development Group - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2003-2025, PgPool Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/common/keywords.h diff --git a/src/include/parser/kwlist.h b/src/include/parser/kwlist.h index bbf22fb52..098738447 100644 --- a/src/include/parser/kwlist.h +++ b/src/include/parser/kwlist.h @@ -7,8 +7,8 @@ * by the PG_KEYWORD macro, which is not defined in this file; it can * be defined by the caller for special purposes. * - * Portions Copyright (c) 2003-2024, PgPool Global Development Group - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2003-2025, PgPool Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -154,6 +154,7 @@ PG_KEYWORD("enable", ENABLE_P, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("encoding", ENCODING, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("encrypted", ENCRYPTED, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("end", END_P, RESERVED_KEYWORD, BARE_LABEL) +PG_KEYWORD("enforced", ENFORCED, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("enum", ENUM_P, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("error", ERROR_P, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("escape", ESCAPE, UNRESERVED_KEYWORD, BARE_LABEL) @@ -308,6 +309,7 @@ PG_KEYWORD("nullif", NULLIF, COL_NAME_KEYWORD, BARE_LABEL) PG_KEYWORD("nulls", NULLS_P, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("numeric", NUMERIC, COL_NAME_KEYWORD, BARE_LABEL) PG_KEYWORD("object", OBJECT_P, UNRESERVED_KEYWORD, BARE_LABEL) +PG_KEYWORD("objects", OBJECTS_P, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("of", OF, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("off", OFF, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("offset", OFFSET, RESERVED_KEYWORD, AS_LABEL) @@ -339,6 +341,7 @@ PG_KEYWORD("partition", PARTITION, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("passing", PASSING, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("password", PASSWORD, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("path", PATH, UNRESERVED_KEYWORD, BARE_LABEL) +PG_KEYWORD("period", PERIOD, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("pgpool", PGPOOL, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("placing", PLACING, RESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("plan", PLAN, UNRESERVED_KEYWORD, BARE_LABEL) @@ -364,7 +367,6 @@ PG_KEYWORD("range", RANGE, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("read", READ, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("real", REAL, COL_NAME_KEYWORD, BARE_LABEL) PG_KEYWORD("reassign", REASSIGN, UNRESERVED_KEYWORD, BARE_LABEL) -PG_KEYWORD("recheck", RECHECK, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("recursive", RECURSIVE, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("ref", REF_P, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("references", REFERENCES, RESERVED_KEYWORD, BARE_LABEL) @@ -492,6 +494,7 @@ PG_KEYWORD("verbose", VERBOSE, TYPE_FUNC_NAME_KEYWORD, BARE_LABEL) PG_KEYWORD("version", VERSION_P, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("view", VIEW, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("views", VIEWS, UNRESERVED_KEYWORD, BARE_LABEL) +PG_KEYWORD("virtual", VIRTUAL, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("volatile", VOLATILE, UNRESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("when", WHEN, RESERVED_KEYWORD, BARE_LABEL) PG_KEYWORD("where", WHERE, RESERVED_KEYWORD, AS_LABEL) diff --git a/src/include/parser/kwlist_d.h b/src/include/parser/kwlist_d.h index 7c917a89a..023a3432a 100644 --- a/src/include/parser/kwlist_d.h +++ b/src/include/parser/kwlist_d.h @@ -3,7 +3,7 @@ * kwlist_d.h * List of keywords represented as a ScanKeywordList. * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * NOTES @@ -150,6 +150,7 @@ static const char ScanKeywords_kw_string[] = "encoding\0" "encrypted\0" "end\0" + "enforced\0" "enum\0" "error\0" "escape\0" @@ -304,6 +305,7 @@ static const char ScanKeywords_kw_string[] = "nulls\0" "numeric\0" "object\0" + "objects\0" "of\0" "off\0" "offset\0" @@ -335,6 +337,7 @@ static const char ScanKeywords_kw_string[] = "passing\0" "password\0" "path\0" + "period\0" "pgpool\0" "placing\0" "plan\0" @@ -360,7 +363,6 @@ static const char ScanKeywords_kw_string[] = "read\0" "real\0" "reassign\0" - "recheck\0" "recursive\0" "ref\0" "references\0" @@ -488,6 +490,7 @@ static const char ScanKeywords_kw_string[] = "version\0" "view\0" "views\0" + "virtual\0" "volatile\0" "when\0" "where\0" @@ -645,515 +648,518 @@ static const uint16 ScanKeywords_kw_offsets[] = { 1003, 1013, 1017, - 1022, - 1028, - 1035, - 1041, - 1048, - 1056, - 1066, - 1076, - 1084, - 1091, - 1099, - 1110, - 1120, + 1026, + 1031, + 1037, + 1044, + 1050, + 1057, + 1065, + 1075, + 1085, + 1093, + 1100, + 1108, + 1119, 1129, - 1137, - 1143, - 1150, - 1156, - 1163, + 1138, + 1146, + 1152, + 1159, + 1165, 1172, - 1178, - 1184, - 1194, - 1198, - 1204, - 1212, - 1219, - 1227, - 1234, - 1239, - 1244, + 1181, + 1187, + 1193, + 1203, + 1207, + 1213, + 1221, + 1228, + 1236, + 1243, + 1248, 1253, - 1263, - 1273, - 1280, - 1286, - 1294, + 1262, + 1272, + 1282, + 1289, + 1295, 1303, - 1309, + 1312, 1318, - 1325, - 1333, - 1340, - 1347, - 1352, - 1357, + 1327, + 1334, + 1342, + 1349, + 1356, + 1361, 1366, - 1369, 1375, - 1385, - 1395, + 1378, + 1384, + 1394, 1404, - 1411, - 1414, - 1422, - 1432, - 1442, - 1449, - 1455, - 1463, - 1471, + 1413, + 1420, + 1423, + 1431, + 1441, + 1451, + 1458, + 1464, + 1472, 1480, - 1490, - 1497, - 1503, - 1509, - 1515, - 1527, - 1534, - 1542, - 1546, - 1554, - 1564, + 1489, + 1499, + 1506, + 1512, + 1518, + 1524, + 1536, + 1543, + 1551, + 1555, + 1563, 1573, - 1578, - 1586, - 1589, - 1596, - 1606, - 1611, - 1616, - 1627, - 1641, - 1653, - 1665, - 1680, - 1691, - 1703, - 1718, - 1729, - 1740, - 1745, + 1582, + 1587, + 1595, + 1598, + 1605, + 1615, + 1620, + 1625, + 1636, + 1650, + 1662, + 1674, + 1689, + 1700, + 1712, + 1727, + 1738, 1749, 1754, - 1760, + 1758, + 1763, 1769, - 1775, - 1780, - 1788, - 1796, - 1806, - 1812, - 1817, - 1823, - 1828, - 1834, - 1841, - 1846, - 1852, - 1862, - 1877, + 1778, + 1784, + 1789, + 1797, + 1805, + 1815, + 1821, + 1826, + 1832, + 1837, + 1843, + 1850, + 1855, + 1861, + 1871, 1886, - 1891, - 1898, - 1905, - 1913, - 1919, - 1927, - 1940, + 1895, + 1900, + 1907, + 1914, + 1922, + 1928, + 1936, 1949, - 1955, - 1968, - 1975, - 1982, + 1958, + 1964, + 1977, + 1984, 1991, - 1996, - 2002, - 2007, - 2012, - 2018, + 2000, + 2005, + 2011, + 2016, + 2021, 2027, - 2035, - 2041, - 2048, - 2052, + 2036, + 2044, + 2050, 2057, 2061, - 2065, + 2066, 2070, - 2075, - 2078, - 2083, - 2093, - 2104, - 2108, - 2116, - 2123, - 2131, - 2138, - 2143, - 2150, - 2156, - 2164, - 2171, - 2174, - 2178, - 2185, - 2190, - 2194, - 2199, + 2074, + 2079, + 2084, + 2087, + 2092, + 2102, + 2113, + 2117, + 2125, + 2132, + 2140, + 2147, + 2152, + 2159, + 2165, + 2173, + 2180, + 2188, + 2191, + 2195, 2202, 2207, + 2211, 2216, - 2223, - 2231, - 2234, + 2219, + 2224, + 2233, 2240, + 2248, 2251, - 2258, - 2262, + 2257, 2268, - 2273, - 2282, + 2275, + 2279, + 2285, 2290, - 2301, + 2299, 2307, - 2313, - 2322, - 2332, + 2318, + 2324, + 2330, 2339, - 2347, - 2357, - 2365, + 2349, + 2356, + 2364, 2374, - 2379, - 2386, - 2394, - 2399, - 2405, - 2412, - 2421, - 2431, - 2441, - 2449, - 2458, - 2467, - 2475, - 2481, - 2492, - 2503, - 2513, - 2524, - 2532, - 2544, - 2550, - 2557, - 2563, + 2382, + 2391, + 2396, + 2403, + 2410, + 2418, + 2423, + 2429, + 2436, + 2445, + 2455, + 2465, + 2473, + 2482, + 2491, + 2499, + 2505, + 2516, + 2527, + 2537, + 2548, + 2556, 2568, - 2573, - 2582, - 2590, - 2600, - 2604, - 2615, - 2627, - 2635, + 2574, + 2581, + 2587, + 2592, + 2597, + 2606, + 2616, + 2620, + 2631, 2643, - 2652, - 2660, - 2667, - 2678, - 2686, + 2651, + 2659, + 2668, + 2676, + 2683, 2694, - 2700, - 2708, - 2717, + 2702, + 2710, + 2716, 2724, - 2734, - 2742, - 2749, - 2755, - 2760, - 2769, + 2733, + 2740, + 2750, + 2758, + 2765, + 2771, 2776, - 2784, - 2793, - 2797, - 2802, - 2807, - 2817, - 2824, - 2831, - 2839, - 2846, - 2853, - 2860, + 2785, + 2792, + 2800, + 2809, + 2813, + 2818, + 2823, + 2833, + 2840, + 2847, + 2855, + 2862, 2869, 2876, 2885, - 2895, - 2908, - 2915, - 2923, - 2936, - 2940, - 2946, - 2951, - 2957, + 2892, + 2901, + 2911, + 2924, + 2931, + 2939, + 2952, + 2956, 2962, - 2970, - 2977, - 2982, - 2991, - 3000, - 3005, - 3012, + 2967, + 2973, + 2978, + 2986, + 2993, + 2998, + 3007, 3016, - 3023, - 3034, - 3040, + 3021, + 3028, + 3032, + 3039, 3050, - 3061, - 3067, - 3074, - 3082, - 3089, - 3096, - 3103, - 3109, - 3122, - 3132, - 3140, - 3150, + 3056, + 3066, + 3077, + 3083, + 3090, + 3098, + 3105, + 3112, + 3119, + 3125, + 3138, + 3148, 3156, - 3163, - 3175, - 3181, - 3188, - 3200, - 3211, - 3218, - 3223, - 3232, - 3242, - 3247, - 3252, - 3257, - 3262, - 3272, - 3275, - 3284, - 3296, - 3306, + 3166, + 3172, + 3179, + 3191, + 3197, + 3204, + 3216, + 3227, + 3234, + 3239, + 3248, + 3258, + 3263, + 3268, + 3273, + 3278, + 3288, + 3291, + 3300, 3312, - 3320, - 3325, - 3330, - 3339, - 3347, - 3352, - 3358, - 3366, - 3376, - 3388, - 3402, - 3414, - 3420, - 3427, - 3435, - 3444, - 3453, - 3459, - 3466, - 3471, - 3477, - 3484, - 3490, - 3499, - 3509, + 3322, + 3328, + 3336, + 3341, + 3346, + 3355, + 3363, + 3368, + 3374, + 3382, + 3392, + 3404, + 3418, + 3430, + 3436, + 3443, + 3451, + 3460, + 3469, + 3475, + 3482, + 3487, + 3493, + 3500, + 3506, 3515, - 3522, - 3530, - 3539, - 3547, + 3525, + 3531, + 3538, + 3546, 3555, 3563, - 3568, - 3574, - 3583, - 3588, - 3594, - 3605, + 3571, + 3579, + 3584, + 3590, + 3598, + 3607, 3612, - 3617, - 3624, - 3632, - 3637, - 3645, - 3651, - 3655, + 3618, + 3629, + 3636, + 3641, + 3648, + 3656, + 3661, 3669, + 3675, 3679, - 3690, - 3700, - 3710, + 3693, + 3703, + 3714, 3724, - 3733, - 3739, - 3747, - 3760, - 3769, - 3774, - 3778, + 3734, + 3748, + 3757, + 3763, + 3771, + 3784, + 3793, + 3798, + 3802, }; -#define SCANKEYWORDS_NUM_KEYWORDS 492 +#define SCANKEYWORDS_NUM_KEYWORDS 495 static int ScanKeywords_hash_func(const void *key, size_t keylen) { - static const int16 h[985] = { - -2, 143, 32767, 200, 0, 0, 448, 302, - 769, -52, 32767, 0, 32767, 0, 32767, 0, - 281, 253, 248, 612, 32767, 8, -436, 0, - 32767, 0, 32767, 354, -267, 362, 32767, 32767, - 568, 32767, 0, 32767, 289, 32767, 75, 32767, - 32767, 33, 32767, 165, 0, 32767, 32767, 32767, - 32767, -97, 32767, 358, 78, -272, 73, 339, - 2, 386, 43, 32767, 0, 32767, 508, -93, - -589, -159, -10, 0, -8, 32767, -359, 32767, - 288, -224, 58, 32767, -226, -10, 201, 32767, - 347, 32767, 255, 0, 464, -8, 0, 32767, - 225, 32767, -118, 32767, -658, 305, 297, -235, - 32767, 177, -393, 0, -43, 136, 32767, 32767, - 32767, 0, 270, -106, 190, 32767, 65, 32767, - 32767, 32767, 32767, -77, 32767, 148, -179, 334, - 0, 32767, 0, 32767, 32767, 280, 477, 346, - 32767, 148, 335, 66, 265, -204, 32767, 9, - -158, 32767, 372, 16, 32767, 227, -247, 0, - 228, -598, 32767, 257, 32767, 32767, 32767, 32767, - 32767, 402, 32767, 32767, 332, -42, 603, 32767, - 32767, 32767, 971, -38, 32767, 242, 0, 221, - -109, 459, 310, 126, 32767, 32767, 114, -410, - 130, 0, 32767, 312, 32767, 313, 32767, 392, - 516, 217, 32767, 0, 70, 32767, 478, 33, - 32767, 303, 32767, 0, 59, 194, 32767, 32767, - 0, 116, 0, 32767, 0, 32767, 32767, -325, - 81, -325, 32767, 0, -204, 0, 0, 32767, - 460, 32767, 0, 379, 375, 32767, 303, 159, - 32767, -24, 32767, 32767, 32767, 511, 32767, -185, - -622, 32767, 32767, 32767, 304, 1204, 0, 520, - 542, 593, -52, 32767, 32767, 291, 32767, 344, - 0, 31, -121, 0, 32767, 32767, 32767, 347, - 0, 32767, 32767, -1259, 0, 32767, 32767, 32767, - 480, 40, 153, 35, 582, 32767, 34, 115, - 32767, -83, 32767, 32767, 36, 324, -434, 32767, - 430, -24, -95, 32767, 32767, 32767, 172, -1264, - -236, -110, 32767, 87, -227, 179, 305, 0, - 32767, 32767, 32767, 32767, 32767, 32767, 0, 134, - 32767, 299, 32767, 32767, 25, 0, 14, -38, - 32767, 105, 392, 32767, 32767, 437, 32767, 32767, - 446, 32767, 358, 264, 209, 32767, 238, 596, - 156, -689, 32767, 435, 32767, 85, -9, -155, - 414, 0, 65, 32767, 32767, -94, 354, 46, - 69, -119, 185, 275, 1727, 32767, 32767, -99, - 32767, 445, 32767, -975, -183, 32767, 32767, 479, - 78, 32767, 0, 32767, 32767, 32767, 452, 252, - 32767, 0, 378, 32767, 32767, -34, 88, 13, - 32767, 32767, 32767, 32767, 107, 32767, 32767, -86, - 298, 1307, 180, 32767, 32767, 32767, 32767, -150, - 95, 0, 32767, 377, 32767, 182, 32767, -1192, - 287, 32767, 0, 554, -1011, 32767, 346, 26, - 0, 32767, 338, 426, 32767, 652, 240, -244, - 0, 118, 32767, -203, 133, 32767, 79, 0, - 94, 32767, 456, 32767, -657, 462, 32767, 266, - 158, 781, 32767, -273, 32767, 351, 0, 32767, - 392, 0, 89, 32767, 41, 370, 32767, 61, - -148, 32767, 32767, -37, 32767, -76, 315, 32767, - 32767, 32767, 358, 139, 56, 458, 32767, 415, - 32767, 32767, 653, 32767, 32767, 32767, -236, 32767, - 0, 0, 615, 32767, 0, 32767, 55, -912, - 32767, 113, 206, 32767, 32767, 32767, 32767, 0, - 32767, 96, 32767, 396, 175, 129, 32767, 32767, - 138, -147, 32767, 32767, -157, 270, 32767, -460, - 263, 448, 32767, 32767, 0, 371, 32767, 32767, - 32767, 32767, -283, 32767, 32767, 197, 0, 32767, - 374, 581, -549, 32767, 32767, 56, 32767, 0, - 234, -115, 32767, -439, 466, 32767, 32767, 0, - 388, 184, 32767, 32767, 83, 32767, 32767, 120, - -277, 0, 32767, 0, 180, 32767, 0, 205, - 32767, 32767, 219, 0, 32767, 32767, -32, 159, - 32767, 204, 0, 826, 495, 32767, 190, 0, - 400, 379, 32767, 32767, -108, 72, 459, 32767, - 32767, 0, 92, 32767, 276, 133, 32767, 32767, - 160, -36, 32767, 70, 871, 32767, 32767, -436, - 32767, 32767, 980, 385, 0, 9, 32767, 327, - 519, 0, 32767, 0, -31, 0, 11, 0, - 32767, 412, 124, -121, 377, 0, 32767, 32767, - 0, 137, 32767, 66, -123, 264, -50, 3, - -190, 21, 32767, 267, 32767, 0, 0, 32767, - 32767, 32767, 221, 32767, 32767, -301, 38, -319, - 389, 32767, 32767, 275, 964, -30, 330, 172, - 32767, 329, -299, 32767, 524, 341, 32767, 32767, - 123, -76, 415, 151, 32767, 179, 0, -365, - 32767, -268, 32767, -425, 203, 0, 146, 32767, - 290, 32767, 259, 32767, 0, 1, 32767, 239, - 160, 914, 39, 32767, -194, 104, 0, 0, - 32767, 32767, 32767, 0, 32767, 32767, 10, 487, - 0, 279, 32767, 223, 32767, 32767, 0, -286, - -510, 151, 429, 32767, 0, 115, 32767, -66, - 647, 291, 32767, -290, 32767, 0, -433, 0, - 180, 32767, 116, 32767, 301, 32767, 282, 294, - 0, 32767, -126, 0, -412, 0, 315, 32767, - 400, 0, 32767, 32767, 32767, 109, -227, 0, - -352, 32767, 112, 0, 471, 0, 32767, 32767, - 461, 32767, 32767, 233, 32767, 32767, 406, 32767, - 464, 32767, 118, 382, 0, 32767, 0, 32767, - 32767, 541, -305, 814, 0, 268, 0, 403, - 268, 372, 84, 32767, -91, 32767, 0, 32767, - 208, 467, 0, 32767, 32767, 32767, -236, 32767, - 32767, -53, -317, 32767, 338, 0, 0, 646, - 32767, 78, 32767, 158, 399, 0, 32767, 0, - -269, 32767, 32767, -213, -786, 32767, 162, 32767, - 32767, -259, 401, 383, 453, 0, 32767, 0, - -232, -159, 322, 32767, 32767, 203, 0, 32767, - 183, 314, 32767, -86, 32767, 377, 195, 878, - 93, -80, 212, 32767, 49, 32767, 614, 337, - 32767, 318, -59, 285, 32767, 0, 32767, 0, - 98, 17, 32767, 0, -192, 482, 0, 32767, - 102, 32767, 331, 366, 0, -325, -143, 438, - 465, 35, 472, 32767, 670, 32767, 0, 0, - 32767, 32767, 32767, 0, 109, 226, 32767, 32767, - 25, -227, 0, 0, 768, 32767, -363, 32767, - 245, 129, 32767, 405, 95, 407, 345, 1494, - 32767, 0, 473, 32767, 32767, 32767, 32767, 0, - 0, 32767, 32767, 244, 32767, 82, 32767, 38, - 32767, 97, -39, 397, 32767, 32767, 32767, 32767, - 32767, 90, 605, 105, 32767, 0, 0, 0, - 250, 32767, 372, 32767, 32767, 0, -434, 0, - 32767, 216, 32767, 443, 32767, 185, 51, 367, - 32767, 87, 0, 560, 0, 0, 0, 0, - 349, -120, 32767, 32767, 408, 32767, 32767, 0, - 32767, 0, 32767, 32767, 32767, 744, 250, -146, - 32767, 142, 0, -492, 32767, 334, 441, 32767, - 0 + static const int16 h[991] = { + 32767, -121, 32767, -21, 32767, 32767, 32767, -435, + 391, 32767, 32767, 487, 377, 213, 32767, 32767, + 32767, 32767, 32767, 20, 32767, 32767, 1, -114, + 458, 375, 88, 535, 32767, 32767, 319, 387, + -180, 0, 0, 32767, -473, 163, 105, 0, + 32767, 32767, 32767, 21, 173, -212, 32767, 371, + 65, 125, 32767, 455, 32767, 370, -342, 830, + 32767, 176, 1114, -78, -161, 32767, 239, -903, + 32767, -653, 32767, -412, 149, 32767, 1137, 32767, + -618, 32767, 919, -333, 237, 20, 32767, 380, + 195, 32767, 152, 135, 264, 115, 95, 0, + 32767, 876, -342, 32767, 32767, 374, 956, 108, + -41, 0, -760, 32767, 32767, 0, 32767, 422, + 328, 32767, 32767, 32767, 60, -183, 32767, -630, + 32767, 266, -353, 503, 32767, -111, 32767, 32767, + 480, 171, -264, 32767, 193, 482, 73, 194, + 32767, 288, 32767, 176, 370, 32767, 32767, 0, + 234, 32767, 62, 229, 32767, 32767, 32767, 0, + 32767, 32767, 32767, 32767, 466, 32767, 56, 32767, + -77, 407, 395, 86, 0, 32767, 201, 562, + 0, -460, 0, 32767, 32767, 32767, 290, 32767, + 35, 32767, 1, 32767, 396, 70, 0, 97, + 434, 420, 272, 178, 32767, 32767, 29, 346, + 0, 382, 32767, 32767, 423, -1086, 32767, 378, + 32767, 429, 32767, -210, 0, 32767, 32767, 369, + -652, 328, 64, 418, 1112, 32767, 32767, 0, + 0, 216, 32767, 32767, -339, -659, 32767, 289, + 419, 47, 32767, 767, -622, 0, -293, 0, + 32767, 32767, -257, 0, 0, 32767, 0, 32767, + 32767, 441, 32767, 0, -279, 0, 38, -433, + 32767, 470, 32767, 0, 32767, 245, -162, 32767, + 32767, -238, 32767, 0, 32767, 32767, 77, 32767, + 32767, 103, 32767, 32767, 181, 342, 32767, 150, + 440, 12, 32767, 244, 32767, 0, -149, 835, + 32767, 390, 423, 189, 32767, 32767, 32767, 32767, + 32767, 0, 0, -138, 32767, 255, 32767, 282, + 32767, -740, -639, 48, -126, 32767, 32767, 32767, + 32767, 32767, 32767, 647, 46, 369, 32767, 0, + 32767, 32767, -206, 32767, 32767, -130, 32767, 96, + 32767, 0, -27, 32767, 356, 32767, 32767, -311, + 314, 13, -158, 32767, 32767, 0, 486, 52, + 32767, 437, -3, 308, -314, -94, 32767, 32767, + 32767, 32767, 0, 32767, 765, 270, 32767, 205, + 32767, 32767, 240, -328, -50, 70, 57, -99, + 95, 32767, 32767, 464, 32767, 32767, 32767, 203, + 445, 32767, 391, 32767, 141, -210, 172, -125, + 0, 32767, 130, 32767, -66, 32767, 32767, 0, + 393, 32767, 32767, 185, 0, 32767, 258, 40, + -799, 32767, 23, 32767, 87, 32767, 119, 32767, + 32767, -227, 138, 32767, 32767, 32767, 206, 344, + 1, 71, 32767, 0, 421, 32767, 32767, 32767, + -625, 32767, 32767, 38, 491, 32767, 32767, -984, + 198, 0, 455, -16, 56, 0, -717, 411, + 200, 0, 32767, 0, 32767, 188, 82, 32767, + 32767, 0, 32767, -80, 80, 32767, -675, 32767, + 378, 26, 0, 32767, 32767, 57, 0, 32767, + 633, 32767, 0, 32767, 307, 32767, 132, 32767, + 320, 220, 32767, 0, 264, 32767, 499, -7, + 139, 271, 32767, 357, 532, 168, 32767, 258, + 32767, 17, 219, -178, 299, 32767, 32767, -27, + 382, 32767, 32767, 32767, 32767, 32767, 637, 32767, + 32767, 329, -364, 32767, -16, 355, -197, 127, + 340, -434, 224, -3, -186, 0, 176, 156, + 32767, 32767, 105, 32767, 435, 34, 32767, 32767, + 568, -176, 0, -471, 333, 32767, 0, -218, + 32767, 254, 283, 0, 326, 32767, 32767, 32767, + 0, 32767, 32767, 99, -142, 0, 318, 303, + 360, 267, 32767, 344, 0, 32767, 32767, 32767, + 547, 32767, 32767, 334, 0, -59, 446, -366, + -253, 32767, -165, 32767, 32767, 32767, 427, -152, + 15, 32767, 32767, 0, 51, 32767, 98, 599, + 169, 31, 0, -116, 0, 0, 32767, -402, + 32767, 32767, 263, 32767, 32767, -205, -94, 0, + 280, 260, 32767, 32767, 1124, 32767, -543, 0, + 0, 32767, 32767, 32767, 32767, 32767, 773, 7, + 930, 288, -620, 32767, 132, 32767, 0, 0, + 58, 32767, 373, 848, 228, 112, -4, 32767, + 32767, -152, 651, 32767, 32767, 1013, -685, 240, + 242, -117, 38, 110, 32767, 0, 32767, -48, + 32767, -113, 32767, 0, 92, 1228, 0, 760, + 32767, 0, 32767, 0, 457, -144, 774, 198, + 32767, 32767, 32767, 351, 329, 292, 32767, 32767, + 118, 32767, 32767, 331, 80, 117, 815, 32767, + 0, 32767, 370, 32767, 32767, 0, 32767, -419, + 32767, 32767, 32767, 0, 32767, 32767, 32767, 193, + 0, 32767, 0, 32767, 32767, 32767, 870, 0, + 32767, -52, 454, 0, 32767, 64, 0, 310, + 0, -338, 32767, 119, 32767, 32767, -366, 32767, + 0, 159, 32767, 362, 66, 32767, 32767, 32767, + 0, -122, -39, 425, 361, 32767, -160, 420, + 163, 210, 32767, 32767, 32767, 32767, -642, 0, + -287, 0, 32767, 0, 401, 0, 221, 32767, + 238, 0, 525, 0, 91, 32767, 325, 32767, + 32767, -651, 129, 463, 0, 0, 32767, 172, + 287, 32767, 32767, -122, 0, 32767, 32767, 798, + 492, 109, -52, 0, 0, 6, 32767, 32767, + 32767, 474, 32767, 87, 32767, 32767, 31, 32767, + 451, 7, 252, 69, 32767, 6, -276, 97, + 32767, 32767, 32767, 32767, 32767, 141, 524, 32767, + 83, -304, 32767, 32767, 32767, 941, 32767, 32767, + 32767, 32767, 107, 32767, 32767, 32767, 32767, 32767, + 32767, 535, -733, 493, 32767, 554, -257, 18, + 173, -370, 191, 528, 406, 0, 468, 292, + 32767, -142, 417, 179, -27, 322, 32767, 504, + 32767, 433, 153, 182, 394, 32767, 32767, 32767, + 0, 32767, 177, 118, 32767, 32767, 83, 194, + 18, -781, 0, 322, 0, 19, 344, 32767, + 156, 118, 0, 32767, 372, 32767, 32767, 0, + 32767, -452, 366, 1133, -126, 834, 32767, 32767, + 32767, 1193, 162, 32767, 0, 0, -328, 360, + 353, -489, 0, 32767, 32767, 32767, 32767, 32767, + -237, 290, 32767, -780, 32767, -78, 32767, 0, + 137, 0, 94, 0, 344, 32767, 671, -164, + 422, 32767, 405, 32767, 57, 0, 141, 32767, + 32767, -16, 32767, 32767, -55, 46, 221, 32767, + 247, 32767, 0, 10, 32767, 401, 613, 32767, + 0, -244, 250, 32767, 223, 32767, 274, 32767, + 32767, 0, 124, 32767, 291, 303, -299, 234, + 38, 32767, 0, 32767, 181, 0, 536, 32767, + 23, -195, -192, 0, 1087, 32767, 60, 32767, + 177, 32767, 0, -646, 622, -36, 752, 46, + 0, 32767, 32767, 1067, 0, 32767, -187, 192, + 0, 32767, 32767, 425, 0, 32767, 879, 32767, + 32767, -129, 0, 32767, 190, 175, 254 }; const unsigned char *k = (const unsigned char *) key; uint32 a = 0; - uint32 b = 0; + uint32 b = 1; while (keylen--) { unsigned char c = *k++ | 0x20; a = a * 257 + c; - b = b * 31 + c; + b = b * 127 + c; } - return h[a % 985] + h[b % 985]; + return h[a % 991] + h[b % 991]; } const ScanKeywordList ScanKeywords = { diff --git a/src/include/parser/makefuncs.h b/src/include/parser/makefuncs.h index 1086b1f55..0441c8e5d 100644 --- a/src/include/parser/makefuncs.h +++ b/src/include/parser/makefuncs.h @@ -4,8 +4,8 @@ * prototypes for the creator functions of various nodes * * - * Portions Copyright (c) 2003-2024, PgPool Global Development Group - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2003-2025, PgPool Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/nodes/makefuncs.h @@ -68,6 +68,7 @@ extern RelabelType *makeRelabelType(Expr *arg, Oid rtype, int32 rtypmod, Oid rcollid, CoercionForm rformat); extern RangeVar *makeRangeVar(char *schemaname, char *relname, int location); +extern Constraint *makeNotNullConstraint(String *colname); extern TypeName *makeTypeName(char *typnam); extern TypeName *makeTypeNameFromNameList(List *names); diff --git a/src/include/parser/miscnodes.h b/src/include/parser/miscnodes.h new file mode 100644 index 000000000..719cacff1 --- /dev/null +++ b/src/include/parser/miscnodes.h @@ -0,0 +1,53 @@ +/*------------------------------------------------------------------------- + * + * miscnodes.h + * Definitions for hard-to-classify node types. + * + * Node types declared here are not part of parse trees, plan trees, + * or execution state trees. We only assign them NodeTag values because + * IsA() tests provide a convenient way to disambiguate what kind of + * structure is being passed through assorted APIs, such as function + * "context" pointers. + * + * + * Portions Copyright (c) 2003-2025, PgPool Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * src/include/nodes/miscnodes.h + * + *------------------------------------------------------------------------- + */ +#ifndef MISCNODES_H +#define MISCNODES_H + +#include "nodes.h" + +/* + * ErrorSaveContext - + * function call context node for handling of "soft" errors + * + * A caller wishing to trap soft errors must initialize a struct like this + * with all fields zero/NULL except for the NodeTag. Optionally, set + * details_wanted = true if more than the bare knowledge that a soft error + * occurred is required. The struct is then passed to a SQL-callable function + * via the FunctionCallInfo.context field; or below the level of SQL calls, + * it could be passed to a subroutine directly. + * + * After calling code that might report an error this way, check + * error_occurred to see if an error happened. If so, and if details_wanted + * is true, error_data has been filled with error details (stored in the + * callee's memory context!). The ErrorData can be modified (e.g. downgraded + * to a WARNING) and reported with ThrowErrorData(). FreeErrorData() can be + * called to release error_data, although that step is typically not necessary + * if the called code was run in a short-lived context. + */ +typedef struct ErrorSaveContext +{ + NodeTag type; + bool error_occurred; /* set to true if we detect a soft error */ + bool details_wanted; /* does caller want more info than that? */ + ErrorData *error_data; /* details of error, if so */ +} ErrorSaveContext; + +#endif /* MISCNODES_H */ diff --git a/src/include/parser/nodes.h b/src/include/parser/nodes.h index d0d4f3cce..275694786 100644 --- a/src/include/parser/nodes.h +++ b/src/include/parser/nodes.h @@ -4,8 +4,8 @@ * Definitions for tagged nodes. * * - * Portions Copyright (c) 2003-2024, PgPool Global Development Group - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2003-2025, PgPool Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/nodes/nodes.h @@ -62,6 +62,7 @@ typedef enum NodeTag * readfuncs.c. * * - custom_query_jumble: Has custom implementation in queryjumblefuncs.c. + * Also available as a node field attribute. * * - no_copy: Does not support copyObject() at all. * @@ -109,10 +110,15 @@ typedef enum NodeTag * - equal_ignore_if_zero: Ignore the field for equality if it is zero. * (Otherwise, compare normally.) * + * - custom_query_jumble: Has custom implementation in queryjumblefuncs.c + * for the field of a node. Also available as a node attribute. + * * - query_jumble_ignore: Ignore the field for the query jumbling. Note * that typmod and collation information are usually irrelevant for the * query jumbling. * + * - query_jumble_squash: Squash multiple values during query jumbling. + * * - query_jumble_location: Mark the field as a location to track. This is * only allowed for integer fields that include "location" in their name. * @@ -210,7 +216,7 @@ extern char *bmsToString(const struct Bitmapset *bms); * nodes/{readfuncs.c,read.c} */ extern void *stringToNode(const char *str); -#ifdef WRITE_READ_PARSE_PLAN_TREES +#ifdef DEBUG_NODE_TESTS_ENABLED extern void *stringToNodeWithLocations(const char *str); #endif extern struct Bitmapset *readBitmapset(void); @@ -314,6 +320,7 @@ typedef enum JoinType */ JOIN_SEMI, /* 1 copy of each LHS row that has match(es) */ JOIN_ANTI, /* 1 copy of each LHS row that has no match */ + JOIN_RIGHT_SEMI, /* 1 copy of each RHS row that has match(es) */ JOIN_RIGHT_ANTI, /* 1 copy of each RHS row that has no match */ /* @@ -330,10 +337,10 @@ typedef enum JoinType /* * OUTER joins are those for which pushed-down quals must behave differently - * from the join's own quals. This is in fact everything except INNER and - * SEMI joins. However, this macro must also exclude the JOIN_UNIQUE symbols - * since those are temporary proxies for what will eventually be an INNER - * join. + * from the join's own quals. This is in fact everything except INNER, SEMI + * and RIGHT_SEMI joins. However, this macro must also exclude the + * JOIN_UNIQUE symbols since those are temporary proxies for what will + * eventually be an INNER join. * * Note: semijoins are a hybrid case, but we choose to treat them as not * being outer joins. This is okay principally because the SQL syntax makes diff --git a/src/include/parser/nodetags.h b/src/include/parser/nodetags.h index ee1fb29ce..312727639 100644 --- a/src/include/parser/nodetags.h +++ b/src/include/parser/nodetags.h @@ -3,7 +3,7 @@ * nodetags.h * Generated node infrastructure code * - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * NOTES @@ -75,45 +75,45 @@ T_CurrentOfExpr = 58, T_NextValueExpr = 59, T_InferenceElem = 60, - T_TargetEntry = 61, - T_RangeTblRef = 62, - T_JoinExpr = 63, - T_FromExpr = 64, - T_OnConflictExpr = 65, - T_Query = 66, - T_TypeName = 67, - T_ColumnRef = 68, - T_ParamRef = 69, - T_A_Expr = 70, - T_A_Const = 71, - T_TypeCast = 72, - T_CollateClause = 73, - T_RoleSpec = 74, - T_FuncCall = 75, - T_A_Star = 76, - T_A_Indices = 77, - T_A_Indirection = 78, - T_A_ArrayExpr = 79, - T_ResTarget = 80, - T_MultiAssignRef = 81, - T_SortBy = 82, - T_WindowDef = 83, - T_RangeSubselect = 84, - T_RangeFunction = 85, - T_RangeTableFunc = 86, - T_RangeTableFuncCol = 87, - T_RangeTableSample = 88, - T_ColumnDef = 89, - T_TableLikeClause = 90, - T_IndexElem = 91, - T_DefElem = 92, - T_LockingClause = 93, - T_XmlSerialize = 94, - T_PartitionElem = 95, - T_PartitionSpec = 96, - T_PartitionBoundSpec = 97, - T_PartitionRangeDatum = 98, - T_SinglePartitionSpec = 99, + T_ReturningExpr = 61, + T_TargetEntry = 62, + T_RangeTblRef = 63, + T_JoinExpr = 64, + T_FromExpr = 65, + T_OnConflictExpr = 66, + T_Query = 67, + T_TypeName = 68, + T_ColumnRef = 69, + T_ParamRef = 70, + T_A_Expr = 71, + T_A_Const = 72, + T_TypeCast = 73, + T_CollateClause = 74, + T_RoleSpec = 75, + T_FuncCall = 76, + T_A_Star = 77, + T_A_Indices = 78, + T_A_Indirection = 79, + T_A_ArrayExpr = 80, + T_ResTarget = 81, + T_MultiAssignRef = 82, + T_SortBy = 83, + T_WindowDef = 84, + T_RangeSubselect = 85, + T_RangeFunction = 86, + T_RangeTableFunc = 87, + T_RangeTableFuncCol = 88, + T_RangeTableSample = 89, + T_ColumnDef = 90, + T_TableLikeClause = 91, + T_IndexElem = 92, + T_DefElem = 93, + T_LockingClause = 94, + T_XmlSerialize = 95, + T_PartitionElem = 96, + T_PartitionSpec = 97, + T_PartitionBoundSpec = 98, + T_PartitionRangeDatum = 99, T_PartitionCmd = 100, T_RangeTblEntry = 101, T_RTEPermissionInfo = 102, @@ -131,361 +131,366 @@ T_CTECycleClause = 114, T_CommonTableExpr = 115, T_MergeWhenClause = 116, - T_TriggerTransition = 117, - T_JsonOutput = 118, - T_JsonArgument = 119, - T_JsonFuncExpr = 120, - T_JsonTablePathSpec = 121, - T_JsonTable = 122, - T_JsonTableColumn = 123, - T_JsonKeyValue = 124, - T_JsonParseExpr = 125, - T_JsonScalarExpr = 126, - T_JsonSerializeExpr = 127, - T_JsonObjectConstructor = 128, - T_JsonArrayConstructor = 129, - T_JsonArrayQueryConstructor = 130, - T_JsonAggConstructor = 131, - T_JsonObjectAgg = 132, - T_JsonArrayAgg = 133, - T_RawStmt = 134, - T_InsertStmt = 135, - T_DeleteStmt = 136, - T_UpdateStmt = 137, - T_MergeStmt = 138, - T_SelectStmt = 139, - T_SetOperationStmt = 140, - T_ReturnStmt = 141, - T_PLAssignStmt = 142, - T_CreateSchemaStmt = 143, - T_AlterTableStmt = 144, - T_ReplicaIdentityStmt = 145, - T_AlterTableCmd = 146, - T_AlterCollationStmt = 147, - T_AlterDomainStmt = 148, - T_GrantStmt = 149, - T_ObjectWithArgs = 150, - T_AccessPriv = 151, - T_GrantRoleStmt = 152, - T_AlterDefaultPrivilegesStmt = 153, - T_CopyStmt = 154, - T_VariableSetStmt = 155, - T_VariableShowStmt = 156, - T_CreateStmt = 157, - T_Constraint = 158, - T_CreateTableSpaceStmt = 159, - T_DropTableSpaceStmt = 160, - T_AlterTableSpaceOptionsStmt = 161, - T_AlterTableMoveAllStmt = 162, - T_CreateExtensionStmt = 163, - T_AlterExtensionStmt = 164, - T_AlterExtensionContentsStmt = 165, - T_CreateFdwStmt = 166, - T_AlterFdwStmt = 167, - T_CreateForeignServerStmt = 168, - T_AlterForeignServerStmt = 169, - T_CreateForeignTableStmt = 170, - T_CreateUserMappingStmt = 171, - T_AlterUserMappingStmt = 172, - T_DropUserMappingStmt = 173, - T_ImportForeignSchemaStmt = 174, - T_CreatePolicyStmt = 175, - T_AlterPolicyStmt = 176, - T_CreateAmStmt = 177, - T_CreateTrigStmt = 178, - T_CreateEventTrigStmt = 179, - T_AlterEventTrigStmt = 180, - T_CreatePLangStmt = 181, - T_CreateRoleStmt = 182, - T_AlterRoleStmt = 183, - T_AlterRoleSetStmt = 184, - T_DropRoleStmt = 185, - T_CreateSeqStmt = 186, - T_AlterSeqStmt = 187, - T_DefineStmt = 188, - T_CreateDomainStmt = 189, - T_CreateOpClassStmt = 190, - T_CreateOpClassItem = 191, - T_CreateOpFamilyStmt = 192, - T_AlterOpFamilyStmt = 193, - T_DropStmt = 194, - T_TruncateStmt = 195, - T_CommentStmt = 196, - T_SecLabelStmt = 197, - T_DeclareCursorStmt = 198, - T_ClosePortalStmt = 199, - T_FetchStmt = 200, - T_IndexStmt = 201, - T_CreateStatsStmt = 202, - T_StatsElem = 203, - T_AlterStatsStmt = 204, - T_CreateFunctionStmt = 205, - T_FunctionParameter = 206, - T_AlterFunctionStmt = 207, - T_DoStmt = 208, - T_InlineCodeBlock = 209, - T_CallStmt = 210, - T_CallContext = 211, - T_RenameStmt = 212, - T_AlterObjectDependsStmt = 213, - T_AlterObjectSchemaStmt = 214, - T_AlterOwnerStmt = 215, - T_AlterOperatorStmt = 216, - T_AlterTypeStmt = 217, - T_RuleStmt = 218, - T_NotifyStmt = 219, - T_ListenStmt = 220, - T_UnlistenStmt = 221, - T_TransactionStmt = 222, - T_CompositeTypeStmt = 223, - T_CreateEnumStmt = 224, - T_CreateRangeStmt = 225, - T_AlterEnumStmt = 226, - T_ViewStmt = 227, - T_LoadStmt = 228, - T_CreatedbStmt = 229, - T_AlterDatabaseStmt = 230, - T_AlterDatabaseRefreshCollStmt = 231, - T_AlterDatabaseSetStmt = 232, - T_DropdbStmt = 233, - T_AlterSystemStmt = 234, - T_ClusterStmt = 235, - T_VacuumStmt = 236, - T_VacuumRelation = 237, - T_ExplainStmt = 238, - T_CreateTableAsStmt = 239, - T_RefreshMatViewStmt = 240, - T_CheckPointStmt = 241, - T_DiscardStmt = 242, - T_LockStmt = 243, - T_ConstraintsSetStmt = 244, - T_ReindexStmt = 245, - T_CreateConversionStmt = 246, - T_CreateCastStmt = 247, - T_CreateTransformStmt = 248, - T_PrepareStmt = 249, - T_ExecuteStmt = 250, - T_DeallocateStmt = 251, - T_DropOwnedStmt = 252, - T_ReassignOwnedStmt = 253, - T_AlterTSDictionaryStmt = 254, - T_AlterTSConfigurationStmt = 255, - T_PublicationTable = 256, - T_PublicationObjSpec = 257, - T_CreatePublicationStmt = 258, - T_AlterPublicationStmt = 259, - T_CreateSubscriptionStmt = 260, - T_AlterSubscriptionStmt = 261, - T_DropSubscriptionStmt = 262, - T_PlannerGlobal = 263, - T_PlannerInfo = 264, - T_RelOptInfo = 265, - T_IndexOptInfo = 266, - T_ForeignKeyOptInfo = 267, - T_StatisticExtInfo = 268, - T_JoinDomain = 269, - T_EquivalenceClass = 270, - T_EquivalenceMember = 271, - T_PathKey = 272, - T_GroupByOrdering = 273, - T_PathTarget = 274, - T_ParamPathInfo = 275, - T_Path = 276, - T_IndexPath = 277, - T_IndexClause = 278, - T_BitmapHeapPath = 279, - T_BitmapAndPath = 280, - T_BitmapOrPath = 281, - T_TidPath = 282, - T_TidRangePath = 283, - T_SubqueryScanPath = 284, - T_ForeignPath = 285, - T_CustomPath = 286, - T_AppendPath = 287, - T_MergeAppendPath = 288, - T_GroupResultPath = 289, - T_MaterialPath = 290, - T_MemoizePath = 291, - T_UniquePath = 292, - T_GatherPath = 293, - T_GatherMergePath = 294, - T_NestPath = 295, - T_MergePath = 296, - T_HashPath = 297, - T_ProjectionPath = 298, - T_ProjectSetPath = 299, - T_SortPath = 300, - T_IncrementalSortPath = 301, - T_GroupPath = 302, - T_UpperUniquePath = 303, - T_AggPath = 304, - T_GroupingSetData = 305, - T_RollupData = 306, - T_GroupingSetsPath = 307, - T_MinMaxAggPath = 308, - T_WindowAggPath = 309, - T_SetOpPath = 310, - T_RecursiveUnionPath = 311, - T_LockRowsPath = 312, - T_ModifyTablePath = 313, - T_LimitPath = 314, - T_RestrictInfo = 315, - T_PlaceHolderVar = 316, - T_SpecialJoinInfo = 317, - T_OuterJoinClauseInfo = 318, - T_AppendRelInfo = 319, - T_RowIdentityVarInfo = 320, - T_PlaceHolderInfo = 321, - T_MinMaxAggInfo = 322, - T_PlannerParamItem = 323, - T_AggInfo = 324, - T_AggTransInfo = 325, - T_PlannedStmt = 326, - T_Result = 327, - T_ProjectSet = 328, - T_ModifyTable = 329, - T_Append = 330, - T_MergeAppend = 331, - T_RecursiveUnion = 332, - T_BitmapAnd = 333, - T_BitmapOr = 334, - T_SeqScan = 335, - T_SampleScan = 336, - T_IndexScan = 337, - T_IndexOnlyScan = 338, - T_BitmapIndexScan = 339, - T_BitmapHeapScan = 340, - T_TidScan = 341, - T_TidRangeScan = 342, - T_SubqueryScan = 343, - T_FunctionScan = 344, - T_ValuesScan = 345, - T_TableFuncScan = 346, - T_CteScan = 347, - T_NamedTuplestoreScan = 348, - T_WorkTableScan = 349, - T_ForeignScan = 350, - T_CustomScan = 351, - T_NestLoop = 352, - T_NestLoopParam = 353, - T_MergeJoin = 354, - T_HashJoin = 355, - T_Material = 356, - T_Memoize = 357, - T_Sort = 358, - T_IncrementalSort = 359, - T_Group = 360, - T_Agg = 361, - T_WindowAgg = 362, - T_Unique = 363, - T_Gather = 364, - T_GatherMerge = 365, - T_Hash = 366, - T_SetOp = 367, - T_LockRows = 368, - T_Limit = 369, - T_PlanRowMark = 370, - T_PartitionPruneInfo = 371, - T_PartitionedRelPruneInfo = 372, - T_PartitionPruneStepOp = 373, - T_PartitionPruneStepCombine = 374, - T_PlanInvalItem = 375, - T_ExprState = 376, - T_IndexInfo = 377, - T_ExprContext = 378, - T_ReturnSetInfo = 379, - T_ProjectionInfo = 380, - T_JunkFilter = 381, - T_OnConflictSetState = 382, - T_MergeActionState = 383, - T_ResultRelInfo = 384, - T_EState = 385, - T_WindowFuncExprState = 386, - T_SetExprState = 387, - T_SubPlanState = 388, - T_DomainConstraintState = 389, - T_ResultState = 390, - T_ProjectSetState = 391, - T_ModifyTableState = 392, - T_AppendState = 393, - T_MergeAppendState = 394, - T_RecursiveUnionState = 395, - T_BitmapAndState = 396, - T_BitmapOrState = 397, - T_ScanState = 398, - T_SeqScanState = 399, - T_SampleScanState = 400, - T_IndexScanState = 401, - T_IndexOnlyScanState = 402, - T_BitmapIndexScanState = 403, - T_BitmapHeapScanState = 404, - T_TidScanState = 405, - T_TidRangeScanState = 406, - T_SubqueryScanState = 407, - T_FunctionScanState = 408, - T_ValuesScanState = 409, - T_TableFuncScanState = 410, - T_CteScanState = 411, - T_NamedTuplestoreScanState = 412, - T_WorkTableScanState = 413, - T_ForeignScanState = 414, - T_CustomScanState = 415, - T_JoinState = 416, - T_NestLoopState = 417, - T_MergeJoinState = 418, - T_HashJoinState = 419, - T_MaterialState = 420, - T_MemoizeState = 421, - T_SortState = 422, - T_IncrementalSortState = 423, - T_GroupState = 424, - T_AggState = 425, - T_WindowAggState = 426, - T_UniqueState = 427, - T_GatherState = 428, - T_GatherMergeState = 429, - T_HashState = 430, - T_SetOpState = 431, - T_LockRowsState = 432, - T_LimitState = 433, - T_IndexAmRoutine = 434, - T_TableAmRoutine = 435, - T_TsmRoutine = 436, - T_EventTriggerData = 437, - T_TriggerData = 438, - T_TupleTableSlot = 439, - T_FdwRoutine = 440, - T_Bitmapset = 441, - T_ExtensibleNode = 442, - T_ErrorSaveContext = 443, - T_IdentifySystemCmd = 444, - T_BaseBackupCmd = 445, - T_CreateReplicationSlotCmd = 446, - T_DropReplicationSlotCmd = 447, - T_AlterReplicationSlotCmd = 448, - T_StartReplicationCmd = 449, - T_ReadReplicationSlotCmd = 450, - T_TimeLineHistoryCmd = 451, - T_UploadManifestCmd = 452, - T_SupportRequestSimplify = 453, - T_SupportRequestSelectivity = 454, - T_SupportRequestCost = 455, - T_SupportRequestRows = 456, - T_SupportRequestIndexCondition = 457, - T_SupportRequestWFuncMonotonic = 458, - T_SupportRequestOptimizeWindowClause = 459, - T_Integer = 460, - T_Float = 461, - T_Boolean = 462, - T_String = 463, - T_BitString = 464, - T_ForeignKeyCacheInfo = 465, - T_IntList = 466, - T_OidList = 467, - T_XidList = 468, - T_AllocSetContext = 469, - T_GenerationContext = 470, - T_SlabContext = 471, - T_BumpContext = 472, - T_TIDBitmap = 473, - T_WindowObjectData = 474, + T_ReturningOption = 117, + T_ReturningClause = 118, + T_TriggerTransition = 119, + T_JsonOutput = 120, + T_JsonArgument = 121, + T_JsonFuncExpr = 122, + T_JsonTablePathSpec = 123, + T_JsonTable = 124, + T_JsonTableColumn = 125, + T_JsonKeyValue = 126, + T_JsonParseExpr = 127, + T_JsonScalarExpr = 128, + T_JsonSerializeExpr = 129, + T_JsonObjectConstructor = 130, + T_JsonArrayConstructor = 131, + T_JsonArrayQueryConstructor = 132, + T_JsonAggConstructor = 133, + T_JsonObjectAgg = 134, + T_JsonArrayAgg = 135, + T_RawStmt = 136, + T_InsertStmt = 137, + T_DeleteStmt = 138, + T_UpdateStmt = 139, + T_MergeStmt = 140, + T_SelectStmt = 141, + T_SetOperationStmt = 142, + T_ReturnStmt = 143, + T_PLAssignStmt = 144, + T_CreateSchemaStmt = 145, + T_AlterTableStmt = 146, + T_AlterTableCmd = 147, + T_ATAlterConstraint = 148, + T_ReplicaIdentityStmt = 149, + T_AlterCollationStmt = 150, + T_AlterDomainStmt = 151, + T_GrantStmt = 152, + T_ObjectWithArgs = 153, + T_AccessPriv = 154, + T_GrantRoleStmt = 155, + T_AlterDefaultPrivilegesStmt = 156, + T_CopyStmt = 157, + T_VariableSetStmt = 158, + T_VariableShowStmt = 159, + T_CreateStmt = 160, + T_Constraint = 161, + T_CreateTableSpaceStmt = 162, + T_DropTableSpaceStmt = 163, + T_AlterTableSpaceOptionsStmt = 164, + T_AlterTableMoveAllStmt = 165, + T_CreateExtensionStmt = 166, + T_AlterExtensionStmt = 167, + T_AlterExtensionContentsStmt = 168, + T_CreateFdwStmt = 169, + T_AlterFdwStmt = 170, + T_CreateForeignServerStmt = 171, + T_AlterForeignServerStmt = 172, + T_CreateForeignTableStmt = 173, + T_CreateUserMappingStmt = 174, + T_AlterUserMappingStmt = 175, + T_DropUserMappingStmt = 176, + T_ImportForeignSchemaStmt = 177, + T_CreatePolicyStmt = 178, + T_AlterPolicyStmt = 179, + T_CreateAmStmt = 180, + T_CreateTrigStmt = 181, + T_CreateEventTrigStmt = 182, + T_AlterEventTrigStmt = 183, + T_CreatePLangStmt = 184, + T_CreateRoleStmt = 185, + T_AlterRoleStmt = 186, + T_AlterRoleSetStmt = 187, + T_DropRoleStmt = 188, + T_CreateSeqStmt = 189, + T_AlterSeqStmt = 190, + T_DefineStmt = 191, + T_CreateDomainStmt = 192, + T_CreateOpClassStmt = 193, + T_CreateOpClassItem = 194, + T_CreateOpFamilyStmt = 195, + T_AlterOpFamilyStmt = 196, + T_DropStmt = 197, + T_TruncateStmt = 198, + T_CommentStmt = 199, + T_SecLabelStmt = 200, + T_DeclareCursorStmt = 201, + T_ClosePortalStmt = 202, + T_FetchStmt = 203, + T_IndexStmt = 204, + T_CreateStatsStmt = 205, + T_StatsElem = 206, + T_AlterStatsStmt = 207, + T_CreateFunctionStmt = 208, + T_FunctionParameter = 209, + T_AlterFunctionStmt = 210, + T_DoStmt = 211, + T_InlineCodeBlock = 212, + T_CallStmt = 213, + T_CallContext = 214, + T_RenameStmt = 215, + T_AlterObjectDependsStmt = 216, + T_AlterObjectSchemaStmt = 217, + T_AlterOwnerStmt = 218, + T_AlterOperatorStmt = 219, + T_AlterTypeStmt = 220, + T_RuleStmt = 221, + T_NotifyStmt = 222, + T_ListenStmt = 223, + T_UnlistenStmt = 224, + T_TransactionStmt = 225, + T_CompositeTypeStmt = 226, + T_CreateEnumStmt = 227, + T_CreateRangeStmt = 228, + T_AlterEnumStmt = 229, + T_ViewStmt = 230, + T_LoadStmt = 231, + T_CreatedbStmt = 232, + T_AlterDatabaseStmt = 233, + T_AlterDatabaseRefreshCollStmt = 234, + T_AlterDatabaseSetStmt = 235, + T_DropdbStmt = 236, + T_AlterSystemStmt = 237, + T_ClusterStmt = 238, + T_VacuumStmt = 239, + T_VacuumRelation = 240, + T_ExplainStmt = 241, + T_CreateTableAsStmt = 242, + T_RefreshMatViewStmt = 243, + T_CheckPointStmt = 244, + T_DiscardStmt = 245, + T_LockStmt = 246, + T_ConstraintsSetStmt = 247, + T_ReindexStmt = 248, + T_CreateConversionStmt = 249, + T_CreateCastStmt = 250, + T_CreateTransformStmt = 251, + T_PrepareStmt = 252, + T_ExecuteStmt = 253, + T_DeallocateStmt = 254, + T_DropOwnedStmt = 255, + T_ReassignOwnedStmt = 256, + T_AlterTSDictionaryStmt = 257, + T_AlterTSConfigurationStmt = 258, + T_PublicationTable = 259, + T_PublicationObjSpec = 260, + T_CreatePublicationStmt = 261, + T_AlterPublicationStmt = 262, + T_CreateSubscriptionStmt = 263, + T_AlterSubscriptionStmt = 264, + T_DropSubscriptionStmt = 265, + T_PlannerGlobal = 266, + T_PlannerInfo = 267, + T_RelOptInfo = 268, + T_IndexOptInfo = 269, + T_ForeignKeyOptInfo = 270, + T_StatisticExtInfo = 271, + T_JoinDomain = 272, + T_EquivalenceClass = 273, + T_EquivalenceMember = 274, + T_PathKey = 275, + T_GroupByOrdering = 276, + T_PathTarget = 277, + T_ParamPathInfo = 278, + T_Path = 279, + T_IndexPath = 280, + T_IndexClause = 281, + T_BitmapHeapPath = 282, + T_BitmapAndPath = 283, + T_BitmapOrPath = 284, + T_TidPath = 285, + T_TidRangePath = 286, + T_SubqueryScanPath = 287, + T_ForeignPath = 288, + T_CustomPath = 289, + T_AppendPath = 290, + T_MergeAppendPath = 291, + T_GroupResultPath = 292, + T_MaterialPath = 293, + T_MemoizePath = 294, + T_UniquePath = 295, + T_GatherPath = 296, + T_GatherMergePath = 297, + T_NestPath = 298, + T_MergePath = 299, + T_HashPath = 300, + T_ProjectionPath = 301, + T_ProjectSetPath = 302, + T_SortPath = 303, + T_IncrementalSortPath = 304, + T_GroupPath = 305, + T_UpperUniquePath = 306, + T_AggPath = 307, + T_GroupingSetData = 308, + T_RollupData = 309, + T_GroupingSetsPath = 310, + T_MinMaxAggPath = 311, + T_WindowAggPath = 312, + T_SetOpPath = 313, + T_RecursiveUnionPath = 314, + T_LockRowsPath = 315, + T_ModifyTablePath = 316, + T_LimitPath = 317, + T_RestrictInfo = 318, + T_PlaceHolderVar = 319, + T_SpecialJoinInfo = 320, + T_OuterJoinClauseInfo = 321, + T_AppendRelInfo = 322, + T_RowIdentityVarInfo = 323, + T_PlaceHolderInfo = 324, + T_MinMaxAggInfo = 325, + T_PlannerParamItem = 326, + T_AggInfo = 327, + T_AggTransInfo = 328, + T_UniqueRelInfo = 329, + T_PlannedStmt = 330, + T_Result = 331, + T_ProjectSet = 332, + T_ModifyTable = 333, + T_Append = 334, + T_MergeAppend = 335, + T_RecursiveUnion = 336, + T_BitmapAnd = 337, + T_BitmapOr = 338, + T_SeqScan = 339, + T_SampleScan = 340, + T_IndexScan = 341, + T_IndexOnlyScan = 342, + T_BitmapIndexScan = 343, + T_BitmapHeapScan = 344, + T_TidScan = 345, + T_TidRangeScan = 346, + T_SubqueryScan = 347, + T_FunctionScan = 348, + T_ValuesScan = 349, + T_TableFuncScan = 350, + T_CteScan = 351, + T_NamedTuplestoreScan = 352, + T_WorkTableScan = 353, + T_ForeignScan = 354, + T_CustomScan = 355, + T_NestLoop = 356, + T_NestLoopParam = 357, + T_MergeJoin = 358, + T_HashJoin = 359, + T_Material = 360, + T_Memoize = 361, + T_Sort = 362, + T_IncrementalSort = 363, + T_Group = 364, + T_Agg = 365, + T_WindowAgg = 366, + T_Unique = 367, + T_Gather = 368, + T_GatherMerge = 369, + T_Hash = 370, + T_SetOp = 371, + T_LockRows = 372, + T_Limit = 373, + T_PlanRowMark = 374, + T_PartitionPruneInfo = 375, + T_PartitionedRelPruneInfo = 376, + T_PartitionPruneStepOp = 377, + T_PartitionPruneStepCombine = 378, + T_PlanInvalItem = 379, + T_ExprState = 380, + T_IndexInfo = 381, + T_ExprContext = 382, + T_ReturnSetInfo = 383, + T_ProjectionInfo = 384, + T_JunkFilter = 385, + T_OnConflictSetState = 386, + T_MergeActionState = 387, + T_ResultRelInfo = 388, + T_EState = 389, + T_WindowFuncExprState = 390, + T_SetExprState = 391, + T_SubPlanState = 392, + T_DomainConstraintState = 393, + T_ResultState = 394, + T_ProjectSetState = 395, + T_ModifyTableState = 396, + T_AppendState = 397, + T_MergeAppendState = 398, + T_RecursiveUnionState = 399, + T_BitmapAndState = 400, + T_BitmapOrState = 401, + T_ScanState = 402, + T_SeqScanState = 403, + T_SampleScanState = 404, + T_IndexScanState = 405, + T_IndexOnlyScanState = 406, + T_BitmapIndexScanState = 407, + T_BitmapHeapScanState = 408, + T_TidScanState = 409, + T_TidRangeScanState = 410, + T_SubqueryScanState = 411, + T_FunctionScanState = 412, + T_ValuesScanState = 413, + T_TableFuncScanState = 414, + T_CteScanState = 415, + T_NamedTuplestoreScanState = 416, + T_WorkTableScanState = 417, + T_ForeignScanState = 418, + T_CustomScanState = 419, + T_JoinState = 420, + T_NestLoopState = 421, + T_MergeJoinState = 422, + T_HashJoinState = 423, + T_MaterialState = 424, + T_MemoizeState = 425, + T_SortState = 426, + T_IncrementalSortState = 427, + T_GroupState = 428, + T_AggState = 429, + T_WindowAggState = 430, + T_UniqueState = 431, + T_GatherState = 432, + T_GatherMergeState = 433, + T_HashState = 434, + T_SetOpState = 435, + T_LockRowsState = 436, + T_LimitState = 437, + T_IndexAmRoutine = 438, + T_TableAmRoutine = 439, + T_TsmRoutine = 440, + T_EventTriggerData = 441, + T_TriggerData = 442, + T_TupleTableSlot = 443, + T_FdwRoutine = 444, + T_Bitmapset = 445, + T_ExtensibleNode = 446, + T_ErrorSaveContext = 447, + T_IdentifySystemCmd = 448, + T_BaseBackupCmd = 449, + T_CreateReplicationSlotCmd = 450, + T_DropReplicationSlotCmd = 451, + T_AlterReplicationSlotCmd = 452, + T_StartReplicationCmd = 453, + T_ReadReplicationSlotCmd = 454, + T_TimeLineHistoryCmd = 455, + T_UploadManifestCmd = 456, + T_SupportRequestSimplify = 457, + T_SupportRequestSelectivity = 458, + T_SupportRequestCost = 459, + T_SupportRequestRows = 460, + T_SupportRequestIndexCondition = 461, + T_SupportRequestWFuncMonotonic = 462, + T_SupportRequestOptimizeWindowClause = 463, + T_SupportRequestModifyInPlace = 464, + T_Integer = 465, + T_Float = 466, + T_Boolean = 467, + T_String = 468, + T_BitString = 469, + T_ForeignKeyCacheInfo = 470, + T_IntList = 471, + T_OidList = 472, + T_XidList = 473, + T_AllocSetContext = 474, + T_GenerationContext = 475, + T_SlabContext = 476, + T_BumpContext = 477, + T_TIDBitmap = 478, + T_WindowObjectData = 479, diff --git a/src/include/parser/parsenodes.h b/src/include/parser/parsenodes.h index cf0ee5bcd..7608230b9 100644 --- a/src/include/parser/parsenodes.h +++ b/src/include/parser/parsenodes.h @@ -12,8 +12,8 @@ * identifying statement boundaries in multi-statement source strings. * * - * Portions Copyright (c) 2003-2024, PgPool Global Development Group - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2003-2025, PgPool Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/nodes/parsenodes.h @@ -132,8 +132,13 @@ typedef struct Query * query identifier (can be set by plugins); ignored for equal, as it * might not be set; also not stored. This is the result of the query * jumble, hence ignored. + * + * We store this as a signed value as this is the form it's displayed to + * users in places such as EXPLAIN and pg_stat_statements. Primarily this + * is done due to lack of an SQL type to represent the full range of + * uint64. */ - uint64 queryId pg_node_attr(equal_ignore, query_jumble_ignore, read_write_ignore, read_as(0)); + int64 queryId pg_node_attr(equal_ignore, query_jumble_ignore, read_write_ignore, read_as(0)); /* do I set the command result tag? */ bool canSetTag pg_node_attr(query_jumble_ignore); @@ -165,6 +170,8 @@ typedef struct Query bool hasForUpdate pg_node_attr(query_jumble_ignore); /* rewriter has applied some RLS policy */ bool hasRowSecurity pg_node_attr(query_jumble_ignore); + /* parser has added an RTE_GROUP RTE */ + bool hasGroupRTE pg_node_attr(query_jumble_ignore); /* is a RETURN statement */ bool isReturn pg_node_attr(query_jumble_ignore); @@ -200,6 +207,15 @@ typedef struct Query OnConflictExpr *onConflict; /* ON CONFLICT DO [NOTHING | UPDATE] */ + /* + * The following three fields describe the contents of the RETURNING list + * for INSERT/UPDATE/DELETE/MERGE. returningOldAlias and returningNewAlias + * are the alias names for OLD and NEW, which may be user-supplied values, + * the defaults "old" and "new", or NULL (if the default "old"/"new" is + * already in use as the alias for some other relation). + */ + char *returningOldAlias pg_node_attr(query_jumble_ignore); + char *returningNewAlias pg_node_attr(query_jumble_ignore); List *returningList; /* return-values list (of TargetEntry) */ List *groupClause; /* a list of SortGroupClause's */ @@ -340,6 +356,14 @@ typedef struct A_Expr List *name; /* possibly-qualified name of operator */ Node *lexpr; /* left argument, or NULL if none */ Node *rexpr; /* right argument, or NULL if none */ + + /* + * If rexpr is a list of some kind, we separately track its starting and + * ending location; it's not the same as the starting and ending location + * of the token itself. + */ + ParseLoc rexpr_list_start; + ParseLoc rexpr_list_end; ParseLoc location; /* token location, or -1 if unknown */ } A_Expr; @@ -495,6 +519,8 @@ typedef struct A_ArrayExpr { NodeTag type; List *elements; /* array element expressions */ + ParseLoc list_start; /* start of the element list */ + ParseLoc list_end; /* end of the elements list */ ParseLoc location; /* token location, or -1 if unknown */ } A_ArrayExpr; @@ -731,7 +757,7 @@ typedef struct ColumnDef char *colname; /* name of column */ TypeName *typeName; /* type of column */ char *compression; /* compression method for column */ - int inhcount; /* number of times column is inherited */ + int16 inhcount; /* number of times column is inherited */ bool is_local; /* column has local (non-inherited) def'n */ bool is_not_null; /* NOT NULL constraint specified? */ bool is_from_type; /* column definition came from table type */ @@ -943,16 +969,6 @@ typedef struct PartitionRangeDatum } PartitionRangeDatum; /* - * PartitionDesc - used in reverted ALTER TABLE SPLIT PARTITION command - * - * Kept as a stub for nodetag ABI compatibility. - */ -typedef struct SinglePartitionSpec -{ - NodeTag type; -} SinglePartitionSpec; - -/* * PartitionCmd - info for ALTER TABLE/INDEX ATTACH/DETACH PARTITION commands */ typedef struct PartitionCmd @@ -1038,6 +1054,7 @@ typedef enum RTEKind RTE_RESULT, /* RTE represents an empty FROM clause; such * RTEs are added by the planner, they're not * present during parsing or rewriting */ + RTE_GROUP, /* the grouping step */ } RTEKind; typedef struct RangeTblEntry @@ -1053,8 +1070,13 @@ typedef struct RangeTblEntry */ /* user-written alias clause, if any */ Alias *alias pg_node_attr(query_jumble_ignore); - /* expanded reference names */ - Alias *eref pg_node_attr(query_jumble_ignore); + + /* + * Expanded reference names. This uses a custom query jumble function so + * that the table name is included in the computation, but not its list of + * columns. + */ + Alias *eref pg_node_attr(custom_query_jumble); RTEKind rtekind; /* see above */ @@ -1097,7 +1119,7 @@ typedef struct RangeTblEntry * tables to be invalidated if the underlying table is altered. */ /* OID of the relation */ - Oid relid; + Oid relid pg_node_attr(query_jumble_ignore); /* inheritance requested? */ bool inh; /* relation kind (see pg_class.relkind) */ @@ -1245,6 +1267,12 @@ typedef struct RangeTblEntry Cardinality enrtuples pg_node_attr(query_jumble_ignore); /* + * Fields valid for a GROUP RTE (else NIL): + */ + /* list of grouping expressions */ + List *groupexprs pg_node_attr(query_jumble_ignore); + + /* * Fields valid in all RTEs: */ /* was LATERAL specified? */ @@ -1444,6 +1472,7 @@ typedef struct SortGroupClause Index tleSortGroupRef; /* reference into targetlist */ Oid eqop; /* the equality operator ('=' op) */ Oid sortop; /* the ordering operator ('<' op), or 0 */ + bool reverse_sort; /* is sortop a "greater than" operator? */ bool nulls_first; /* do NULLs come before normal values? */ /* can eqop be implemented by hashing? */ bool hashable pg_node_attr(query_jumble_ignore); @@ -1732,6 +1761,41 @@ typedef struct MergeWhenClause } MergeWhenClause; /* + * ReturningOptionKind - + * Possible kinds of option in RETURNING WITH(...) list + * + * Currently, this is used only for specifying OLD/NEW aliases. + */ +typedef enum ReturningOptionKind +{ + RETURNING_OPTION_OLD, /* specify alias for OLD in RETURNING */ + RETURNING_OPTION_NEW, /* specify alias for NEW in RETURNING */ +} ReturningOptionKind; + +/* + * ReturningOption - + * An individual option in the RETURNING WITH(...) list + */ +typedef struct ReturningOption +{ + NodeTag type; + ReturningOptionKind option; /* specified option */ + char *value; /* option's value */ + ParseLoc location; /* token location, or -1 if unknown */ +} ReturningOption; + +/* + * ReturningClause - + * List of RETURNING expressions, together with any WITH(...) options + */ +typedef struct ReturningClause +{ + NodeTag type; + List *options; /* list of ReturningOption elements */ + List *exprs; /* list of expressions to return */ +} ReturningClause; + +/* * TriggerTransition - * representation of transition row or table naming clause * @@ -2048,7 +2112,7 @@ typedef struct InsertStmt List *cols; /* optional: names of the target columns */ Node *selectStmt; /* the source SELECT/VALUES, or NULL */ OnConflictClause *onConflictClause; /* ON CONFLICT clause */ - List *returningList; /* list of expressions to return */ + ReturningClause *returningClause; /* RETURNING clause */ WithClause *withClause; /* WITH clause */ OverridingKind override; /* OVERRIDING clause */ } InsertStmt; @@ -2063,7 +2127,7 @@ typedef struct DeleteStmt RangeVar *relation; /* relation to delete from */ List *usingClause; /* optional using clause for more tables */ Node *whereClause; /* qualifications */ - List *returningList; /* list of expressions to return */ + ReturningClause *returningClause; /* RETURNING clause */ WithClause *withClause; /* WITH clause */ } DeleteStmt; @@ -2078,7 +2142,7 @@ typedef struct UpdateStmt List *targetList; /* the target list (of ResTarget) */ Node *whereClause; /* qualifications */ List *fromClause; /* optional from clause for more tables */ - List *returningList; /* list of expressions to return */ + ReturningClause *returningClause; /* RETURNING clause */ WithClause *withClause; /* WITH clause */ } UpdateStmt; @@ -2093,7 +2157,7 @@ typedef struct MergeStmt Node *sourceRelation; /* source relation */ Node *joinCondition; /* join condition between source and target */ List *mergeWhenClauses; /* list of MergeWhenClause(es) */ - List *returningList; /* list of expressions to return */ + ReturningClause *returningClause; /* RETURNING clause */ WithClause *withClause; /* WITH clause */ } MergeStmt; @@ -2360,7 +2424,6 @@ typedef enum AlterTableType AT_SetNotNull, /* alter column set not null */ AT_SetExpression, /* alter column set expression */ AT_DropExpression, /* alter column drop expression */ - AT_CheckNotNull, /* check column is already marked not null */ AT_SetStatistics, /* alter column set statistics */ AT_SetOptions, /* alter column set ( options ) */ AT_ResetOptions, /* alter column reset ( options ) */ @@ -2421,13 +2484,6 @@ typedef enum AlterTableType AT_ReAddStatistics, /* internal to commands/tablecmds.c */ } AlterTableType; -typedef struct ReplicaIdentityStmt -{ - NodeTag type; - char identity_type; - char *name; -} ReplicaIdentityStmt; - typedef struct AlterTableCmd /* one subcommand of an ALTER TABLE */ { NodeTag type; @@ -2444,6 +2500,28 @@ typedef struct AlterTableCmd /* one subcommand of an ALTER TABLE */ bool recurse; /* exec-time recursion */ } AlterTableCmd; +/* Ad-hoc node for AT_AlterConstraint */ +typedef struct ATAlterConstraint +{ + NodeTag type; + char *conname; /* Constraint name */ + bool alterEnforceability; /* changing enforceability properties? */ + bool is_enforced; /* ENFORCED? */ + bool alterDeferrability; /* changing deferrability properties? */ + bool deferrable; /* DEFERRABLE? */ + bool initdeferred; /* INITIALLY DEFERRED? */ + bool alterInheritability; /* changing inheritability properties */ + bool noinherit; +} ATAlterConstraint; + +/* Ad-hoc node for AT_ReplicaIdentity */ +typedef struct ReplicaIdentityStmt +{ + NodeTag type; + char identity_type; + char *name; +} ReplicaIdentityStmt; + /* ---------------------- * Alter Collation @@ -2622,11 +2700,26 @@ typedef enum VariableSetKind typedef struct VariableSetStmt { + pg_node_attr(custom_query_jumble) + NodeTag type; VariableSetKind kind; - char *name; /* variable to be set */ - List *args; /* List of A_Const nodes */ - bool is_local; /* SET LOCAL? */ + /* variable to be set */ + char *name; + /* List of A_Const nodes */ + List *args; + + /* + * True if arguments should be accounted for in query jumbling. We use a + * separate flag rather than query_jumble_ignore on "args" as several + * grammar flavors of SET rely on a list of values that are parsed + * directly from the grammar's keywords. + */ + bool jumble_args; + /* SET LOCAL? */ + bool is_local; + /* token location, or -1 if unknown */ + ParseLoc location pg_node_attr(query_jumble_location); } VariableSetStmt; /* ---------------------- @@ -2643,10 +2736,10 @@ typedef struct VariableShowStmt * Create Table Statement * * NOTE: in the raw gram.y output, ColumnDef and Constraint nodes are - * intermixed in tableElts, and constraints is NIL. After parse analysis, - * tableElts contains just ColumnDefs, and constraints contains just - * Constraint nodes (in fact, only CONSTR_CHECK nodes, in the present - * implementation). + * intermixed in tableElts, and constraints and nnconstraints are NIL. After + * parse analysis, tableElts contains just ColumnDefs, nnconstraints contains + * Constraint nodes of CONSTR_NOTNULL type from various sources, and + * constraints contains just CONSTR_CHECK Constraint nodes. * ---------------------- */ @@ -2661,6 +2754,7 @@ typedef struct CreateStmt PartitionSpec *partspec; /* PARTITION BY clause */ TypeName *ofTypename; /* OF typename */ List *constraints; /* constraints (list of Constraint nodes) */ + List *nnconstraints; /* NOT NULL constraints (ditto) */ List *options; /* options from WITH clause */ OnCommitAction oncommit; /* what do we do at COMMIT? */ char *tablespacename; /* table space to use, or NULL */ @@ -2716,6 +2810,8 @@ typedef enum ConstrType /* types of constraints */ CONSTR_ATTR_NOT_DEFERRABLE, CONSTR_ATTR_DEFERRED, CONSTR_ATTR_IMMEDIATE, + CONSTR_ATTR_ENFORCED, + CONSTR_ATTR_NOT_ENFORCED, } ConstrType; /* Foreign key action codes */ @@ -2737,6 +2833,7 @@ typedef struct Constraint char *conname; /* Constraint name, or NULL if unnamed */ bool deferrable; /* DEFERRABLE? */ bool initdeferred; /* INITIALLY DEFERRED? */ + bool is_enforced; /* enforced constraint? */ bool skip_validation; /* skip validation of existing rows? */ bool initially_valid; /* mark the new constraint as valid? */ bool is_no_inherit; /* is constraint non-inheritable? */ @@ -2745,11 +2842,11 @@ typedef struct Constraint char *cooked_expr; /* CHECK or DEFAULT expression, as * nodeToString representation */ char generated_when; /* ALWAYS or BY DEFAULT */ - int inhcount; /* initial inheritance count to apply, for - * "raw" NOT NULL constraints */ + char generated_kind; /* STORED or VIRTUAL */ bool nulls_not_distinct; /* null treatment for UNIQUE constraints */ List *keys; /* String nodes naming referenced key * column(s); for UNIQUE/PK/NOT NULL */ + bool without_overlaps; /* WITHOUT OVERLAPS specified */ List *including; /* String nodes naming referenced nonkey * column(s); for UNIQUE/PK */ List *exclusions; /* list of (IndexElem, operator name) pairs; @@ -2766,6 +2863,8 @@ typedef struct Constraint RangeVar *pktable; /* Primary key table */ List *fk_attrs; /* Attributes of foreign key */ List *pk_attrs; /* Corresponding attrs in PK table */ + bool fk_with_period; /* Last attribute of FK uses PERIOD */ + bool pk_with_period; /* Last attribute of PK uses PERIOD */ char fk_matchtype; /* FULL, PARTIAL, SIMPLE */ char fk_upd_action; /* ON UPDATE action */ char fk_del_action; /* ON DELETE action */ @@ -3373,6 +3472,7 @@ typedef struct IndexStmt bool nulls_not_distinct; /* null treatment for UNIQUE constraints */ bool primary; /* is index a primary key? */ bool isconstraint; /* is it for a pkey/unique constraint? */ + bool iswithoutoverlaps; /* is the constraint WITHOUT OVERLAPS? */ bool deferrable; /* is the constraint DEFERRABLE? */ bool initdeferred; /* is the constraint INITIALLY DEFERRED? */ bool transformed; /* true when transformIndexStmt is finished */ @@ -3460,6 +3560,7 @@ typedef struct FunctionParameter TypeName *argType; /* TypeName for parameter type */ FunctionParameterMode mode; /* IN/OUT/etc */ Node *defexpr; /* raw default expr, or NULL if not given */ + ParseLoc location; /* token location, or -1 if unknown */ } FunctionParameter; typedef struct AlterFunctionStmt diff --git a/src/include/parser/parser.h b/src/include/parser/parser.h index e412c438e..70a08f145 100644 --- a/src/include/parser/parser.h +++ b/src/include/parser/parser.h @@ -5,8 +5,8 @@ * * This is the external API for the raw lexing/parsing functions. * - * Portions Copyright (c) 2003-2024, PgPool Global Development Group - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2003-2025, PgPool Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/parser/parser.h diff --git a/src/include/parser/pg_class.h b/src/include/parser/pg_class.h index 7ebf4c439..82438dede 100644 --- a/src/include/parser/pg_class.h +++ b/src/include/parser/pg_class.h @@ -4,8 +4,8 @@ * definition of the "relation" system catalog (pg_class) * * - * Portions Copyright (c) 2003-2024, PgPool Global Development Group - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2003-2025, PgPool Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/pg_class.h @@ -22,7 +22,7 @@ #if 0 /* NOT_USED_IN_PGPOOL */ #include "catalog/genbki.h" -#include "catalog/pg_class_d.h" +#include "catalog/pg_class_d.h" /* IWYU pragma: export */ CATALOG(pg_class,1259,RelationRelationId) BKI_BOOTSTRAP BKI_ROWTYPE_OID(83,RelationRelation_Rowtype_Id) BKI_SCHEMA_MACRO { @@ -63,6 +63,9 @@ CATALOG(pg_class,1259,RelationRelationId) BKI_BOOTSTRAP BKI_ROWTYPE_OID(83,Relat /* # of all-visible blocks (not always up-to-date) */ int32 relallvisible BKI_DEFAULT(0); + /* # of all-frozen blocks (not always up-to-date) */ + int32 relallfrozen BKI_DEFAULT(0); + /* OID of toast table; 0 if none */ Oid reltoastrelid BKI_DEFAULT(0) BKI_LOOKUP_OPT(pg_class); diff --git a/src/include/parser/pg_config_manual.h b/src/include/parser/pg_config_manual.h index f522dc2a0..cbea7dc1d 100644 --- a/src/include/parser/pg_config_manual.h +++ b/src/include/parser/pg_config_manual.h @@ -6,8 +6,8 @@ * for developers. If you edit any of these, be sure to do a *full* * rebuild (and an initdb if noted). * - * Portions Copyright (c) 2003-2024, PgPool Global Development Group - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2003-2025, PgPool Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/pg_config_manual.h @@ -104,21 +104,6 @@ #define USE_FLOAT8_BYVAL 1 #endif -/* - * When we don't have native spinlocks, we use semaphores to simulate them. - * Decreasing this value reduces consumption of OS resources; increasing it - * may improve performance, but supplying a real spinlock implementation is - * probably far better. - */ -#define NUM_SPINLOCK_SEMAPHORES 128 - -/* - * When we have neither spinlocks nor atomic operations support we're - * implementing atomic operations on top of spinlock on top of semaphores. To - * be safe against atomic operations while holding a spinlock separate - * semaphores have to be used. - */ -#define NUM_ATOMICS_SEMAPHORES 64 /* * MAXPGPATH: standard size of a pathname buffer in PostgreSQL (hence, @@ -172,9 +157,8 @@ /* * USE_PREFETCH code should be compiled only if we have a way to implement * prefetching. (This is decoupled from USE_POSIX_FADVISE because there - * might in future be support for alternative low-level prefetch APIs. - * If you change this, you probably need to adjust the error message in - * check_effective_io_concurrency.) + * might in future be support for alternative low-level prefetch APIs, + * as well as platform-specific APIs defined elsewhere.) */ #ifdef USE_POSIX_FADVISE #define USE_PREFETCH @@ -316,10 +300,10 @@ /* * For cache-invalidation debugging, define DISCARD_CACHES_ENABLED to enable - * use of the debug_discard_caches GUC to aggressively flush syscache/relcache - * entries whenever it's possible to deliver invalidations. See - * AcceptInvalidationMessages() in src/backend/utils/cache/inval.c for - * details. + * use of the debug_discard_caches GUC to aggressively flush + * syscache/relcache/relsynccache entries whenever it's possible to deliver + * invalidations. See AcceptInvalidationMessages() in + * src/backend/utils/cache/inval.c for details. * * USE_ASSERT_CHECKING builds default to enabling this. It's possible to use * DISCARD_CACHES_ENABLED without a cassert build and the implied @@ -354,31 +338,31 @@ /* #define RECOVER_RELATION_BUILD_MEMORY 1 */ /* Force enable */ /* - * Define this to force all parse and plan trees to be passed through - * copyObject(), to facilitate catching errors and omissions in - * copyObject(). + * Define DEBUG_NODE_TESTS_ENABLED to enable use of the GUCs + * debug_copy_parse_plan_trees, debug_write_read_parse_plan_trees, and + * debug_raw_expression_coverage_test, to test coverage of node support + * functions in src/backend/nodes/. + * + * USE_ASSERT_CHECKING builds default to enabling this. */ -/* #define COPY_PARSE_PLAN_TREES */ +/* #define DEBUG_NODE_TESTS_ENABLED */ -/* - * Define this to force Bitmapset reallocation on each modification. Helps - * to find dangling pointers to Bitmapset's. - */ -/* #define REALLOCATE_BITMAPSETS */ +#if defined(USE_ASSERT_CHECKING) && !defined(DEBUG_NODE_TESTS_ENABLED) +#define DEBUG_NODE_TESTS_ENABLED +#endif /* - * Define this to force all parse and plan trees to be passed through - * outfuncs.c/readfuncs.c, to facilitate catching errors and omissions in - * those modules. + * Backwards compatibility for the older compile-time-only node-tests macros. */ -/* #define WRITE_READ_PARSE_PLAN_TREES */ +#if !defined(DEBUG_NODE_TESTS_ENABLED) && (defined(COPY_PARSE_PLAN_TREES) || defined(WRITE_READ_PARSE_PLAN_TREES) || defined(RAW_EXPRESSION_COVERAGE_TEST)) +#define DEBUG_NODE_TESTS_ENABLED +#endif /* - * Define this to force all raw parse trees for DML statements to be scanned - * by raw_expression_tree_walker(), to facilitate catching errors and - * omissions in that function. + * Define this to force Bitmapset reallocation on each modification. Helps + * to find dangling pointers to Bitmapset's. */ -/* #define RAW_EXPRESSION_COVERAGE_TEST */ +/* #define REALLOCATE_BITMAPSETS */ /* * Define this to force all raw parse trees for DML statements to be scanned @@ -399,12 +383,6 @@ /* #define WAL_DEBUG */ /* - * Enable tracing of resource consumption during sort operations; - * see also the trace_sort GUC var. For 8.1 this is enabled by default. - */ -#define TRACE_SORT 1 - -/* * Enable tracing of syncscan operations (see also the trace_syncscan GUC var). */ /* #define TRACE_SYNCSCAN */ diff --git a/src/include/parser/pg_list.h b/src/include/parser/pg_list.h index 4a63a466d..99f334b84 100644 --- a/src/include/parser/pg_list.h +++ b/src/include/parser/pg_list.h @@ -29,8 +29,8 @@ * always be so; be careful to use the appropriate list type for your data.) * * - * Portions Copyright (c) 2003-2024, PgPool Global Development Group - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2003-2025, PgPool Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/nodes/pg_list.h @@ -493,7 +493,7 @@ for_each_cell_setup(const List *lst, const ListCell *initcell) for (ForEachState var##__state = {(lst), 0}; \ (var##__state.l != NIL && \ var##__state.i < var##__state.l->length && \ - (var = func(&var##__state.l->elements[var##__state.i]), true)); \ + (var = (type pointer) func(&var##__state.l->elements[var##__state.i]), true)); \ var##__state.i++) /* @@ -630,23 +630,23 @@ extern List *list_make5_impl(NodeTag t, ListCell datum1, ListCell datum2, #define pg_nodiscard #endif -extern pg_nodiscard List *lappend(List *list, void *datum); -extern pg_nodiscard List *lappend_int(List *list, int datum); -extern pg_nodiscard List *lappend_oid(List *list, Oid datum); -extern pg_nodiscard List *lappend_xid(List *list, TransactionId datum); +pg_nodiscard extern List *lappend(List *list, void *datum); +pg_nodiscard extern List *lappend_int(List *list, int datum); +pg_nodiscard extern List *lappend_oid(List *list, Oid datum); +pg_nodiscard extern List *lappend_xid(List *list, TransactionId datum); -extern pg_nodiscard List *list_insert_nth(List *list, int pos, void *datum); -extern pg_nodiscard List *list_insert_nth_int(List *list, int pos, int datum); -extern pg_nodiscard List *list_insert_nth_oid(List *list, int pos, Oid datum); +pg_nodiscard extern List *list_insert_nth(List *list, int pos, void *datum); +pg_nodiscard extern List *list_insert_nth_int(List *list, int pos, int datum); +pg_nodiscard extern List *list_insert_nth_oid(List *list, int pos, Oid datum); -extern pg_nodiscard List *lcons(void *datum, List *list); -extern pg_nodiscard List *lcons_int(int datum, List *list); -extern pg_nodiscard List *lcons_oid(Oid datum, List *list); +pg_nodiscard extern List *lcons(void *datum, List *list); +pg_nodiscard extern List *lcons_int(int datum, List *list); +pg_nodiscard extern List *lcons_oid(Oid datum, List *list); -extern pg_nodiscard List *list_concat(List *list1, const List *list2); -extern pg_nodiscard List *list_concat_copy(const List *list1, const List *list2); +pg_nodiscard extern List *list_concat(List *list1, const List *list2); +pg_nodiscard extern List *list_concat_copy(const List *list1, const List *list2); -extern pg_nodiscard List *list_truncate(List *list, int new_size); +pg_nodiscard extern List *list_truncate(List *list, int new_size); extern bool list_member(const List *list, const void *datum); extern bool list_member_ptr(const List *list, const void *datum); @@ -654,15 +654,15 @@ extern bool list_member_int(const List *list, int datum); extern bool list_member_oid(const List *list, Oid datum); extern bool list_member_xid(const List *list, TransactionId datum); -extern pg_nodiscard List *list_delete(List *list, void *datum); -extern pg_nodiscard List *list_delete_ptr(List *list, void *datum); -extern pg_nodiscard List *list_delete_int(List *list, int datum); -extern pg_nodiscard List *list_delete_oid(List *list, Oid datum); -extern pg_nodiscard List *list_delete_first(List *list); -extern pg_nodiscard List *list_delete_last(List *list); -extern pg_nodiscard List *list_delete_first_n(List *list, int n); -extern pg_nodiscard List *list_delete_nth_cell(List *list, int n); -extern pg_nodiscard List *list_delete_cell(List *list, ListCell *cell); +pg_nodiscard extern List *list_delete(List *list, void *datum); +pg_nodiscard extern List *list_delete_ptr(List *list, void *datum); +pg_nodiscard extern List *list_delete_int(List *list, int datum); +pg_nodiscard extern List *list_delete_oid(List *list, Oid datum); +pg_nodiscard extern List *list_delete_first(List *list); +pg_nodiscard extern List *list_delete_last(List *list); +pg_nodiscard extern List *list_delete_first_n(List *list, int n); +pg_nodiscard extern List *list_delete_nth_cell(List *list, int n); +pg_nodiscard extern List *list_delete_cell(List *list, ListCell *cell); extern List *list_union(const List *list1, const List *list2); extern List *list_union_ptr(const List *list1, const List *list2); @@ -679,25 +679,25 @@ extern List *list_difference_ptr(const List *list1, const List *list2); extern List *list_difference_int(const List *list1, const List *list2); extern List *list_difference_oid(const List *list1, const List *list2); -extern pg_nodiscard List *list_append_unique(List *list, void *datum); -extern pg_nodiscard List *list_append_unique_ptr(List *list, void *datum); -extern pg_nodiscard List *list_append_unique_int(List *list, int datum); -extern pg_nodiscard List *list_append_unique_oid(List *list, Oid datum); +pg_nodiscard extern List *list_append_unique(List *list, void *datum); +pg_nodiscard extern List *list_append_unique_ptr(List *list, void *datum); +pg_nodiscard extern List *list_append_unique_int(List *list, int datum); +pg_nodiscard extern List *list_append_unique_oid(List *list, Oid datum); -extern pg_nodiscard List *list_concat_unique(List *list1, const List *list2); -extern pg_nodiscard List *list_concat_unique_ptr(List *list1, const List *list2); -extern pg_nodiscard List *list_concat_unique_int(List *list1, const List *list2); -extern pg_nodiscard List *list_concat_unique_oid(List *list1, const List *list2); +pg_nodiscard extern List *list_concat_unique(List *list1, const List *list2); +pg_nodiscard extern List *list_concat_unique_ptr(List *list1, const List *list2); +pg_nodiscard extern List *list_concat_unique_int(List *list1, const List *list2); +pg_nodiscard extern List *list_concat_unique_oid(List *list1, const List *list2); extern void list_deduplicate_oid(List *list); extern void list_free(List *list); extern void list_free_deep(List *list); -extern pg_nodiscard List *list_copy(const List *oldlist); -extern pg_nodiscard List *list_copy_head(const List *oldlist, int len); -extern pg_nodiscard List *list_copy_tail(const List *oldlist, int nskip); -extern pg_nodiscard List *list_copy_deep(const List *oldlist); +pg_nodiscard extern List *list_copy(const List *oldlist); +pg_nodiscard extern List *list_copy_head(const List *oldlist, int len); +pg_nodiscard extern List *list_copy_tail(const List *oldlist, int nskip); +pg_nodiscard extern List *list_copy_deep(const List *oldlist); typedef int (*list_sort_comparator) (const ListCell *a, const ListCell *b); extern void list_sort(List *list, list_sort_comparator cmp); diff --git a/src/include/parser/pg_trigger.h b/src/include/parser/pg_trigger.h index 745fe049a..daec329dd 100644 --- a/src/include/parser/pg_trigger.h +++ b/src/include/parser/pg_trigger.h @@ -4,8 +4,8 @@ * definition of the "trigger" system catalog (pg_trigger) * * - * Portions Copyright (c) 2003-2024, PgPool Global Development Group - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2003-2025, PgPool Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/catalog/pg_trigger.h @@ -21,7 +21,7 @@ #if 0 #include "catalog/genbki.h" -#include "catalog/pg_trigger_d.h" +#include "catalog/pg_trigger_d.h" /* IWYU pragma: export */ /* ---------------- * pg_trigger definition. cpp turns this into diff --git a/src/include/parser/pg_wchar.h b/src/include/parser/pg_wchar.h index 59582d1ff..8612afd07 100644 --- a/src/include/parser/pg_wchar.h +++ b/src/include/parser/pg_wchar.h @@ -3,8 +3,8 @@ * pg_wchar.h * multibyte-character support * - * Portions Copyright (c) 2003-2024, PgPool Global Development Group - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2003-2025, PgPool Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/mb/pg_wchar.h @@ -663,7 +663,10 @@ extern int pg_valid_server_encoding_id(int encoding); * (in addition to the ones just above). The constant tables declared * earlier in this file are also available from libpgcommon. */ +extern void pg_encoding_set_invalid(int encoding, char *dst); extern int pg_encoding_mblen(int encoding, const char *mbstr); +extern int pg_encoding_mblen_or_incomplete(int encoding, const char *mbstr, + size_t remaining); extern int pg_encoding_mblen_bounded(int encoding, const char *mbstr); extern int pg_encoding_dsplen(int encoding, const char *mbstr); extern int pg_encoding_verifymbchar(int encoding, const char *mbstr, int len); @@ -768,9 +771,9 @@ extern void check_encoding_conversion_args(int src_encoding, int expected_src_encoding, int expected_dest_encoding); -extern void report_invalid_encoding(int encoding, const char *mbstr, int len) pg_attribute_noreturn(); -extern void report_untranslatable_char(int src_encoding, int dest_encoding, - const char *mbstr, int len) pg_attribute_noreturn(); +pg_noreturn extern void report_invalid_encoding(int encoding, const char *mbstr, int len); +pg_noreturn extern void report_untranslatable_char(int src_encoding, int dest_encoding, + const char *mbstr, int len); extern int local2local(const unsigned char *l, unsigned char *p, int len, int src_encoding, int dest_encoding, diff --git a/src/include/parser/pool_parser.h b/src/include/parser/pool_parser.h index f10a9f8da..6ea19070f 100644 --- a/src/include/parser/pool_parser.h +++ b/src/include/parser/pool_parser.h @@ -66,6 +66,26 @@ typedef unsigned int Index; */ #define endof(array) (&(array)[lengthof(array)]) +/* + * pg_noreturn corresponds to the C11 noreturn/_Noreturn function specifier. + * We can't use the standard name "noreturn" because some third-party code + * uses __attribute__((noreturn)) in headers, which would get confused if + * "noreturn" is defined to "_Noreturn", as is done by <stdnoreturn.h>. + * + * In a declaration, function specifiers go before the function name. The + * common style is to put them before the return type. (The MSVC fallback has + * the same requirement. The GCC fallback is more flexible.) + */ +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L +#define pg_noreturn _Noreturn +#elif defined(__GNUC__) || defined(__SUNPRO_C) +#define pg_noreturn __attribute__((noreturn)) +#elif defined(_MSC_VER) +#define pg_noreturn __declspec(noreturn) +#else +#define pg_noreturn +#endif + /* GCC and XLC support format attributes */ #if defined(__GNUC__) || defined(__IBMC__) #define pg_attribute_format_arg(a) __attribute__((format_arg(a))) @@ -78,16 +98,13 @@ typedef unsigned int Index; /* GCC, Sunpro and XLC support aligned, packed and noreturn */ #if defined(__GNUC__) || defined(__SUNPRO_C) || defined(__IBMC__) #define pg_attribute_aligned(a) __attribute__((aligned(a))) -#define pg_attribute_noreturn() __attribute__((noreturn)) #define pg_attribute_packed() __attribute__((packed)) -#define HAVE_PG_ATTRIBUTE_NORETURN 1 #else /* * NB: aligned and packed are not given default definitions because they * affect code functionality; they *must* be implemented by the compiler * if they are to be used. */ -#define pg_attribute_noreturn() #endif /* diff --git a/src/include/parser/primnodes.h b/src/include/parser/primnodes.h index 09be5529b..6fce8be0c 100644 --- a/src/include/parser/primnodes.h +++ b/src/include/parser/primnodes.h @@ -6,8 +6,8 @@ * Currently, these are mostly nodes for executable expressions * and join trees. * - * Portions Copyright (c) 2003-2024, PgPool Global Development Group - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2003-2025, PgPool Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/nodes/primnodes.h @@ -171,8 +171,8 @@ typedef struct TableFunc * For CREATE MATERIALIZED VIEW, viewQuery is the parsed-but-not-rewritten * SELECT Query for the view; otherwise it's NULL. This is irrelevant in * the query jumbling as CreateTableAsStmt already includes a reference to - * its own Query, so ignore it. (Although it's actually Query*, we declare - * it as Node* to avoid a forward reference.) + * its own Query, so ignore it. (We declare it as struct Query* to avoid a + * forward reference.) */ typedef struct IntoClause { @@ -185,7 +185,7 @@ typedef struct IntoClause OnCommitAction onCommit; /* what do we do at COMMIT? */ char *tableSpaceName; /* table space to use, or NULL */ /* materialized view's SELECT query */ - Node *viewQuery pg_node_attr(query_jumble_ignore); + struct Query *viewQuery pg_node_attr(query_jumble_ignore); bool skipData; /* true for WITH NO DATA */ } IntoClause; @@ -242,6 +242,11 @@ typedef struct Expr * Note that it affects the meaning of all of varno, varnullingrels, and * varnosyn, all of which refer to the range table of that query level. * + * varreturningtype is used for Vars that refer to the target relation in the + * RETURNING list of data-modifying queries. The default behavior is to + * return old values for DELETE and new values for INSERT and UPDATE, but it + * is also possible to explicitly request old or new values. + * * In the parser, varnosyn and varattnosyn are either identical to * varno/varattno, or they specify the column's position in an aliased JOIN * RTE that hides the semantic referent RTE's refname. This is a syntactic @@ -263,6 +268,14 @@ typedef struct Expr #define PRS2_OLD_VARNO 1 #define PRS2_NEW_VARNO 2 +/* Returning behavior for Vars in RETURNING list */ +typedef enum VarReturningType +{ + VAR_RETURNING_DEFAULT, /* return OLD for DELETE, else return NEW */ + VAR_RETURNING_OLD, /* return OLD for DELETE/UPDATE, else NULL */ + VAR_RETURNING_NEW, /* return NEW for INSERT/UPDATE, else NULL */ +} VarReturningType; + typedef struct Var { Expr xpr; @@ -298,6 +311,9 @@ typedef struct Var */ Index varlevelsup; + /* returning type of this var (see above) */ + VarReturningType varreturningtype; + /* * varnosyn/varattnosyn are ignored for equality, because Vars with * different syntactic identifiers are semantically the same as long as @@ -391,14 +407,16 @@ typedef enum ParamKind typedef struct Param { + pg_node_attr(custom_query_jumble) + Expr xpr; ParamKind paramkind; /* kind of parameter. See above */ int paramid; /* numeric ID for parameter */ Oid paramtype; /* pg_type OID of parameter's datatype */ /* typmod value, if known */ - int32 paramtypmod pg_node_attr(query_jumble_ignore); + int32 paramtypmod; /* OID of collation, or InvalidOid if none */ - Oid paramcollid pg_node_attr(query_jumble_ignore); + Oid paramcollid; /* token location, or -1 if unknown */ ParseLoc location; } Param; @@ -1396,9 +1414,13 @@ typedef struct ArrayExpr /* common type of array elements */ Oid element_typeid pg_node_attr(query_jumble_ignore); /* the array elements or sub-arrays */ - List *elements; + List *elements pg_node_attr(query_jumble_squash); /* true if elements are sub-arrays */ bool multidims pg_node_attr(query_jumble_ignore); + /* location of the start of the elements list */ + ParseLoc list_start; + /* location of the end of the elements list */ + ParseLoc list_end; /* token location, or -1 if unknown */ ParseLoc location; } ArrayExpr; @@ -1455,6 +1477,34 @@ typedef struct RowExpr } RowExpr; /* + * CompareType - fundamental semantics of certain operators + * + * These enum symbols represent the fundamental semantics of certain operators + * that the system needs to have some hardcoded knowledge about. (For + * example, RowCompareExpr needs to know which operators can be determined to + * act like =, <>, <, etc.) Index access methods map (some of) strategy + * numbers to these values so that the system can know about the meaning of + * (some of) the operators without needing hardcoded knowledge of index AM's + * strategy numbering. + * + * XXX Currently, this mapping is not fully developed and most values are + * chosen to match btree strategy numbers, which is not going to work very + * well for other access methods. + */ +typedef enum CompareType +{ + COMPARE_INVALID = 0, + COMPARE_LT = 1, /* BTLessStrategyNumber */ + COMPARE_LE = 2, /* BTLessEqualStrategyNumber */ + COMPARE_EQ = 3, /* BTEqualStrategyNumber */ + COMPARE_GE = 4, /* BTGreaterEqualStrategyNumber */ + COMPARE_GT = 5, /* BTGreaterStrategyNumber */ + COMPARE_NE = 6, /* no such btree strategy */ + COMPARE_OVERLAP, + COMPARE_CONTAINED_BY, +} CompareType; + +/* * RowCompareExpr - row-wise comparison, such as (a, b) <= (1, 2) * * We support row comparison for any operator that can be determined to @@ -1465,26 +1515,14 @@ typedef struct RowExpr * * A RowCompareExpr node is only generated for the < <= > >= cases; * the = and <> cases are translated to simple AND or OR combinations - * of the pairwise comparisons. However, we include = and <> in the - * RowCompareType enum for the convenience of parser logic. + * of the pairwise comparisons. */ -typedef enum RowCompareType -{ - /* Values of this enum are chosen to match btree strategy numbers */ - ROWCOMPARE_LT = 1, /* BTLessStrategyNumber */ - ROWCOMPARE_LE = 2, /* BTLessEqualStrategyNumber */ - ROWCOMPARE_EQ = 3, /* BTEqualStrategyNumber */ - ROWCOMPARE_GE = 4, /* BTGreaterEqualStrategyNumber */ - ROWCOMPARE_GT = 5, /* BTGreaterStrategyNumber */ - ROWCOMPARE_NE = 6, /* no such btree strategy */ -} RowCompareType; - typedef struct RowCompareExpr { Expr xpr; /* LT LE GE or GT, never EQ or NE */ - RowCompareType rctype; + CompareType cmptype; /* OID list of pairwise comparison ops */ List *opnos pg_node_attr(query_jumble_ignore); /* OID list of containing operator families */ @@ -1688,15 +1726,19 @@ typedef struct JsonReturning * JsonValueExpr - * representation of JSON value expression (expr [FORMAT JsonFormat]) * - * The actual value is obtained by evaluating formatted_expr. raw_expr is - * only there for displaying the original user-written expression and is not - * evaluated by ExecInterpExpr() and eval_const_expressions_mutator(). + * raw_expr is the user-specified value, while formatted_expr is the value + * obtained by coercing raw_expr to the type required by either the FORMAT + * clause or an enclosing node's RETURNING clause. + * + * When deparsing a JsonValueExpr, get_rule_expr() prints raw_expr. However, + * during the evaluation of a JsonValueExpr, the value of formatted_expr + * takes precedence over that of raw_expr. */ typedef struct JsonValueExpr { NodeTag type; - Expr *raw_expr; /* raw expression */ - Expr *formatted_expr; /* formatted expression */ + Expr *raw_expr; /* user-specified expression */ + Expr *formatted_expr; /* coerced formatted expression */ JsonFormat *format; /* FORMAT clause, if specified */ } JsonValueExpr; @@ -2143,6 +2185,30 @@ typedef struct InferenceElem Oid inferopclass; /* OID of att opclass, or InvalidOid */ } InferenceElem; +/* + * ReturningExpr - return OLD/NEW.(expression) in RETURNING list + * + * This is used when updating an auto-updatable view and returning a view + * column that is not simply a Var referring to the base relation. In such + * cases, OLD/NEW.viewcol can expand to an arbitrary expression, but the + * result is required to be NULL if the OLD/NEW row doesn't exist. To handle + * this, the rewriter wraps the expanded expression in a ReturningExpr, which + * is equivalent to "CASE WHEN (OLD/NEW row exists) THEN (expr) ELSE NULL". + * + * A similar situation can arise when rewriting the RETURNING clause of a + * rule, which may also contain arbitrary expressions. + * + * ReturningExpr nodes never appear in a parsed Query --- they are only ever + * inserted by the rewriter and the planner. + */ +typedef struct ReturningExpr +{ + Expr xpr; + int retlevelsup; /* > 0 if it belongs to outer query */ + bool retold; /* true for OLD, false for NEW */ + Expr *retexpr; /* expression to be returned */ +} ReturningExpr; + /*-------------------- * TargetEntry - * a target entry (used in query target lists) diff --git a/src/include/parser/scanner.h b/src/include/parser/scanner.h index 8c78b0a57..69deaeb48 100644 --- a/src/include/parser/scanner.h +++ b/src/include/parser/scanner.h @@ -8,8 +8,8 @@ * higher-level API provided by parser.h. * * - * Portions Copyright (c) 2003-2024, PgPool Global Development Group - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2003-2025, PgPool Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/parser/scanner.h @@ -148,6 +148,6 @@ extern void setup_scanner_errposition_callback(ScannerCallbackState *scbstate, core_yyscan_t yyscanner, int location); extern void cancel_scanner_errposition_callback(ScannerCallbackState *scbstate); -extern void scanner_yyerror(const char *message, core_yyscan_t yyscanner) pg_attribute_noreturn(); +pg_noreturn extern void scanner_yyerror(const char *message, core_yyscan_t yyscanner); #endif /* SCANNER_H */ diff --git a/src/include/parser/scansup.h b/src/include/parser/scansup.h index 319b12800..ef5e618be 100644 --- a/src/include/parser/scansup.h +++ b/src/include/parser/scansup.h @@ -3,8 +3,8 @@ * scansup.h * scanner support routines used by the core lexer * - * Portions Copyright (c) 2003-2024, PgPool Global Development Group - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2003-2025, PgPool Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/parser/scansup.h diff --git a/src/include/parser/stringinfo.h b/src/include/parser/stringinfo.h index 16515b0b1..1897c96bb 100644 --- a/src/include/parser/stringinfo.h +++ b/src/include/parser/stringinfo.h @@ -8,8 +8,8 @@ * (null-terminated text) or arbitrary binary data. All storage is allocated * with palloc() (falling back to malloc in frontend code). * - * Portions Copyright (c) 2003-2024, PgPool Global Development Group - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2003-2025, PgPool Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * src/include/lib/stringinfo.h @@ -104,11 +104,15 @@ typedef StringInfoData *StringInfo; /*------------------------ - * There are four ways to create a StringInfo object initially: + * There are six ways to create a StringInfo object initially: * * StringInfo stringptr = makeStringInfo(); * Both the StringInfoData and the data buffer are palloc'd. * + * StringInfo stringptr = makeStringInfoExt(initsize); + * Same as makeStringInfo except the data buffer is allocated + * with size 'initsize'. + * * StringInfoData string; * initStringInfo(&string); * The data buffer is palloc'd but the StringInfoData is just local. @@ -116,6 +120,11 @@ typedef StringInfoData *StringInfo; * only live as long as the current routine. * * StringInfoData string; + * initStringInfoExt(&string, initsize); + * Same as initStringInfo except the data buffer is allocated + * with size 'initsize'. + * + * StringInfoData string; * initReadOnlyStringInfo(&string, existingbuf, len); * The StringInfoData's data field is set to point directly to the * existing buffer and the StringInfoData's len is set to the given len. @@ -149,6 +158,8 @@ typedef StringInfoData *StringInfo; *------------------------- */ +#define STRINGINFO_DEFAULT_SIZE 1024 /* default initial allocation size */ + /*------------------------ * makeStringInfo * Create an empty 'StringInfoData' & return a pointer to it. @@ -156,6 +167,14 @@ typedef StringInfoData *StringInfo; extern StringInfo makeStringInfo(void); /*------------------------ + * makeStringInfoExt + * Create an empty 'StringInfoData' & return a pointer to it. + * The data buffer is allocated with size 'initsize'. + * The valid range for 'initsize' is 1 to MaxAllocSize. + */ +extern StringInfo makeStringInfoExt(int initsize); + +/*------------------------ * initStringInfo * Initialize a StringInfoData struct (with previously undefined contents) * to describe an empty string. @@ -163,6 +182,14 @@ extern StringInfo makeStringInfo(void); extern void initStringInfo(StringInfo str); /*------------------------ + * initStringInfoExt + * Initialize a StringInfoData struct (with previously undefined contents) to + * describe an empty string. The data buffer is allocated with size + * 'initsize'. The valid range for 'initsize' is 1 to MaxAllocSize. + */ +extern void initStringInfoExt(StringInfo str, int initsize); + +/*------------------------ * initReadOnlyStringInfo * Initialize a StringInfoData struct from an existing string without copying * the string. The caller is responsible for ensuring the given string diff --git a/src/include/parser/unicode_east_asian_fw_table.h b/src/include/parser/unicode_east_asian_fw_table.h new file mode 100644 index 000000000..db8bd0ad8 --- /dev/null +++ b/src/include/parser/unicode_east_asian_fw_table.h @@ -0,0 +1,126 @@ +/* generated by src/common/unicode/generate-unicode_east_asian_fw_table.pl, do not edit */ + +static const struct mbinterval east_asian_fw[] = { + {0x1100, 0x115F}, + {0x231A, 0x231B}, + {0x2329, 0x232A}, + {0x23E9, 0x23EC}, + {0x23F0, 0x23F0}, + {0x23F3, 0x23F3}, + {0x25FD, 0x25FE}, + {0x2614, 0x2615}, + {0x2630, 0x2637}, + {0x2648, 0x2653}, + {0x267F, 0x267F}, + {0x268A, 0x268F}, + {0x2693, 0x2693}, + {0x26A1, 0x26A1}, + {0x26AA, 0x26AB}, + {0x26BD, 0x26BE}, + {0x26C4, 0x26C5}, + {0x26CE, 0x26CE}, + {0x26D4, 0x26D4}, + {0x26EA, 0x26EA}, + {0x26F2, 0x26F3}, + {0x26F5, 0x26F5}, + {0x26FA, 0x26FA}, + {0x26FD, 0x26FD}, + {0x2705, 0x2705}, + {0x270A, 0x270B}, + {0x2728, 0x2728}, + {0x274C, 0x274C}, + {0x274E, 0x274E}, + {0x2753, 0x2755}, + {0x2757, 0x2757}, + {0x2795, 0x2797}, + {0x27B0, 0x27B0}, + {0x27BF, 0x27BF}, + {0x2B1B, 0x2B1C}, + {0x2B50, 0x2B50}, + {0x2B55, 0x2B55}, + {0x2E80, 0x2E99}, + {0x2E9B, 0x2EF3}, + {0x2F00, 0x2FD5}, + {0x2FF0, 0x303E}, + {0x3041, 0x3096}, + {0x3099, 0x30FF}, + {0x3105, 0x312F}, + {0x3131, 0x318E}, + {0x3190, 0x31E5}, + {0x31EF, 0x321E}, + {0x3220, 0x3247}, + {0x3250, 0xA48C}, + {0xA490, 0xA4C6}, + {0xA960, 0xA97C}, + {0xAC00, 0xD7A3}, + {0xF900, 0xFAFF}, + {0xFE10, 0xFE19}, + {0xFE30, 0xFE52}, + {0xFE54, 0xFE66}, + {0xFE68, 0xFE6B}, + {0xFF01, 0xFF60}, + {0xFFE0, 0xFFE6}, + {0x16FE0, 0x16FE4}, + {0x16FF0, 0x16FF1}, + {0x17000, 0x187F7}, + {0x18800, 0x18CD5}, + {0x18CFF, 0x18D08}, + {0x1AFF0, 0x1AFF3}, + {0x1AFF5, 0x1AFFB}, + {0x1AFFD, 0x1AFFE}, + {0x1B000, 0x1B122}, + {0x1B132, 0x1B132}, + {0x1B150, 0x1B152}, + {0x1B155, 0x1B155}, + {0x1B164, 0x1B167}, + {0x1B170, 0x1B2FB}, + {0x1D300, 0x1D356}, + {0x1D360, 0x1D376}, + {0x1F004, 0x1F004}, + {0x1F0CF, 0x1F0CF}, + {0x1F18E, 0x1F18E}, + {0x1F191, 0x1F19A}, + {0x1F200, 0x1F202}, + {0x1F210, 0x1F23B}, + {0x1F240, 0x1F248}, + {0x1F250, 0x1F251}, + {0x1F260, 0x1F265}, + {0x1F300, 0x1F320}, + {0x1F32D, 0x1F335}, + {0x1F337, 0x1F37C}, + {0x1F37E, 0x1F393}, + {0x1F3A0, 0x1F3CA}, + {0x1F3CF, 0x1F3D3}, + {0x1F3E0, 0x1F3F0}, + {0x1F3F4, 0x1F3F4}, + {0x1F3F8, 0x1F43E}, + {0x1F440, 0x1F440}, + {0x1F442, 0x1F4FC}, + {0x1F4FF, 0x1F53D}, + {0x1F54B, 0x1F54E}, + {0x1F550, 0x1F567}, + {0x1F57A, 0x1F57A}, + {0x1F595, 0x1F596}, + {0x1F5A4, 0x1F5A4}, + {0x1F5FB, 0x1F64F}, + {0x1F680, 0x1F6C5}, + {0x1F6CC, 0x1F6CC}, + {0x1F6D0, 0x1F6D2}, + {0x1F6D5, 0x1F6D7}, + {0x1F6DC, 0x1F6DF}, + {0x1F6EB, 0x1F6EC}, + {0x1F6F4, 0x1F6FC}, + {0x1F7E0, 0x1F7EB}, + {0x1F7F0, 0x1F7F0}, + {0x1F90C, 0x1F93A}, + {0x1F93C, 0x1F945}, + {0x1F947, 0x1F9FF}, + {0x1FA70, 0x1FA7C}, + {0x1FA80, 0x1FA89}, + {0x1FA8F, 0x1FAC6}, + {0x1FACE, 0x1FADC}, + {0x1FADF, 0x1FAE9}, + {0x1FAF0, 0x1FAF8}, + {0x20000, 0x2FFFD}, + {0x30000, 0x3FFFD}, +}; diff --git a/src/include/parser/unicode_nonspacing_table.h b/src/include/parser/unicode_nonspacing_table.h new file mode 100644 index 000000000..d67f5b3f2 --- /dev/null +++ b/src/include/parser/unicode_nonspacing_table.h @@ -0,0 +1,338 @@ +/* generated by src/common/unicode/generate-unicode_nonspacing_table.pl, do not edit */ + +static const struct mbinterval nonspacing[] = { + {0x00AD, 0x00AD}, + {0x0300, 0x036F}, + {0x0483, 0x0489}, + {0x0591, 0x05BD}, + {0x05BF, 0x05BF}, + {0x05C1, 0x05C2}, + {0x05C4, 0x05C5}, + {0x05C7, 0x05C7}, + {0x0600, 0x0605}, + {0x0610, 0x061A}, + {0x061C, 0x061C}, + {0x064B, 0x065F}, + {0x0670, 0x0670}, + {0x06D6, 0x06DD}, + {0x06DF, 0x06E4}, + {0x06E7, 0x06E8}, + {0x06EA, 0x06ED}, + {0x070F, 0x070F}, + {0x0711, 0x0711}, + {0x0730, 0x074A}, + {0x07A6, 0x07B0}, + {0x07EB, 0x07F3}, + {0x07FD, 0x07FD}, + {0x0816, 0x0819}, + {0x081B, 0x0823}, + {0x0825, 0x0827}, + {0x0829, 0x082D}, + {0x0859, 0x085B}, + {0x0890, 0x089F}, + {0x08CA, 0x0902}, + {0x093A, 0x093A}, + {0x093C, 0x093C}, + {0x0941, 0x0948}, + {0x094D, 0x094D}, + {0x0951, 0x0957}, + {0x0962, 0x0963}, + {0x0981, 0x0981}, + {0x09BC, 0x09BC}, + {0x09C1, 0x09C4}, + {0x09CD, 0x09CD}, + {0x09E2, 0x09E3}, + {0x09FE, 0x0A02}, + {0x0A3C, 0x0A3C}, + {0x0A41, 0x0A51}, + {0x0A70, 0x0A71}, + {0x0A75, 0x0A75}, + {0x0A81, 0x0A82}, + {0x0ABC, 0x0ABC}, + {0x0AC1, 0x0AC8}, + {0x0ACD, 0x0ACD}, + {0x0AE2, 0x0AE3}, + {0x0AFA, 0x0B01}, + {0x0B3C, 0x0B3C}, + {0x0B3F, 0x0B3F}, + {0x0B41, 0x0B44}, + {0x0B4D, 0x0B56}, + {0x0B62, 0x0B63}, + {0x0B82, 0x0B82}, + {0x0BC0, 0x0BC0}, + {0x0BCD, 0x0BCD}, + {0x0C00, 0x0C00}, + {0x0C04, 0x0C04}, + {0x0C3C, 0x0C3C}, + {0x0C3E, 0x0C40}, + {0x0C46, 0x0C56}, + {0x0C62, 0x0C63}, + {0x0C81, 0x0C81}, + {0x0CBC, 0x0CBC}, + {0x0CBF, 0x0CBF}, + {0x0CC6, 0x0CC6}, + {0x0CCC, 0x0CCD}, + {0x0CE2, 0x0CE3}, + {0x0D00, 0x0D01}, + {0x0D3B, 0x0D3C}, + {0x0D41, 0x0D44}, + {0x0D4D, 0x0D4D}, + {0x0D62, 0x0D63}, + {0x0D81, 0x0D81}, + {0x0DCA, 0x0DCA}, + {0x0DD2, 0x0DD6}, + {0x0E31, 0x0E31}, + {0x0E34, 0x0E3A}, + {0x0E47, 0x0E4E}, + {0x0EB1, 0x0EB1}, + {0x0EB4, 0x0EBC}, + {0x0EC8, 0x0ECE}, + {0x0F18, 0x0F19}, + {0x0F35, 0x0F35}, + {0x0F37, 0x0F37}, + {0x0F39, 0x0F39}, + {0x0F71, 0x0F7E}, + {0x0F80, 0x0F84}, + {0x0F86, 0x0F87}, + {0x0F8D, 0x0FBC}, + {0x0FC6, 0x0FC6}, + {0x102D, 0x1030}, + {0x1032, 0x1037}, + {0x1039, 0x103A}, + {0x103D, 0x103E}, + {0x1058, 0x1059}, + {0x105E, 0x1060}, + {0x1071, 0x1074}, + {0x1082, 0x1082}, + {0x1085, 0x1086}, + {0x108D, 0x108D}, + {0x109D, 0x109D}, + {0x135D, 0x135F}, + {0x1712, 0x1714}, + {0x1732, 0x1733}, + {0x1752, 0x1753}, + {0x1772, 0x1773}, + {0x17B4, 0x17B5}, + {0x17B7, 0x17BD}, + {0x17C6, 0x17C6}, + {0x17C9, 0x17D3}, + {0x17DD, 0x17DD}, + {0x180B, 0x180F}, + {0x1885, 0x1886}, + {0x18A9, 0x18A9}, + {0x1920, 0x1922}, + {0x1927, 0x1928}, + {0x1932, 0x1932}, + {0x1939, 0x193B}, + {0x1A17, 0x1A18}, + {0x1A1B, 0x1A1B}, + {0x1A56, 0x1A56}, + {0x1A58, 0x1A60}, + {0x1A62, 0x1A62}, + {0x1A65, 0x1A6C}, + {0x1A73, 0x1A7F}, + {0x1AB0, 0x1B03}, + {0x1B34, 0x1B34}, + {0x1B36, 0x1B3A}, + {0x1B3C, 0x1B3C}, + {0x1B42, 0x1B42}, + {0x1B6B, 0x1B73}, + {0x1B80, 0x1B81}, + {0x1BA2, 0x1BA5}, + {0x1BA8, 0x1BA9}, + {0x1BAB, 0x1BAD}, + {0x1BE6, 0x1BE6}, + {0x1BE8, 0x1BE9}, + {0x1BED, 0x1BED}, + {0x1BEF, 0x1BF1}, + {0x1C2C, 0x1C33}, + {0x1C36, 0x1C37}, + {0x1CD0, 0x1CD2}, + {0x1CD4, 0x1CE0}, + {0x1CE2, 0x1CE8}, + {0x1CED, 0x1CED}, + {0x1CF4, 0x1CF4}, + {0x1CF8, 0x1CF9}, + {0x1DC0, 0x1DFF}, + {0x200B, 0x200F}, + {0x202A, 0x202E}, + {0x2060, 0x206F}, + {0x20D0, 0x20F0}, + {0x2CEF, 0x2CF1}, + {0x2D7F, 0x2D7F}, + {0x2DE0, 0x2DFF}, + {0x302A, 0x302D}, + {0x3099, 0x309A}, + {0xA66F, 0xA672}, + {0xA674, 0xA67D}, + {0xA69E, 0xA69F}, + {0xA6F0, 0xA6F1}, + {0xA802, 0xA802}, + {0xA806, 0xA806}, + {0xA80B, 0xA80B}, + {0xA825, 0xA826}, + {0xA82C, 0xA82C}, + {0xA8C4, 0xA8C5}, + {0xA8E0, 0xA8F1}, + {0xA8FF, 0xA8FF}, + {0xA926, 0xA92D}, + {0xA947, 0xA951}, + {0xA980, 0xA982}, + {0xA9B3, 0xA9B3}, + {0xA9B6, 0xA9B9}, + {0xA9BC, 0xA9BD}, + {0xA9E5, 0xA9E5}, + {0xAA29, 0xAA2E}, + {0xAA31, 0xAA32}, + {0xAA35, 0xAA36}, + {0xAA43, 0xAA43}, + {0xAA4C, 0xAA4C}, + {0xAA7C, 0xAA7C}, + {0xAAB0, 0xAAB0}, + {0xAAB2, 0xAAB4}, + {0xAAB7, 0xAAB8}, + {0xAABE, 0xAABF}, + {0xAAC1, 0xAAC1}, + {0xAAEC, 0xAAED}, + {0xAAF6, 0xAAF6}, + {0xABE5, 0xABE5}, + {0xABE8, 0xABE8}, + {0xABED, 0xABED}, + {0xFB1E, 0xFB1E}, + {0xFE00, 0xFE0F}, + {0xFE20, 0xFE2F}, + {0xFEFF, 0xFEFF}, + {0xFFF9, 0xFFFB}, + {0x101FD, 0x101FD}, + {0x102E0, 0x102E0}, + {0x10376, 0x1037A}, + {0x10A01, 0x10A0F}, + {0x10A38, 0x10A3F}, + {0x10AE5, 0x10AE6}, + {0x10D24, 0x10D27}, + {0x10D69, 0x10D6D}, + {0x10EAB, 0x10EAC}, + {0x10EFC, 0x10EFF}, + {0x10F46, 0x10F50}, + {0x10F82, 0x10F85}, + {0x11001, 0x11001}, + {0x11038, 0x11046}, + {0x11070, 0x11070}, + {0x11073, 0x11074}, + {0x1107F, 0x11081}, + {0x110B3, 0x110B6}, + {0x110B9, 0x110BA}, + {0x110BD, 0x110BD}, + {0x110C2, 0x110CD}, + {0x11100, 0x11102}, + {0x11127, 0x1112B}, + {0x1112D, 0x11134}, + {0x11173, 0x11173}, + {0x11180, 0x11181}, + {0x111B6, 0x111BE}, + {0x111C9, 0x111CC}, + {0x111CF, 0x111CF}, + {0x1122F, 0x11231}, + {0x11234, 0x11234}, + {0x11236, 0x11237}, + {0x1123E, 0x1123E}, + {0x11241, 0x11241}, + {0x112DF, 0x112DF}, + {0x112E3, 0x112EA}, + {0x11300, 0x11301}, + {0x1133B, 0x1133C}, + {0x11340, 0x11340}, + {0x11366, 0x11374}, + {0x113BB, 0x113C0}, + {0x113CE, 0x113CE}, + {0x113D0, 0x113D0}, + {0x113D2, 0x113D2}, + {0x113E1, 0x113E2}, + {0x11438, 0x1143F}, + {0x11442, 0x11444}, + {0x11446, 0x11446}, + {0x1145E, 0x1145E}, + {0x114B3, 0x114B8}, + {0x114BA, 0x114BA}, + {0x114BF, 0x114C0}, + {0x114C2, 0x114C3}, + {0x115B2, 0x115B5}, + {0x115BC, 0x115BD}, + {0x115BF, 0x115C0}, + {0x115DC, 0x115DD}, + {0x11633, 0x1163A}, + {0x1163D, 0x1163D}, + {0x1163F, 0x11640}, + {0x116AB, 0x116AB}, + {0x116AD, 0x116AD}, + {0x116B0, 0x116B5}, + {0x116B7, 0x116B7}, + {0x1171D, 0x1171D}, + {0x1171F, 0x1171F}, + {0x11722, 0x11725}, + {0x11727, 0x1172B}, + {0x1182F, 0x11837}, + {0x11839, 0x1183A}, + {0x1193B, 0x1193C}, + {0x1193E, 0x1193E}, + {0x11943, 0x11943}, + {0x119D4, 0x119DB}, + {0x119E0, 0x119E0}, + {0x11A01, 0x11A0A}, + {0x11A33, 0x11A38}, + {0x11A3B, 0x11A3E}, + {0x11A47, 0x11A47}, + {0x11A51, 0x11A56}, + {0x11A59, 0x11A5B}, + {0x11A8A, 0x11A96}, + {0x11A98, 0x11A99}, + {0x11C30, 0x11C3D}, + {0x11C3F, 0x11C3F}, + {0x11C92, 0x11CA7}, + {0x11CAA, 0x11CB0}, + {0x11CB2, 0x11CB3}, + {0x11CB5, 0x11CB6}, + {0x11D31, 0x11D45}, + {0x11D47, 0x11D47}, + {0x11D90, 0x11D91}, + {0x11D95, 0x11D95}, + {0x11D97, 0x11D97}, + {0x11EF3, 0x11EF4}, + {0x11F00, 0x11F01}, + {0x11F36, 0x11F3A}, + {0x11F40, 0x11F40}, + {0x11F42, 0x11F42}, + {0x11F5A, 0x11F5A}, + {0x13430, 0x13440}, + {0x13447, 0x13455}, + {0x1611E, 0x16129}, + {0x1612D, 0x1612F}, + {0x16AF0, 0x16AF4}, + {0x16B30, 0x16B36}, + {0x16F4F, 0x16F4F}, + {0x16F8F, 0x16F92}, + {0x16FE4, 0x16FE4}, + {0x1BC9D, 0x1BC9E}, + {0x1BCA0, 0x1BCA3}, + {0x1CF00, 0x1CF46}, + {0x1D167, 0x1D169}, + {0x1D173, 0x1D182}, + {0x1D185, 0x1D18B}, + {0x1D1AA, 0x1D1AD}, + {0x1D242, 0x1D244}, + {0x1DA00, 0x1DA36}, + {0x1DA3B, 0x1DA6C}, + {0x1DA75, 0x1DA75}, + {0x1DA84, 0x1DA84}, + {0x1DA9B, 0x1DAAF}, + {0x1E000, 0x1E02A}, + {0x1E08F, 0x1E08F}, + {0x1E130, 0x1E136}, + {0x1E2AE, 0x1E2AE}, + {0x1E2EC, 0x1E2EF}, + {0x1E4EC, 0x1E4EF}, + {0x1E5EE, 0x1E5EF}, + {0x1E8D0, 0x1E8D6}, + {0x1E944, 0x1E94A}, + {0xE0001, 0xE01EF}, +}; diff --git a/src/include/parser/value.h b/src/include/parser/value.h index f6fafb5c3..0734c4ea2 100644 --- a/src/include/parser/value.h +++ b/src/include/parser/value.h @@ -4,8 +4,8 @@ * interface for value nodes * * - * Copyright (c) 2003-2024, PgPool Global Development Group - * Copyright (c) 2003-2024, PostgreSQL Global Development Group + * Copyright (c) 2003-2025, PgPool Global Development Group + * Copyright (c) 2003-2025, PostgreSQL Global Development Group * * src/include/nodes/value.h * diff --git a/src/include/pool.h b/src/include/pool.h index 233d36608..ea6f87e12 100644 --- a/src/include/pool.h +++ b/src/include/pool.h @@ -410,11 +410,9 @@ typedef enum #define REPLICATION (pool_config->backend_clustering_mode == CM_NATIVE_REPLICATION || \ pool_config->backend_clustering_mode == CM_SNAPSHOT_ISOLATION) #define MAIN_REPLICA (pool_config->backend_clustering_mode == CM_STREAMING_REPLICATION || \ - pool_config->backend_clustering_mode == CM_LOGICAL_REPLICATION || \ - pool_config->backend_clustering_mode == CM_SLONY) + pool_config->backend_clustering_mode == CM_LOGICAL_REPLICATION) #define STREAM (pool_config->backend_clustering_mode == CM_STREAMING_REPLICATION) #define LOGICAL (pool_config->backend_clustering_mode == CM_LOGICAL_REPLICATION) -#define SLONY (pool_config->backend_clustering_mode == CM_SLONY) #define RAW_MODE (pool_config->backend_clustering_mode == CM_RAW) #define SL_MODE (STREAM || LOGICAL) /* streaming or logical replication mode */ @@ -717,7 +715,7 @@ extern size_t strlcpy(char *dst, const char *src, size_t siz); #endif /* pool_worker_child.c */ -extern void do_worker_child(void); +extern void do_worker_child(void *params); extern int get_query_result(POOL_CONNECTION_POOL_SLOT **slots, int backend_id, char *query, POOL_SELECT_RESULT **res); /* utils/pg_strong_random.c */ diff --git a/src/include/pool_config.h b/src/include/pool_config.h index 3d12c0a9f..758d51552 100644 --- a/src/include/pool_config.h +++ b/src/include/pool_config.h @@ -70,19 +70,11 @@ typedef enum ProcessManagementSstrategies PM_STRATEGY_LAZY } ProcessManagementSstrategies; -typedef enum NativeReplicationSubModes -{ - SLONY_MODE = 1, - STREAM_MODE, - LOGICAL_MODE -} NativeReplicationSubModes; - typedef enum ClusteringModes { CM_STREAMING_REPLICATION = 1, CM_NATIVE_REPLICATION, CM_LOGICAL_REPLICATION, - CM_SLONY, CM_RAW, CM_SNAPSHOT_ISOLATION } ClusteringModes; @@ -261,7 +253,8 @@ typedef struct int authentication_timeout; /* maximum time in seconds to complete * client authentication */ int max_pool; /* max # of connection pool per child */ - char *logdir; /* logging directory */ + char *work_dir; /* directory to create pgpool_status and lock + * files */ char *log_destination_str; /* log destination: stderr and/or * syslog */ int log_destination; /* log destination */ @@ -665,16 +658,17 @@ typedef struct * lifecheck */ char *wd_lifecheck_user; /* PostgreSQL user name for watchdog */ char *wd_lifecheck_password; /* password for watchdog user */ - int wd_heartbeat_port; /* Port number for heartbeat lifecheck */ int wd_heartbeat_keepalive; /* Interval time of sending heartbeat * signal (sec) */ int wd_heartbeat_deadtime; /* Deadtime interval for heartbeat * signal (sec) */ WdHbIf hb_ifs[WD_MAX_IF_NUM]; /* heartbeat interfaces of all * watchdog nodes */ + WdHbIf hb_local_if[WD_MAX_IF_NUM]; /* local heartbeat interfaces */ + int num_hb_local_if; /* number of local interface */ WdHbIf hb_dest_if[WD_MAX_IF_NUM]; /* heartbeat destination * interfaces */ - int num_hb_dest_if; /* number of interface devices */ + int num_hb_dest_if; /* number of destination interface */ char **wd_monitoring_interfaces_list; /* network interface name list * to be monitored by watchdog */ bool health_check_test; /* if on, enable health check testing */ diff --git a/src/include/pool_type.h b/src/include/pool_type.h index 6e8fe85dc..078376b50 100644 --- a/src/include/pool_type.h +++ b/src/include/pool_type.h @@ -31,32 +31,34 @@ #include <sys/socket.h> #include <stddef.h> #include "libpq-fe.h" -/* Define common boolean type. C++ and BEOS already has it so exclude them. */ -#ifdef c_plusplus -#ifndef __cplusplus -#define __cplusplus -#endif /* __cplusplus */ -#endif /* c_plusplus */ - -#ifndef __BEOS__ -#ifndef __cplusplus -#ifndef bool -typedef char bool; -#endif -#ifndef true -#define true ((bool) 1) -#endif + +/* ---------------------------------------------------------------- + * Section 2: bool, true, false + * ---------------------------------------------------------------- + */ + +/* + * bool + * Boolean value, either true or false. + * + * PostgreSQL currently cannot deal with bool of size other than 1; there are + * static assertions around the code to prevent that. + */ + +#include <stdbool.h> + +/* + * Pgpool-II still uses TRUE/FALSE, that are only used Windows build in + * PostgreSQL. In the feature, we should replace TRUE/FALSE with true/false, + * but until that day... + */ + #ifndef TRUE #define TRUE ((bool) 1) #endif -#ifndef false -#define false ((bool) 0) -#endif #ifndef FALSE #define FALSE ((bool) 0) #endif -#endif /* not C++ */ -#endif /* __BEOS__ */ /* ---------------------------------------------------------------- * Section 5: offsetof, lengthof, endof, alignment diff --git a/src/include/utils/json.h b/src/include/utils/json.h index cb4378a9c..8bf5b8f52 100644 --- a/src/include/utils/json.h +++ b/src/include/utils/json.h @@ -313,7 +313,7 @@ extern "C" /* pgpool-II extensions */ json_value *json_get_value_for_key(json_value *source, const char *key); int json_get_int_value_for_key(json_value *source, const char *key, int *value); -int json_get_long_value_for_key(json_value *source, const char *key, long *value); +int json_get_llong_value_for_key(json_value *source, const char *key, long long *value); char *json_get_string_value_for_key(json_value *source, const char *key); int json_get_bool_value_for_key(json_value *source, const char *key, bool *value); diff --git a/src/include/utils/pool_relcache.h b/src/include/utils/pool_relcache.h index 16f2fcd61..b19d71ebc 100644 --- a/src/include/utils/pool_relcache.h +++ b/src/include/utils/pool_relcache.h @@ -6,7 +6,7 @@ * pgpool: a language independent connection pool server for PostgreSQL * written by Tatsuo Ishii * - * Copyright (c) 2003-2010 PgPool Global Development Group + * Copyright (c) 2003-2025 PgPool Global Development Group * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby @@ -34,8 +34,6 @@ /* Relation lookup cache structure */ -typedef void *(*func_ptr) (); - typedef struct { char dbname[MAX_ITEM_LENGTH]; /* database name */ @@ -57,13 +55,13 @@ typedef struct * POOL_SELECT_RESULT *. This function must return a pointer to be saved * in cache->data. */ - func_ptr register_func; + void *(*register_func) (POOL_SELECT_RESULT *data); /* * User defined function to be called at data unregister. Argument * cache->data. */ - func_ptr unregister_func; + void *(*unregister_func) (void *data); bool cache_is_session_local; /* True if cache life time is session * local */ bool no_cache_if_zero; /* if register func returns 0, do not @@ -72,7 +70,7 @@ typedef struct } POOL_RELCACHE; extern POOL_RELCACHE *pool_create_relcache(int cachesize, char *sql, - func_ptr register_func, func_ptr unregister_func, + void *(*register_func) (POOL_SELECT_RESULT *), void *(*unregister_func) (void *), bool issessionlocal); extern void pool_discard_relcache(POOL_RELCACHE *relcache); extern void *pool_search_relcache(POOL_RELCACHE *relcache, POOL_CONNECTION_POOL *backend, char *table); diff --git a/src/include/utils/pool_select_walker.h b/src/include/utils/pool_select_walker.h index 9eb9760c8..3c067c61a 100644 --- a/src/include/utils/pool_select_walker.h +++ b/src/include/utils/pool_select_walker.h @@ -6,7 +6,7 @@ * pgpool: a language independent connection pool server for PostgreSQL * written by Tatsuo Ishii * - * Copyright (c) 2003-2024 PgPool Global Development Group + * Copyright (c) 2003-2025 PgPool Global Development Group * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby @@ -54,6 +54,9 @@ typedef struct char table_names[POOL_MAX_SELECT_OIDS][NAMEDATALEN]; /* table names */ } SelectContext; + +typedef bool (*tree_walker_callback) (Node *node, void *context); + extern int pool_get_terminate_backend_pid(Node *node); extern bool pool_has_function_call(Node *node); extern bool pool_has_non_immutable_function_call(Node *node); @@ -66,7 +69,7 @@ extern bool pool_has_row_security(Node *node); extern bool pool_has_insertinto_or_locking_clause(Node *node); extern bool pool_has_pgpool_regclass(void); extern bool pool_has_to_regclass(void); -extern bool raw_expression_tree_walker(Node *node, bool (*walker) (), void *context); +extern bool raw_expression_tree_walker(Node *node, tree_walker_callback walker, void *context); extern int pool_table_name_to_oid(char *table_name); extern int pool_extract_table_oids_from_select_stmt(Node *node, SelectContext *ctx); extern RangeVar *makeRangeVarFromNameList(List *names); diff --git a/src/include/version.h b/src/include/version.h index 0af58a638..861500331 100644 --- a/src/include/version.h +++ b/src/include/version.h @@ -1 +1 @@ -#define PGPOOLVERSION "tasukiboshi" +#define PGPOOLVERSION "mitsukakeboshi" diff --git a/src/include/watchdog/wd_commands.h b/src/include/watchdog/wd_commands.h index 61326137d..a016772f6 100644 --- a/src/include/watchdog/wd_commands.h +++ b/src/include/watchdog/wd_commands.h @@ -52,7 +52,7 @@ typedef struct WDGenericData char *stringVal; int intVal; bool boolVal; - long longVal; + long long longVal; } data; } WDGenericData; diff --git a/src/include/watchdog/wd_json_data.h b/src/include/watchdog/wd_json_data.h index 1016dcae8..01e40e784 100644 --- a/src/include/watchdog/wd_json_data.h +++ b/src/include/watchdog/wd_json_data.h @@ -51,8 +51,8 @@ extern bool parse_node_status_json(char *json_data, int data_len, int *nodeID, i extern bool parse_beacon_message_json(char *json_data, int data_len, int *state, - long *seconds_since_node_startup, - long *seconds_since_current_state, + long long *seconds_since_node_startup, + long long *seconds_since_current_state, int *quorumStatus, int *standbyNodesCount, bool *escalated); diff --git a/src/include/watchdog/wd_utils.h b/src/include/watchdog/wd_utils.h index 0c8ad17ca..5df1fa1e9 100644 --- a/src/include/watchdog/wd_utils.h +++ b/src/include/watchdog/wd_utils.h @@ -49,10 +49,7 @@ extern pid_t fork_escalation_process(void); extern pid_t fork_plunging_process(void); /* wd_ping.c */ -extern int wd_is_upper_ok(char *server_list); extern bool wd_is_ip_exists(char *ip); -extern bool wd_get_ping_result(char *hostname, int exit_status, int outfd); -extern pid_t wd_issue_ping_command(char *hostname, int *outfd); extern pid_t wd_trusted_server_command(char *hostname); /* wd_if.c */ diff --git a/src/libs/pcp/Makefile.am b/src/libs/pcp/Makefile.am index c3172c203..31f51233a 100644 --- a/src/libs/pcp/Makefile.am +++ b/src/libs/pcp/Makefile.am @@ -1,7 +1,7 @@ AM_CPPFLAGS = -D_GNU_SOURCE -DPOOL_PRIVATE -I @PGSQL_INCLUDE_DIR@ lib_LTLIBRARIES = libpcp.la -libpcp_la_LDFLAGS = -version-info 2:1:0 +libpcp_la_LDFLAGS = -version-info 3:0:0 dist_libpcp_la_SOURCES = pcp.c \ ../../utils/pool_path.c \ ../../tools/fe_port.c \ diff --git a/src/main/health_check.c b/src/main/health_check.c index f32d54ce0..0c72c0a72 100644 --- a/src/main/health_check.c +++ b/src/main/health_check.c @@ -109,7 +109,7 @@ static bool check_backend_down_request(int node, bool done_requests); * health check child main loop */ void -do_health_check_child(int *node_id) +do_health_check_child(void *params) { sigjmp_buf local_sigjmp_buf; MemoryContext HealthCheckMemoryContext; @@ -117,20 +117,22 @@ do_health_check_child(int *node_id) static struct timeval start_time; static struct timeval end_time; long diff_t; + int node_id; POOL_HEALTH_CHECK_STATISTICS mystat; - stats = &health_check_stats[*node_id]; + node_id = *((int *) params); + stats = &health_check_stats[node_id]; /* Set application name */ - set_application_name_with_suffix(PT_HEALTH_CHECK, *node_id); + set_application_name_with_suffix(PT_HEALTH_CHECK, node_id); ereport(DEBUG1, - (errmsg("I am health check process pid:%d DB node id:%d", getpid(), *node_id))); + (errmsg("I am health check process pid:%d DB node id:%d", getpid(), node_id))); /* Identify myself via ps */ init_ps_display("", "", "", ""); - snprintf(psbuffer, sizeof(psbuffer), "health check process(%d)", *node_id); + snprintf(psbuffer, sizeof(psbuffer), "health check process(%d)", node_id); set_ps_display(psbuffer, false); /* set up signal handlers */ @@ -193,7 +195,7 @@ do_health_check_child(int *node_id) CHECK_REQUEST; - if (pool_config->health_check_params[*node_id].health_check_period <= 0) + if (pool_config->health_check_params[node_id].health_check_period <= 0) { stats->min_health_check_duration = 0; sleep(30); @@ -203,27 +205,27 @@ do_health_check_child(int *node_id) * If health checking is enabled and the node is not in down status, * do health check. */ - else if (pool_config->health_check_params[*node_id].health_check_period > 0) + else if (pool_config->health_check_params[node_id].health_check_period > 0) { bool result; - BackendInfo *bkinfo = pool_get_node_info(*node_id); + BackendInfo *bkinfo = pool_get_node_info(node_id); stats->total_count++; gettimeofday(&start_time, NULL); stats->last_health_check = time(NULL); - result = establish_persistent_connection(*node_id); + result = establish_persistent_connection(node_id); if (result && slot == NULL) { stats->last_failed_health_check = time(NULL); - if (POOL_DISALLOW_TO_FAILOVER(BACKEND_INFO(*node_id).flag)) + if (POOL_DISALLOW_TO_FAILOVER(BACKEND_INFO(node_id).flag)) { ereport(LOG, (errmsg("health check failed on node %d but failover is disallowed for the node", - *node_id))); + node_id))); } else { @@ -232,19 +234,19 @@ do_health_check_child(int *node_id) stats->fail_count++; ereport(LOG, (errmsg("health check failed on node %d (timeout:%d)", - *node_id, health_check_timer_expired))); + node_id, health_check_timer_expired))); if (bkinfo->backend_status == CON_DOWN && bkinfo->quarantine == true) { ereport(LOG, (errmsg("health check failed on quarantine node %d (timeout:%d)", - *node_id, health_check_timer_expired), + node_id, health_check_timer_expired), errdetail("ignoring.."))); } else { /* trigger failover */ partial = health_check_timer_expired ? false : true; - degenerate_backend_set(node_id, 1, partial ? REQ_DETAIL_SWITCHOVER : 0); + degenerate_backend_set(&node_id, 1, partial ? REQ_DETAIL_SWITCHOVER : 0); } } } @@ -257,7 +259,7 @@ do_health_check_child(int *node_id) * The node has become reachable again. Reset the quarantine * state */ - send_failback_request(*node_id, false, REQ_DETAIL_UPDATE | REQ_DETAIL_WATCHDOG); + send_failback_request(node_id, false, REQ_DETAIL_UPDATE | REQ_DETAIL_WATCHDOG); } else if (result && slot) { @@ -274,7 +276,7 @@ do_health_check_child(int *node_id) } /* Discard persistent connections */ - discard_persistent_connection(*node_id); + discard_persistent_connection(node_id); /* * Update health check duration only if health check was not @@ -302,7 +304,7 @@ do_health_check_child(int *node_id) memcpy(&mystat, (void *) stats, sizeof(mystat)); - sleep(pool_config->health_check_params[*node_id].health_check_period); + sleep(pool_config->health_check_params[node_id].health_check_period); } } exit(0); @@ -618,7 +620,7 @@ check_backend_down_request(int node, bool done_requests) if (backend_down_request_file[0] == '\0') { snprintf(backend_down_request_file, sizeof(backend_down_request_file), - "%s/%s", pool_config->logdir, BACKEND_DOWN_REQUEST_FILE); + "%s/%s", pool_config->work_dir, BACKEND_DOWN_REQUEST_FILE); } fd = fopen(backend_down_request_file, "r"); diff --git a/src/main/pgpool_logger.c b/src/main/pgpool_logger.c index 9d127183a..d57a0d000 100644 --- a/src/main/pgpool_logger.c +++ b/src/main/pgpool_logger.c @@ -50,7 +50,7 @@ #include "main/pgpool_logger.h" #define DEVNULL "/dev/null" -typedef int64 pg_time_t; +typedef time_t pg_time_t; /* * We read() into a temp buffer twice as big as a chunk, so that any fragment @@ -113,7 +113,7 @@ static volatile sig_atomic_t got_SIGHUP = false; static volatile sig_atomic_t rotation_requested = false; -static void SysLoggerMain(int argc, char *argv[]) pg_attribute_noreturn(); +pg_noreturn static void SysLoggerMain(int argc, char *argv[]); static void process_pipe_input(char *logbuffer, int *bytes_in_logbuffer); static void flush_pipe_input(char *logbuffer, int *bytes_in_logbuffer); static FILE *logfile_open(const char *filename, const char *mode, diff --git a/src/main/pgpool_main.c b/src/main/pgpool_main.c index ef2e5dfc1..4d88c5815 100644 --- a/src/main/pgpool_main.c +++ b/src/main/pgpool_main.c @@ -5,7 +5,7 @@ * pgpool: a language independent connection pool server for PostgreSQL * written by Tatsuo Ishii * - * Copyright (c) 2003-2024 PgPool Global Development Group + * Copyright (c) 2003-2025 PgPool Global Development Group * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby @@ -137,6 +137,7 @@ typedef struct bool sync_required; /* true if watchdog synchronization is * necessary */ + /* followings are copy of Req_info */ POOL_REQUEST_KIND reqkind; int node_id_set[MAX_NUM_BACKENDS]; int node_count; @@ -154,7 +155,7 @@ static void signal_user1_to_parent_with_reason(User1SignalReason reason); static void FileUnlink(int code, Datum path); static pid_t pcp_fork_a_child(int *fds, char *pcp_conf_file); static pid_t fork_a_child(int *fds, int id); -static pid_t worker_fork_a_child(ProcessType type, void (*func) (), void *params); +static pid_t worker_fork_a_child(ProcessType type, void (*func) (void *), void *params); static int create_unix_domain_socket(struct sockaddr_un un_addr_tmp, const char *group, const int permissions); static int *create_unix_domain_sockets_by_list(struct sockaddr_un *un_addrs, char *group, int permissions, int n_sockets); static int *create_inet_domain_sockets(const char *hostname, const int port); @@ -305,6 +306,12 @@ PgpoolMain(bool discard_status, bool clear_memcache_oidmaps) */ volatile bool first = true; + /* + * Query cache lock file path. This should be declared as "static" because + * the path is passed to be registered using on_proc_exit(). + */ + static char query_cache_lock_path[MAXPGPATH]; + processState = INITIALIZING; /* @@ -511,23 +518,23 @@ PgpoolMain(bool discard_status, bool clear_memcache_oidmaps) } /* For query cache concurrency control */ - if (pool_config->memory_cache_enabled) + if (pool_config->memory_cache_enabled || pool_config->enable_shared_relcache) { - char path[1024]; int lfd; - snprintf(path, sizeof(path), "%s/QUERY_CACHE_LOCK_FILE", pool_config->logdir); - lfd = open(path, O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR | S_IWUSR); + snprintf(query_cache_lock_path, sizeof(query_cache_lock_path), + "%s/%s", pool_config->work_dir, QUERY_CACHE_LOCK_FILE); + lfd = open(query_cache_lock_path, O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR | S_IWUSR); if (lfd == -1) { ereport(FATAL, - (errmsg("Failed to open lock file for query cache \"%s\"", path), + (errmsg("Failed to open lock file for query cache \"%s\"", query_cache_lock_path), errdetail("%m"))); } close(lfd); /* Register file unlink at exit */ - on_proc_exit(FileUnlink, (Datum) path); + on_proc_exit(FileUnlink, (Datum) query_cache_lock_path); } /* @@ -878,7 +885,7 @@ fork_a_child(int *fds, int id) * fork worker child process */ static pid_t -worker_fork_a_child(ProcessType type, void (*func) (), void *params) +worker_fork_a_child(ProcessType type, void (*func) (void *), void *params) { pid_t pid; @@ -1636,9 +1643,9 @@ failover(void) wd_failover_start(); /* - * if not in replication mode/native replication mode, we treat this a - * restart request. otherwise we need to check if we have already - * failovered. + * If not in streaming replication mode/native replication mode, we + * treat this as a restart request. Otherwise we need to check if we + * have already performed the failover. */ ereport(DEBUG1, (errmsg("failover handler"), @@ -1651,14 +1658,14 @@ failover(void) */ if (failover_context.request_details & REQ_DETAIL_PROMOTE) { - promote_node = failover_context.node_id_set[0]; + promote_node = failover_context.node_id_set[0]; /* requested node */ for (i = 0; i < failover_context.node_count; i++) { failover_context.node_id_set[i] = REAL_PRIMARY_NODE_ID; } } - node_id = failover_context.node_id_set[0]; + node_id = failover_context.node_id_set[0]; /* set target node id */ /* failback request? */ if (failover_context.reqkind == NODE_UP_REQUEST) @@ -1686,6 +1693,7 @@ failover(void) * NODE_QUARANTINE_REQUEST */ { + /* process single failover request */ if (handle_failover_request(&failover_context, node_id) < 0) continue; } @@ -3196,7 +3204,7 @@ read_status_file(bool discard_status) pool_set_backend_status_changed_time(i); } - snprintf(fnamebuf, sizeof(fnamebuf), "%s/%s", pool_config->logdir, STATUS_FILE_NAME); + snprintf(fnamebuf, sizeof(fnamebuf), "%s/%s", pool_config->work_dir, STATUS_FILE_NAME); fd = fopen(fnamebuf, "r"); if (!fd) { @@ -3383,7 +3391,7 @@ write_status_file(void) return 0; } - snprintf(fnamebuf, sizeof(fnamebuf), "%s/%s", pool_config->logdir, STATUS_FILE_NAME); + snprintf(fnamebuf, sizeof(fnamebuf), "%s/%s", pool_config->work_dir, STATUS_FILE_NAME); fd = fopen(fnamebuf, "w"); if (!fd) { diff --git a/src/parser/copyfuncs.c b/src/parser/copyfuncs.c index 4571d4b17..9cbbbe4f0 100644 --- a/src/parser/copyfuncs.c +++ b/src/parser/copyfuncs.c @@ -11,8 +11,8 @@ * be handled easily in a simple depth-first traversal. * * - * Portions Copyright (c) 2003-2024, PgPool Global Development Group - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2003-2025, PgPool Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -52,7 +52,7 @@ /* Copy a field that is a pointer to a C string, or perhaps NULL */ #define COPY_STRING_FIELD(fldname) \ - (newnode->fldname = from->fldname ? pstrdup(from->fldname) : (char *) NULL) + (newnode->fldname = from->fldname ? pstrdup(from->fldname) : NULL) /* Copy a field that is an inline array */ #define COPY_ARRAY_FIELD(fldname) \ @@ -90,6 +90,7 @@ _copyPlannedStmt(const PlannedStmt * from) COPY_SCALAR_FIELD(commandType); COPY_SCALAR_FIELD(queryId); + COPY_SCALAR_FIELD(planId); COPY_SCALAR_FIELD(hasReturning); COPY_SCALAR_FIELD(hasModifyingCTE); COPY_SCALAR_FIELD(canSetTag); @@ -98,7 +99,10 @@ _copyPlannedStmt(const PlannedStmt * from) COPY_SCALAR_FIELD(parallelModeNeeded); COPY_SCALAR_FIELD(jitFlags); COPY_NODE_FIELD(planTree); + COPY_NODE_FIELD(partPruneInfos); COPY_NODE_FIELD(rtable); + COPY_BITMAPSET_FIELD(unprunableRelids); + COPY_NODE_FIELD(permInfos); COPY_NODE_FIELD(resultRelations); COPY_NODE_FIELD(appendRelations); COPY_NODE_FIELD(subplans); @@ -123,6 +127,7 @@ _copyPlannedStmt(const PlannedStmt * from) static void CopyPlanFields(const Plan * from, Plan * newnode) { + COPY_SCALAR_FIELD(plan.disabled_nodes); COPY_SCALAR_FIELD(startup_cost); COPY_SCALAR_FIELD(total_cost); COPY_SCALAR_FIELD(plan_rows); @@ -218,6 +223,8 @@ _copyModifyTable(const ModifyTable * from) COPY_NODE_FIELD(resultRelations); COPY_NODE_FIELD(updateColnosLists); COPY_NODE_FIELD(withCheckOptionLists); + COPY_STRING_FIELD(returningOldAlias); + COPY_STRING_FIELD(returningNewAlias); COPY_NODE_FIELD(returningLists); COPY_NODE_FIELD(fdwPrivLists); COPY_BITMAPSET_FIELD(fdwDirectModifyPlans); @@ -256,7 +263,7 @@ _copyAppend(const Append * from) COPY_NODE_FIELD(appendplans); COPY_SCALAR_FIELD(nasyncplans); COPY_SCALAR_FIELD(first_partial_plan); - COPY_NODE_FIELD(part_prune_info); + COPY_SCALAR_FIELD(part_prune_index); return newnode; } @@ -284,7 +291,7 @@ _copyMergeAppend(const MergeAppend * from) COPY_POINTER_FIELD(sortOperators, from->numCols * sizeof(Oid)); COPY_POINTER_FIELD(collations, from->numCols * sizeof(Oid)); COPY_POINTER_FIELD(nullsFirst, from->numCols * sizeof(bool)); - COPY_NODE_FIELD(part_prune_info); + COPY_SCALAR_FIELD(part_prune_index); return newnode; } @@ -903,11 +910,11 @@ _copyMergeJoin(const MergeJoin * from) */ COPY_SCALAR_FIELD(skip_mark_restore); COPY_NODE_FIELD(mergeclauses); - numCols = list_length(from->mergeclauses); - COPY_POINTER_FIELD(mergeFamilies, numCols * sizeof(Oid)); - COPY_POINTER_FIELD(mergeCollations, numCols * sizeof(Oid)); - COPY_POINTER_FIELD(mergeStrategies, numCols * sizeof(int)); - COPY_POINTER_FIELD(mergeNullsFirst, numCols * sizeof(bool)); + COPY_POINTER_FIELD(mergeFamilies, list_length(from->mergeclauses) * sizeof(Oid)); + COPY_POINTER_FIELD(mergeCollations, list_length(from->mergeclauses) * sizeof(Oid)); + COPY_POINTER_FIELD(mergeStrategies, list_length(from->mergeclauses) * sizeof(int)); + COPY_POINTER_FIELD(mergeReversals, list_length(from->mergeclauses) * sizeof(bool)); + COPY_POINTER_FIELD(mergeNullsFirst, list_length(from->mergeclauses) * sizeof(bool)); return newnode; } @@ -1093,6 +1100,7 @@ _copyWindowAgg(const WindowAgg * from) CopyPlanFields((const Plan *) from, (Plan *) newnode); + COPY_STRING_FIELD(winname); COPY_SCALAR_FIELD(winref); COPY_SCALAR_FIELD(partNumCols); COPY_POINTER_FIELD(partColIdx, from->partNumCols * sizeof(AttrNumber)); @@ -1185,11 +1193,10 @@ _copySetOp(const SetOp * from) COPY_SCALAR_FIELD(cmd); COPY_SCALAR_FIELD(strategy); COPY_SCALAR_FIELD(numCols); - COPY_POINTER_FIELD(dupColIdx, from->numCols * sizeof(AttrNumber)); - COPY_POINTER_FIELD(dupOperators, from->numCols * sizeof(Oid)); - COPY_POINTER_FIELD(dupCollations, from->numCols * sizeof(Oid)); - COPY_SCALAR_FIELD(flagColIdx); - COPY_SCALAR_FIELD(firstFlag); + COPY_POINTER_FIELD(cmpColIdx, from->numCols * sizeof(AttrNumber)); + COPY_POINTER_FIELD(cmpOperators, from->numCols * sizeof(Oid)); + COPY_POINTER_FIELD(cmpCollations, from->numCols * sizeof(Oid)); + COPY_POINTER_FIELD(cmpNullsFirst, from->numCols * sizeof(bool)); COPY_SCALAR_FIELD(numGroups); return newnode; @@ -1283,6 +1290,7 @@ _copyPartitionPruneInfo(const PartitionPruneInfo * from) { PartitionPruneInfo *newnode = makeNode(PartitionPruneInfo); + COPY_BITMAPSET_FIELD(relids); COPY_NODE_FIELD(prune_infos); COPY_BITMAPSET_FIELD(other_subplans); @@ -1299,6 +1307,7 @@ _copyPartitionedRelPruneInfo(const PartitionedRelPruneInfo * from) COPY_SCALAR_FIELD(nparts); COPY_POINTER_FIELD(subplan_map, from->nparts * sizeof(int)); COPY_POINTER_FIELD(subpart_map, from->nparts * sizeof(int)); + COPY_POINTER_FIELD(leafpart_rti_map, from->nparts * sizeof(int)); COPY_POINTER_FIELD(relid_map, from->nparts * sizeof(Oid)); COPY_NODE_FIELD(initial_prunning_steps); COPY_NODE_FIELD(exec_prunning_steps); @@ -1461,7 +1470,9 @@ _copyVar(const Var *from) COPY_SCALAR_FIELD(vartype); COPY_SCALAR_FIELD(vartypmod); COPY_SCALAR_FIELD(varcollid); + COPY_BITMAPSET_FIELD(varnullingrels); COPY_SCALAR_FIELD(varlevelsup); + COPY_SCALAR_FIELD(varreturningtype); COPY_SCALAR_FIELD(varnosyn); COPY_SCALAR_FIELD(varattnosyn); COPY_LOCATION_FIELD(location); @@ -2014,6 +2025,8 @@ _copyArrayExpr(const ArrayExpr *from) COPY_SCALAR_FIELD(element_typeid); COPY_NODE_FIELD(elements); COPY_SCALAR_FIELD(multidims); + COPY_LOCATION_FIELD(list_start); + COPY_LOCATION_FIELD(list_end); COPY_LOCATION_FIELD(location); return newnode; @@ -2044,7 +2057,7 @@ _copyRowCompareExpr(const RowCompareExpr *from) { RowCompareExpr *newnode = makeNode(RowCompareExpr); - COPY_SCALAR_FIELD(rctype); + COPY_SCALAR_FIELD(cmptype); COPY_NODE_FIELD(opnos); COPY_NODE_FIELD(opfamilies); COPY_NODE_FIELD(inputcollids); @@ -2406,6 +2419,18 @@ _copyInferenceElem(const InferenceElem *from) return newnode; } +static ReturningExpr * +_copyReturningExpr(const ReturningExpr *from) +{ + ReturningExpr *newnode = makeNode(ReturningExpr); + + COPY_SCALAR_FIELD(retlevelsup); + COPY_SCALAR_FIELD(retold); + COPY_NODE_FIELD(retexpr); + + return newnode; +} + /* * _copyTargetEntry */ @@ -2513,7 +2538,7 @@ _copyPathKey(const PathKey * from) /* EquivalenceClasses are never moved, so just shallow-copy the pointer */ COPY_SCALAR_FIELD(pk_eclass); COPY_SCALAR_FIELD(pk_opfamily); - COPY_SCALAR_FIELD(pk_strategy); + COPY_SCALAR_FIELD(pk_cmptype); COPY_SCALAR_FIELD(pk_nulls_first); return newnode; @@ -2695,6 +2720,7 @@ _copyRangeTblEntry(const RangeTblEntry *from) COPY_NODE_FIELD(colcollations); COPY_STRING_FIELD(enrname); COPY_SCALAR_FIELD(enrtuples); + COPY_NODE_FIELD(groupexprs); COPY_SCALAR_FIELD(lateral); COPY_SCALAR_FIELD(inFromCl); COPY_NODE_FIELD(securityQuals); @@ -2752,6 +2778,7 @@ _copySortGroupClause(const SortGroupClause *from) COPY_SCALAR_FIELD(tleSortGroupRef); COPY_SCALAR_FIELD(eqop); COPY_SCALAR_FIELD(sortop); + COPY_SCALAR_FIELD(reverse_sort); COPY_SCALAR_FIELD(nulls_first); COPY_SCALAR_FIELD(hashable); @@ -2922,6 +2949,8 @@ _copyA_Expr(const A_Expr *from) COPY_NODE_FIELD(name); COPY_NODE_FIELD(lexpr); COPY_NODE_FIELD(rexpr); + COPY_LOCATION_FIELD(rexpr_list_start); + COPY_LOCATION_FIELD(rexpr_list_end); COPY_LOCATION_FIELD(location); return newnode; @@ -3045,6 +3074,8 @@ _copyA_ArrayExpr(const A_ArrayExpr *from) A_ArrayExpr *newnode = makeNode(A_ArrayExpr); COPY_NODE_FIELD(elements); + COPY_LOCATION_FIELD(list_start); + COPY_LOCATION_FIELD(list_end); COPY_LOCATION_FIELD(location); return newnode; @@ -3284,15 +3315,17 @@ _copyConstraint(const Constraint *from) COPY_STRING_FIELD(conname); COPY_SCALAR_FIELD(deferrable); COPY_SCALAR_FIELD(initdeferred); + COPY_SCALAR_FIELD(is_enforced); COPY_SCALAR_FIELD(skip_validation); COPY_SCALAR_FIELD(initially_valid); COPY_SCALAR_FIELD(is_no_inherit); COPY_NODE_FIELD(raw_expr); COPY_STRING_FIELD(cooked_expr); COPY_SCALAR_FIELD(generated_when); - COPY_SCALAR_FIELD(inhcount); + COPY_SCALAR_FIELD(generated_kind); COPY_SCALAR_FIELD(nulls_not_distinct); COPY_NODE_FIELD(keys); + COPY_SCALAR_FIELD(without_overlaps); COPY_NODE_FIELD(including); COPY_NODE_FIELD(exclusions); COPY_NODE_FIELD(options); @@ -3304,6 +3337,8 @@ _copyConstraint(const Constraint *from) COPY_NODE_FIELD(pktable); COPY_NODE_FIELD(fk_attrs); COPY_NODE_FIELD(pk_attrs); + COPY_SCALAR_FIELD(fk_with_period); + COPY_SCALAR_FIELD(pk_with_period); COPY_SCALAR_FIELD(fk_matchtype); COPY_SCALAR_FIELD(fk_upd_action); COPY_SCALAR_FIELD(fk_del_action); @@ -3366,6 +3401,29 @@ _copyRoleSpec(const RoleSpec *from) return newnode; } +static ReturningOption * +_copyReturningOption(const ReturningOption *from) +{ + ReturningOption *newnode = makeNode(ReturningOption); + + COPY_SCALAR_FIELD(option); + COPY_STRING_FIELD(value); + COPY_LOCATION_FIELD(location); + + return newnode; +} + +static ReturningClause * +_copyReturningClause(const ReturningClause *from) +{ + ReturningClause *newnode = makeNode(ReturningClause); + + COPY_NODE_FIELD(options); + COPY_NODE_FIELD(exprs); + + return newnode; +} + static TriggerTransition * _copyTriggerTransition(const TriggerTransition *from) { @@ -3618,6 +3676,7 @@ _copyQuery(const Query *from) COPY_SCALAR_FIELD(hasModifyingCTE); COPY_SCALAR_FIELD(hasForUpdate); COPY_SCALAR_FIELD(hasRowSecurity); + COPY_SCALAR_FIELD(hasGroupRTE); COPY_SCALAR_FIELD(isReturn); COPY_NODE_FIELD(cteList); COPY_NODE_FIELD(rtable); @@ -3629,6 +3688,8 @@ _copyQuery(const Query *from) COPY_NODE_FIELD(targetList); COPY_SCALAR_FIELD(override); COPY_NODE_FIELD(onConflict); + COPY_STRING_FIELD(returningOldAlias); + COPY_STRING_FIELD(returningNewAlias); COPY_NODE_FIELD(returningList); COPY_NODE_FIELD(groupClause); COPY_SCALAR_FIELD(groupDistinct); @@ -3671,7 +3732,7 @@ _copyInsertStmt(const InsertStmt *from) COPY_NODE_FIELD(cols); COPY_NODE_FIELD(selectStmt); COPY_NODE_FIELD(onConflictClause); - COPY_NODE_FIELD(returningList); + COPY_NODE_FIELD(returningClause); COPY_NODE_FIELD(withClause); COPY_SCALAR_FIELD(override); @@ -3686,7 +3747,7 @@ _copyDeleteStmt(const DeleteStmt *from) COPY_NODE_FIELD(relation); COPY_NODE_FIELD(usingClause); COPY_NODE_FIELD(whereClause); - COPY_NODE_FIELD(returningList); + COPY_NODE_FIELD(returningClause); COPY_NODE_FIELD(withClause); return newnode; @@ -3701,7 +3762,7 @@ _copyUpdateStmt(const UpdateStmt *from) COPY_NODE_FIELD(targetList); COPY_NODE_FIELD(whereClause); COPY_NODE_FIELD(fromClause); - COPY_NODE_FIELD(returningList); + COPY_NODE_FIELD(returningClause); COPY_NODE_FIELD(withClause); return newnode; @@ -3716,7 +3777,7 @@ _copyMergeStmt(const MergeStmt *from) COPY_NODE_FIELD(sourceRelation); COPY_NODE_FIELD(joinCondition); COPY_NODE_FIELD(mergeWhenClauses); - COPY_NODE_FIELD(returningList); + COPY_NODE_FIELD(returningClause); COPY_NODE_FIELD(withClause); return newnode; @@ -3822,6 +3883,34 @@ _copyAlterTableCmd(const AlterTableCmd *from) return newnode; } +static ATAlterConstraint * +_copyATAlterConstraint(const ATAlterConstraint *from) +{ + ATAlterConstraint *newnode = makeNode(ATAlterConstraint); + + COPY_STRING_FIELD(conname); + COPY_SCALAR_FIELD(alterEnforceability); + COPY_SCALAR_FIELD(is_enforced); + COPY_SCALAR_FIELD(alterDeferrability); + COPY_SCALAR_FIELD(deferrable); + COPY_SCALAR_FIELD(initdeferred); + COPY_SCALAR_FIELD(alterInheritability); + COPY_SCALAR_FIELD(noinherit); + + return newnode; +} + +static ReplicaIdentityStmt * +_copyReplicaIdentityStmt(const ReplicaIdentityStmt *from) +{ + ReplicaIdentityStmt *newnode = makeNode(ReplicaIdentityStmt); + + COPY_SCALAR_FIELD(identity_type); + COPY_STRING_FIELD(name); + + return newnode; +} + static AlterCollationStmt * _copyAlterCollationStmt(const AlterCollationStmt *from) { @@ -3994,6 +4083,7 @@ CopyCreateStmtFields(const CreateStmt *from, CreateStmt *newnode) COPY_NODE_FIELD(partbound); COPY_NODE_FIELD(ofTypename); COPY_NODE_FIELD(constraints); + COPY_NODE_FIELD(nnconstraints); COPY_NODE_FIELD(options); COPY_SCALAR_FIELD(oncommit); COPY_STRING_FIELD(tablespacename); @@ -4126,6 +4216,7 @@ _copyIndexStmt(const IndexStmt *from) COPY_SCALAR_FIELD(nulls_not_distinct); COPY_SCALAR_FIELD(primary); COPY_SCALAR_FIELD(isconstraint); + COPY_SCALAR_FIELD(iswithoutoverlaps); COPY_SCALAR_FIELD(deferrable); COPY_SCALAR_FIELD(initdeferred); COPY_SCALAR_FIELD(transformed); @@ -4189,6 +4280,7 @@ _copyFunctionParameter(const FunctionParameter *from) COPY_NODE_FIELD(argType); COPY_SCALAR_FIELD(mode); COPY_NODE_FIELD(defexpr); + COPY_LOCATION_FIELD(location); return newnode; } @@ -4613,17 +4705,6 @@ _copyRefreshMatViewStmt(const RefreshMatViewStmt *from) return newnode; } -static ReplicaIdentityStmt * -_copyReplicaIdentityStmt(const ReplicaIdentityStmt *from) -{ - ReplicaIdentityStmt *newnode = makeNode(ReplicaIdentityStmt); - - COPY_SCALAR_FIELD(identity_type); - COPY_STRING_FIELD(name); - - return newnode; -} - static AlterSystemStmt * _copyAlterSystemStmt(const AlterSystemStmt *from) { @@ -4669,7 +4750,9 @@ _copyVariableSetStmt(const VariableSetStmt *from) COPY_SCALAR_FIELD(kind); COPY_STRING_FIELD(name); COPY_NODE_FIELD(args); + COPY_SCALAR_FIELD(jumble_args); COPY_SCALAR_FIELD(is_local); + COPY_LOCATION_FIELD(location); return newnode; } @@ -5279,15 +5362,6 @@ _copyPartitionRangeDatum(const PartitionRangeDatum *from) return newnode; } -static SinglePartitionSpec * -_copySinglePartitionSpec(const SinglePartitionSpec *from) -{ - SinglePartitionSpec *newnode = makeNode(SinglePartitionSpec); - - - return newnode; -} - static PartitionCmd * _copyPartitionCmd(const PartitionCmd *from) { @@ -5479,6 +5553,7 @@ _copyForeignKeyCacheInfo(const ForeignKeyCacheInfo * from) COPY_SCALAR_FIELD(conrelid); COPY_SCALAR_FIELD(confrelid); COPY_SCALAR_FIELD(nkeys); + COPY_SCALAR_FIELD(conenforced); COPY_ARRAY_FIELD(conkey); COPY_ARRAY_FIELD(confkey); COPY_ARRAY_FIELD(conpfeqop); @@ -5855,6 +5930,9 @@ copyObjectImpl(const void *from) case T_InferenceElem: retval = _copyInferenceElem(from); break; + case T_ReturningExpr: + retval = _copyReturningExpr(from); + break; case T_TargetEntry: retval = _copyTargetEntry(from); break; @@ -5985,6 +6063,12 @@ copyObjectImpl(const void *from) case T_AlterTableCmd: retval = _copyAlterTableCmd(from); break; + case T_ATAlterConstraint: + retval = _copyATAlterConstraint(from); + break; + case T_ReplicaIdentityStmt: + retval = _copyReplicaIdentityStmt(from); + break; case T_AlterCollationStmt: retval = _copyAlterCollationStmt(from); break; @@ -6156,9 +6240,6 @@ copyObjectImpl(const void *from) case T_RefreshMatViewStmt: retval = _copyRefreshMatViewStmt(from); break; - case T_ReplicaIdentityStmt: - retval = _copyReplicaIdentityStmt(from); - break; case T_AlterSystemStmt: retval = _copyAlterSystemStmt(from); break; @@ -6444,6 +6525,12 @@ copyObjectImpl(const void *from) case T_MergeWhenClause: retval = _copyMergeWhenClause(from); break; + case T_ReturningOption: + retval = _copyReturningOption(from); + break; + case T_ReturningClause: + retval = _copyReturningClause(from); + break; case T_ObjectWithArgs: retval = _copyObjectWithArgs(from); break; @@ -6519,9 +6606,6 @@ copyObjectImpl(const void *from) case T_PartitionRangeDatum: retval = _copyPartitionRangeDatum(from); break; - case T_SinglePartitionSpec: - retval = _copySinglePartitionSpec(from); - break; case T_PartitionCmd: retval = _copyPartitionCmd(from); break; diff --git a/src/parser/gram.y b/src/parser/gram.y index 61663cce2..8052ced8d 100644 --- a/src/parser/gram.y +++ b/src/parser/gram.y @@ -6,8 +6,8 @@ * gram.y * POSTGRESQL BISON rules/actions * - * Portions Copyright (c) 2003-2024, PgPool Global Development Group - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2003-2025, PgPool Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -89,6 +89,8 @@ #define ATTRIBUTE_IDENTITY_ALWAYS 'a' #define ATTRIBUTE_IDENTITY_BY_DEFAULT 'd' +#define ATTRIBUTE_GENERATED_STORED 's' +#define ATTRIBUTE_GENERATED_VIRTUAL 'v' /* * Definition taken from * postgreSQL source code file: src/include/utils/xml.h @@ -102,40 +104,26 @@ typedef enum } XmlStandaloneType; /* - * Location tracking support --- simpler than bison's default, since we only - * want to track the start position not the end position of each nonterminal. + * Location tracking support. Unlike bison's default, we only want + * to track the start position not the end position of each nonterminal. + * Nonterminals that reduce to empty receive position "-1". Since a + * production's leading RHS nonterminal(s) may have reduced to empty, + * we have to scan to find the first one that's not -1. */ #define YYLLOC_DEFAULT(Current, Rhs, N) \ do { \ - if ((N) > 0) \ - (Current) = (Rhs)[1]; \ - else \ - (Current) = (-1); \ + (Current) = (-1); \ + for (int _i = 1; _i <= (N); _i++) \ + { \ + if ((Rhs)[_i] >= 0) \ + { \ + (Current) = (Rhs)[_i]; \ + break; \ + } \ + } \ } while (0) /* - * The above macro assigns -1 (unknown) as the parse location of any - * nonterminal that was reduced from an empty rule, or whose leftmost - * component was reduced from an empty rule. This is problematic - * for nonterminals defined like - * OptFooList: / * EMPTY * / { ... } | OptFooList Foo { ... } ; - * because we'll set -1 as the location during the first reduction and then - * copy it during each subsequent reduction, leaving us with -1 for the - * location even when the list is not empty. To fix that, do this in the - * action for the nonempty rule(s): - * if (@$ < 0) @$ = @2; - * (Although we have many nonterminals that follow this pattern, we only - * bother with fixing @$ like this when the nonterminal's parse location - * is actually referenced in some rule.) - * - * A cleaner answer would be to make YYLLOC_DEFAULT scan all the Rhs - * locations until it's found one that's not -1. Then we'd get a correct - * location for any nonterminal that isn't entirely empty. But this way - * would add overhead to every rule reduction, and so far there's not been - * a compelling reason to pay that overhead. - */ - -/* * Bison doesn't allocate anything that needs to live across parser calls, * so we can easily have it use palloc instead of malloc. This prevents * memory leaks if we error out during parsing. @@ -158,12 +146,15 @@ typedef struct ImportQual List *table_names; } ImportQual; -/* Private struct for the result of opt_select_limit production */ +/* Private struct for the result of select_limit & limit_clause productions */ typedef struct SelectLimit { Node *limitOffset; Node *limitCount; - LimitOption limitOption; + LimitOption limitOption; /* indicates presence of WITH TIES */ + ParseLoc offsetLoc; /* location of OFFSET token, if present */ + ParseLoc countLoc; /* location of LIMIT/FETCH token, if present */ + ParseLoc optionLoc; /* location of WITH TIES, if present */ } SelectLimit; /* Private struct for the result of group_clause production */ @@ -193,6 +184,8 @@ typedef struct KeyActions #define CAS_INITIALLY_DEFERRED 0x08 #define CAS_NOT_VALID 0x10 #define CAS_NO_INHERIT 0x20 +#define CAS_NOT_ENFORCED 0x40 +#define CAS_ENFORCED 0x80 #define parser_yyerror(msg) scanner_yyerror(msg, yyscanner) @@ -228,12 +221,12 @@ static void doNegateFloat(Float *v); static Node *makeAndExpr(Node *lexpr, Node *rexpr, int location); static Node *makeOrExpr(Node *lexpr, Node *rexpr, int location); static Node *makeNotExpr(Node *expr, int location); -static Node *makeAArrayExpr(List *elements, int location); +static Node *makeAArrayExpr(List *elements, int location, int end_location); static Node *makeSQLValueFunction(SQLValueFunctionOp op, int32 typmod, int location); static Node *makeXmlExpr(XmlExprOp op, char *name, List *named_args, List *args, int location); -static List *mergeTableFuncParameters(List *func_args, List *columns); +static List *mergeTableFuncParameters(List *func_args, List *columns, core_yyscan_t yyscanner); static TypeName *TableFuncTypeName(List *columns); static RangeVar *makeRangeVarFromAnyName(List *names, int position, core_yyscan_t yyscanner); static RangeVar *makeRangeVarFromQualifiedName(char *name, List *namelist, int location, @@ -242,9 +235,10 @@ static void SplitColQualList(List *qualList, List **constraintList, CollateClause **collClause, core_yyscan_t yyscanner); static void processCASbits(int cas_bits, int location, const char *constrType, - bool *deferrable, bool *initdeferred, bool *not_valid, - bool *no_inherit, core_yyscan_t yyscanner); -static PartitionStrategy parsePartitionStrategy(char *strategy); + bool *deferrable, bool *initdeferred, bool *is_enforced, + bool *not_valid, bool *no_inherit, core_yyscan_t yyscanner); +static PartitionStrategy parsePartitionStrategy(char *strategy, int location, + core_yyscan_t yyscanner); static void preprocess_pubobj_list(List *pubobjspec_list, core_yyscan_t yyscanner); static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); @@ -310,6 +304,8 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); MergeWhenClause *mergewhen; struct KeyActions *keyactions; struct KeyAction *keyaction; + ReturningClause *retclause; + ReturningOptionKind retoptionkind; } %type <node> stmt toplevel_stmt schema_stmt routine_body_stmt @@ -480,7 +476,8 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); opclass_purpose opt_opfamily transaction_mode_list_or_empty OptTableFuncElementList TableFuncElementList opt_type_modifiers prep_type_clause - execute_param_clause using_clause returning_clause + execute_param_clause using_clause + returning_with_clause returning_options opt_enum_val_list enum_val_list table_func_column_list create_generic_options alter_generic_options relation_expr_list dostmt_opt_list @@ -489,6 +486,9 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); vacuum_relation_list opt_vacuum_relation_list drop_option_list pub_obj_list +%type <retclause> returning_clause +%type <node> returning_option +%type <retoptionkind> returning_option_kind %type <node> opt_routine_body %type <groupclause> group_clause %type <list> group_by_list @@ -527,7 +527,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); %type <boolean> opt_instead %type <boolean> opt_unique opt_verbose opt_full -%type <boolean> opt_freeze opt_analyze opt_default opt_recheck +%type <boolean> opt_freeze opt_analyze opt_default %type <defelt> opt_binary copy_delimiter %type <boolean> copy_from opt_program @@ -557,14 +557,15 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); SetResetClause FunctionSetResetClause %type <node> TableElement TypedTableElement ConstraintElem DomainConstraintElem TableFuncElement -%type <node> columnDef columnOptions +%type <node> columnDef columnOptions optionalPeriodName %type <defelt> def_elem reloption_elem old_aggr_elem operator_def_elem %type <node> def_arg columnElem where_clause where_or_current_clause a_expr b_expr c_expr AexprConst indirection_el opt_slice_bound - columnref in_expr having_clause func_table xmltable array_expr + columnref having_clause func_table xmltable array_expr OptWhereClause operator_def_arg +%type <list> opt_column_and_period_list %type <list> rowsfrom_item rowsfrom_list opt_col_def_list -%type <boolean> opt_ordinality +%type <boolean> opt_ordinality opt_without_overlaps %type <list> ExclusionConstraintList ExclusionConstraintElem %type <list> func_arg_list func_arg_list_opt %type <node> func_arg_expr @@ -673,7 +674,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); %type <str> opt_existing_window_name %type <boolean> opt_if_not_exists %type <boolean> opt_unique_null_treatment -%type <ival> generated_when override_kind +%type <ival> generated_when override_kind opt_virtual_or_stored %type <partspec> PartitionSpec OptPartitionSpec %type <partelem> part_elem %type <list> part_params @@ -756,9 +757,9 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); DETACH DICTIONARY DISABLE_P DISCARD DISTINCT DO DOCUMENT_P DOMAIN_P DOUBLE_P DROP - EACH ELSE EMPTY_P ENABLE_P ENCODING ENCRYPTED END_P ENUM_P ERROR_P ESCAPE - EVENT EXCEPT EXCLUDE EXCLUDING EXCLUSIVE EXECUTE EXISTS EXPLAIN EXPRESSION - EXTENSION EXTERNAL EXTRACT + EACH ELSE EMPTY_P ENABLE_P ENCODING ENCRYPTED END_P ENFORCED ENUM_P ERROR_P + ESCAPE EVENT EXCEPT EXCLUDE EXCLUDING EXCLUSIVE EXECUTE EXISTS EXPLAIN + EXPRESSION EXTENSION EXTERNAL EXTRACT FALSE_P FAMILY FETCH FILTER FINALIZE FIRST_P FLOAT_P FOLLOWING FOR FORCE FOREIGN FORMAT FORWARD FREEZE FROM FULL FUNCTION FUNCTIONS @@ -789,18 +790,18 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); NOT NOTHING NOTIFY NOTNULL NOWAIT NULL_P NULLIF NULLS_P NUMERIC - OBJECT_P OF OFF OFFSET OIDS OLD OMIT ON ONLY OPERATOR OPTION OPTIONS OR + OBJECT_P OBJECTS_P OF OFF OFFSET OIDS OLD OMIT ON ONLY OPERATOR OPTION OPTIONS OR ORDER ORDINALITY OTHERS OUT_P OUTER_P OVER OVERLAPS OVERLAY OVERRIDING OWNED OWNER PARALLEL PARAMETER PARSER PARTIAL PARTITION PASSING PASSWORD PATH PGPOOL - PLACING PLAN PLANS POLICY + PERIOD PLACING PLAN PLANS POLICY POSITION PRECEDING PRECISION PRESERVE PREPARE PREPARED PRIMARY PRIOR PRIVILEGES PROCEDURAL PROCEDURE PROCEDURES PROGRAM PUBLICATION QUOTE QUOTES - RANGE READ REAL REASSIGN RECHECK RECURSIVE REF_P REFERENCES REFERENCING + RANGE READ REAL REASSIGN RECURSIVE REF_P REFERENCES REFERENCING REFRESH REINDEX RELATIVE_P RELEASE RENAME REPEATABLE REPLACE REPLICA RESET RESTART RESTRICT RETURN RETURNING RETURNS REVOKE RIGHT ROLE ROLLBACK ROLLUP ROUTINE ROUTINES ROW ROWS RULE @@ -821,7 +822,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); UNLISTEN UNLOGGED UNTIL UPDATE USER USING VACUUM VALID VALIDATE VALIDATOR VALUE_P VALUES VARCHAR VARIADIC VARYING - VERBOSE VERSION_P VIEW VIEWS VOLATILE + VERBOSE VERSION_P VIEW VIEWS VIRTUAL VOLATILE WHEN WHERE WHITESPACE_P WINDOW WITH WITHIN WITHOUT WORK WRAPPER WRITE @@ -962,7 +963,7 @@ parse_toplevel: | MODE_PLPGSQL_EXPR PLpgSQL_Expr { pg_yyget_extra(yyscanner)->parsetree = - list_make1(makeRawStmt($2, 0)); + list_make1(makeRawStmt($2, @2)); } | MODE_PLPGSQL_ASSIGN1 PLAssignStmt { @@ -970,7 +971,7 @@ parse_toplevel: n->nnames = 1; pg_yyget_extra(yyscanner)->parsetree = - list_make1(makeRawStmt((Node *) n, 0)); + list_make1(makeRawStmt((Node *) n, @2)); } | MODE_PLPGSQL_ASSIGN2 PLAssignStmt { @@ -978,7 +979,7 @@ parse_toplevel: n->nnames = 2; pg_yyget_extra(yyscanner)->parsetree = - list_make1(makeRawStmt((Node *) n, 0)); + list_make1(makeRawStmt((Node *) n, @2)); } | MODE_PLPGSQL_ASSIGN3 PLAssignStmt { @@ -986,19 +987,15 @@ parse_toplevel: n->nnames = 3; pg_yyget_extra(yyscanner)->parsetree = - list_make1(makeRawStmt((Node *) n, 0)); + list_make1(makeRawStmt((Node *) n, @2)); } ; /* * At top level, we wrap each stmt with a RawStmt node carrying start location - * and length of the stmt's text. Notice that the start loc/len are driven - * entirely from semicolon locations (@2). It would seem natural to use - * @1 or @3 to get the true start location of a stmt, but that doesn't work - * for statements that can start with empty nonterminals (opt_with_clause is - * the main offender here); as noted in the comments for YYLLOC_DEFAULT, - * we'd get -1 for the location in such cases. - * We also take care to discard empty statements entirely. + * and length of the stmt's text. + * We also take care to discard empty statements entirely (which among other + * things dodges the problem of assigning them a location). */ stmtmulti: stmtmulti ';' toplevel_stmt { @@ -1008,14 +1005,14 @@ stmtmulti: stmtmulti ';' toplevel_stmt updateRawStmtEnd(llast_node(RawStmt, $1), @2); } if ($3 != NULL) - $$ = lappend($1, makeRawStmt($3, @2 + 1)); + $$ = lappend($1, makeRawStmt($3, @3)); else $$ = $1; } | toplevel_stmt { if ($1 != NULL) - $$ = list_make1(makeRawStmt($1, 0)); + $$ = list_make1(makeRawStmt($1, @1)); else $$ = NIL; } @@ -1616,8 +1613,6 @@ CreateSchemaStmt: OptSchemaEltList: OptSchemaEltList schema_stmt { - if (@$ < 0) /* see comments for YYLLOC_DEFAULT */ - @$ = @2; $$ = lappend($1, $2); } | /* EMPTY */ @@ -1693,6 +1688,8 @@ set_rest: n->kind = VAR_SET_MULTI; n->name = "TRANSACTION"; n->args = $2; + n->jumble_args = true; + n->location = -1; $$ = n; } | SESSION CHARACTERISTICS AS TRANSACTION transaction_mode_list @@ -1702,6 +1699,8 @@ set_rest: n->kind = VAR_SET_MULTI; n->name = "SESSION CHARACTERISTICS"; n->args = $5; + n->jumble_args = true; + n->location = -1; $$ = n; } | set_rest_more @@ -1715,6 +1714,7 @@ generic_set: n->kind = VAR_SET_VALUE; n->name = $1; n->args = $3; + n->location = @3; $$ = n; } | var_name '=' var_list @@ -1724,6 +1724,7 @@ generic_set: n->kind = VAR_SET_VALUE; n->name = $1; n->args = $3; + n->location = @3; $$ = n; } | var_name TO DEFAULT @@ -1732,6 +1733,7 @@ generic_set: n->kind = VAR_SET_DEFAULT; n->name = $1; + n->location = -1; $$ = n; } | var_name '=' DEFAULT @@ -1740,6 +1742,7 @@ generic_set: n->kind = VAR_SET_DEFAULT; n->name = $1; + n->location = -1; $$ = n; } ; @@ -1752,6 +1755,7 @@ set_rest_more: /* Generic SET syntaxes: */ n->kind = VAR_SET_CURRENT; n->name = $1; + n->location = -1; $$ = n; } /* Special syntaxes mandated by SQL standard: */ @@ -1761,6 +1765,8 @@ set_rest_more: /* Generic SET syntaxes: */ n->kind = VAR_SET_VALUE; n->name = "timezone"; + n->location = -1; + n->jumble_args = true; if ($3 != NULL) n->args = list_make1($3); else @@ -1782,6 +1788,7 @@ set_rest_more: /* Generic SET syntaxes: */ n->kind = VAR_SET_VALUE; n->name = "search_path"; n->args = list_make1(makeStringConst($2, @2)); + n->location = @2; $$ = n; } | NAMES opt_encoding @@ -1790,6 +1797,7 @@ set_rest_more: /* Generic SET syntaxes: */ n->kind = VAR_SET_VALUE; n->name = "client_encoding"; + n->location = @2; if ($2 != NULL) n->args = list_make1(makeStringConst($2, @2)); else @@ -1803,6 +1811,7 @@ set_rest_more: /* Generic SET syntaxes: */ n->kind = VAR_SET_VALUE; n->name = "role"; n->args = list_make1(makeStringConst($2, @2)); + n->location = @2; $$ = n; } | SESSION AUTHORIZATION NonReservedWord_or_Sconst @@ -1812,6 +1821,7 @@ set_rest_more: /* Generic SET syntaxes: */ n->kind = VAR_SET_VALUE; n->name = "session_authorization"; n->args = list_make1(makeStringConst($3, @3)); + n->location = @3; $$ = n; } | SESSION AUTHORIZATION DEFAULT @@ -1820,6 +1830,7 @@ set_rest_more: /* Generic SET syntaxes: */ n->kind = VAR_SET_DEFAULT; n->name = "session_authorization"; + n->location = -1; $$ = n; } | XML_P OPTION document_or_content @@ -1829,6 +1840,8 @@ set_rest_more: /* Generic SET syntaxes: */ n->kind = VAR_SET_VALUE; n->name = "xmloption"; n->args = list_make1(makeStringConst($3 == XMLOPTION_DOCUMENT ? "DOCUMENT" : "CONTENT", @3)); + n->jumble_args = true; + n->location = -1; $$ = n; } /* Special syntaxes invented by PostgreSQL: */ @@ -1839,13 +1852,14 @@ set_rest_more: /* Generic SET syntaxes: */ n->kind = VAR_SET_MULTI; n->name = "TRANSACTION SNAPSHOT"; n->args = list_make1(makeStringConst($3, @3)); + n->location = @3; $$ = n; } /* PGPOOL CACHE DELETE */ | SET CACHE DELETE_P Sconst { VariableSetStmt *n = makeNode(VariableSetStmt); - n->name = $4; /* query to delete query cache */ + n->name = $4; /* query to delete query cache */ $$ = n; } ; @@ -1959,6 +1973,7 @@ reset_rest: n->kind = VAR_RESET; n->name = "timezone"; + n->location = -1; $$ = n; } | TRANSACTION ISOLATION LEVEL @@ -1967,6 +1982,7 @@ reset_rest: n->kind = VAR_RESET; n->name = "transaction_isolation"; + n->location = -1; $$ = n; } | SESSION AUTHORIZATION @@ -1975,6 +1991,7 @@ reset_rest: n->kind = VAR_RESET; n->name = "session_authorization"; + n->location = -1; $$ = n; } ; @@ -1986,6 +2003,7 @@ generic_reset: n->kind = VAR_RESET; n->name = $1; + n->location = -1; $$ = n; } | ALL @@ -1993,6 +2011,7 @@ generic_reset: VariableSetStmt *n = makeNode(VariableSetStmt); n->kind = VAR_RESET_ALL; + n->location = -1; $$ = n; } ; @@ -2715,15 +2734,45 @@ alter_table_cmd: | ALTER CONSTRAINT name ConstraintAttributeSpec { AlterTableCmd *n = makeNode(AlterTableCmd); - Constraint *c = makeNode(Constraint); + ATAlterConstraint *c = makeNode(ATAlterConstraint); + n->subtype = AT_AlterConstraint; n->def = (Node *) c; - c->contype = CONSTR_FOREIGN; /* others not supported, yet */ c->conname = $3; - processCASbits($4, @4, "ALTER CONSTRAINT statement", + if ($4 & (CAS_NOT_ENFORCED | CAS_ENFORCED)) + c->alterEnforceability = true; + if ($4 & (CAS_DEFERRABLE | CAS_NOT_DEFERRABLE | + CAS_INITIALLY_DEFERRED | CAS_INITIALLY_IMMEDIATE)) + c->alterDeferrability = true; + if ($4 & CAS_NO_INHERIT) + c->alterInheritability = true; + /* handle unsupported case with specific error message */ + if ($4 & CAS_NOT_VALID) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("constraints cannot be altered to be NOT VALID"), + parser_errposition(@4))); + processCASbits($4, @4, "FOREIGN KEY", &c->deferrable, &c->initdeferred, - NULL, NULL, yyscanner); + &c->is_enforced, + NULL, + &c->noinherit, + yyscanner); + $$ = (Node *) n; + } + /* ALTER TABLE <name> ALTER CONSTRAINT INHERIT */ + | ALTER CONSTRAINT name INHERIT + { + AlterTableCmd *n = makeNode(AlterTableCmd); + ATAlterConstraint *c = makeNode(ATAlterConstraint); + + n->subtype = AT_AlterConstraint; + n->def = (Node *) c; + c->conname = $3; + c->alterInheritability = true; + c->noinherit = false; + $$ = (Node *) n; } /* ALTER TABLE <name> VALIDATE CONSTRAINT ... */ @@ -3214,11 +3263,13 @@ PartitionBoundSpec: if (n->modulus == -1) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("modulus for hash partition must be specified"))); + errmsg("modulus for hash partition must be specified"), + parser_errposition(@3))); if (n->remainder == -1) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("remainder for hash partition must be specified"))); + errmsg("remainder for hash partition must be specified"), + parser_errposition(@3))); n->location = @3; @@ -3970,12 +4021,16 @@ ColConstraint: * or be part of a_expr NOT LIKE or similar constructs). */ ColConstraintElem: - NOT NULL_P + NOT NULL_P opt_no_inherit { Constraint *n = makeNode(Constraint); n->contype = CONSTR_NOTNULL; n->location = @1; + n->is_no_inherit = $3; + n->is_enforced = true; + n->skip_validation = false; + n->initially_valid = true; $$ = (Node *) n; } | NULL_P @@ -4020,6 +4075,7 @@ ColConstraintElem: n->is_no_inherit = $5; n->raw_expr = $3; n->cooked_expr = NULL; + n->is_enforced = true; n->skip_validation = false; n->initially_valid = true; $$ = (Node *) n; @@ -4046,7 +4102,7 @@ ColConstraintElem: n->location = @1; $$ = (Node *) n; } - | GENERATED generated_when AS '(' a_expr ')' STORED + | GENERATED generated_when AS '(' a_expr ')' opt_virtual_or_stored { Constraint *n = makeNode(Constraint); @@ -4054,6 +4110,7 @@ ColConstraintElem: n->generated_when = $2; n->raw_expr = $5; n->cooked_expr = NULL; + n->generated_kind = $7; n->location = @1; /* @@ -4083,6 +4140,7 @@ ColConstraintElem: n->fk_upd_action = ($5)->updateAction->action; n->fk_del_action = ($5)->deleteAction->action; n->fk_del_set_cols = ($5)->deleteAction->cols; + n->is_enforced = true; n->skip_validation = false; n->initially_valid = true; $$ = (Node *) n; @@ -4100,6 +4158,12 @@ generated_when: | BY DEFAULT { $$ = ATTRIBUTE_IDENTITY_BY_DEFAULT; } ; +opt_virtual_or_stored: + STORED { $$ = ATTRIBUTE_GENERATED_STORED; } + | VIRTUAL { $$ = ATTRIBUTE_GENERATED_VIRTUAL; } + | /*EMPTY*/ { $$ = ATTRIBUTE_GENERATED_VIRTUAL; } + ; + /* * ConstraintAttr represents constraint attributes, which we parse as if * they were independent constraint clauses, in order to avoid shift/reduce @@ -4148,6 +4212,22 @@ ConstraintAttr: n->location = @1; $$ = (Node *) n; } + | ENFORCED + { + Constraint *n = makeNode(Constraint); + + n->contype = CONSTR_ATTR_ENFORCED; + n->location = @1; + $$ = (Node *) n; + } + | NOT ENFORCED + { + Constraint *n = makeNode(Constraint); + + n->contype = CONSTR_ATTR_NOT_ENFORCED; + n->location = @1; + $$ = (Node *) n; + } ; @@ -4209,12 +4289,25 @@ ConstraintElem: n->raw_expr = $3; n->cooked_expr = NULL; processCASbits($5, @5, "CHECK", - NULL, NULL, &n->skip_validation, + NULL, NULL, &n->is_enforced, &n->skip_validation, &n->is_no_inherit, yyscanner); n->initially_valid = !n->skip_validation; $$ = (Node *) n; } - | UNIQUE opt_unique_null_treatment '(' columnList ')' opt_c_include opt_definition OptConsTableSpace + | NOT NULL_P ColId ConstraintAttributeSpec + { + Constraint *n = makeNode(Constraint); + + n->contype = CONSTR_NOTNULL; + n->location = @1; + n->keys = list_make1(makeString($3)); + processCASbits($4, @4, "NOT NULL", + NULL, NULL, NULL, &n->skip_validation, + &n->is_no_inherit, yyscanner); + n->initially_valid = !n->skip_validation; + $$ = (Node *) n; + } + | UNIQUE opt_unique_null_treatment '(' columnList opt_without_overlaps ')' opt_c_include opt_definition OptConsTableSpace ConstraintAttributeSpec { Constraint *n = makeNode(Constraint); @@ -4223,13 +4316,14 @@ ConstraintElem: n->location = @1; n->nulls_not_distinct = !$2; n->keys = $4; - n->including = $6; - n->options = $7; + n->without_overlaps = $5; + n->including = $7; + n->options = $8; n->indexname = NULL; - n->indexspace = $8; - processCASbits($9, @9, "UNIQUE", + n->indexspace = $9; + processCASbits($10, @10, "UNIQUE", &n->deferrable, &n->initdeferred, NULL, - NULL, yyscanner); + NULL, NULL, yyscanner); $$ = (Node *) n; } | UNIQUE ExistingIndex ConstraintAttributeSpec @@ -4245,10 +4339,10 @@ ConstraintElem: n->indexspace = NULL; processCASbits($3, @3, "UNIQUE", &n->deferrable, &n->initdeferred, NULL, - NULL, yyscanner); + NULL, NULL, yyscanner); $$ = (Node *) n; } - | PRIMARY KEY '(' columnList ')' opt_c_include opt_definition OptConsTableSpace + | PRIMARY KEY '(' columnList opt_without_overlaps ')' opt_c_include opt_definition OptConsTableSpace ConstraintAttributeSpec { Constraint *n = makeNode(Constraint); @@ -4256,13 +4350,14 @@ ConstraintElem: n->contype = CONSTR_PRIMARY; n->location = @1; n->keys = $4; - n->including = $6; - n->options = $7; + n->without_overlaps = $5; + n->including = $7; + n->options = $8; n->indexname = NULL; - n->indexspace = $8; - processCASbits($9, @9, "PRIMARY KEY", + n->indexspace = $9; + processCASbits($10, @10, "PRIMARY KEY", &n->deferrable, &n->initdeferred, NULL, - NULL, yyscanner); + NULL, NULL, yyscanner); $$ = (Node *) n; } | PRIMARY KEY ExistingIndex ConstraintAttributeSpec @@ -4278,7 +4373,7 @@ ConstraintElem: n->indexspace = NULL; processCASbits($4, @4, "PRIMARY KEY", &n->deferrable, &n->initdeferred, NULL, - NULL, yyscanner); + NULL, NULL, yyscanner); $$ = (Node *) n; } | EXCLUDE access_method_clause '(' ExclusionConstraintList ')' @@ -4298,26 +4393,36 @@ ConstraintElem: n->where_clause = $9; processCASbits($10, @10, "EXCLUDE", &n->deferrable, &n->initdeferred, NULL, - NULL, yyscanner); + NULL, NULL, yyscanner); $$ = (Node *) n; } - | FOREIGN KEY '(' columnList ')' REFERENCES qualified_name - opt_column_list key_match key_actions ConstraintAttributeSpec + | FOREIGN KEY '(' columnList optionalPeriodName ')' REFERENCES qualified_name + opt_column_and_period_list key_match key_actions ConstraintAttributeSpec { Constraint *n = makeNode(Constraint); n->contype = CONSTR_FOREIGN; n->location = @1; - n->pktable = $7; + n->pktable = $8; n->fk_attrs = $4; - n->pk_attrs = $8; - n->fk_matchtype = $9; - n->fk_upd_action = ($10)->updateAction->action; - n->fk_del_action = ($10)->deleteAction->action; - n->fk_del_set_cols = ($10)->deleteAction->cols; - processCASbits($11, @11, "FOREIGN KEY", + if ($5) + { + n->fk_attrs = lappend(n->fk_attrs, $5); + n->fk_with_period = true; + } + n->pk_attrs = linitial($9); + if (lsecond($9)) + { + n->pk_attrs = lappend(n->pk_attrs, lsecond($9)); + n->pk_with_period = true; + } + n->fk_matchtype = $10; + n->fk_upd_action = ($11)->updateAction->action; + n->fk_del_action = ($11)->deleteAction->action; + n->fk_del_set_cols = ($11)->deleteAction->cols; + processCASbits($12, @12, "FOREIGN KEY", &n->deferrable, &n->initdeferred, - &n->skip_validation, NULL, + &n->is_enforced, &n->skip_validation, NULL, yyscanner); n->initially_valid = !n->skip_validation; $$ = (Node *) n; @@ -4357,8 +4462,9 @@ DomainConstraintElem: n->raw_expr = $3; n->cooked_expr = NULL; processCASbits($5, @5, "CHECK", - NULL, NULL, &n->skip_validation, + NULL, NULL, NULL, &n->skip_validation, &n->is_no_inherit, yyscanner); + n->is_enforced = true; n->initially_valid = !n->skip_validation; $$ = (Node *) n; } @@ -4369,10 +4475,10 @@ DomainConstraintElem: n->contype = CONSTR_NOTNULL; n->location = @1; n->keys = list_make1(makeString("value")); - /* no NOT VALID support yet */ + /* no NOT VALID, NO INHERIT support */ processCASbits($3, @3, "NOT NULL", NULL, NULL, NULL, - &n->is_no_inherit, yyscanner); + NULL, NULL, yyscanner); n->initially_valid = true; $$ = (Node *) n; } @@ -4382,6 +4488,11 @@ opt_no_inherit: NO INHERIT { $$ = true; } | /* EMPTY */ { $$ = false; } ; +opt_without_overlaps: + WITHOUT OVERLAPS { $$ = true; } + | /*EMPTY*/ { $$ = false; } + ; + opt_column_list: '(' columnList ')' { $$ = $2; } | /*EMPTY*/ { $$ = NIL; } @@ -4392,6 +4503,16 @@ columnList: | columnList ',' columnElem { $$ = lappend($1, $3); } ; +optionalPeriodName: + ',' PERIOD columnElem { $$ = $3; } + | /*EMPTY*/ { $$ = NULL; } + ; + +opt_column_and_period_list: + '(' columnList optionalPeriodName ')' { $$ = list_make2($2, $3); } + | /*EMPTY*/ { $$ = list_make2(NIL, NULL); } + ; + columnElem: ColId { $$ = (Node *) makeString($1); @@ -4571,7 +4692,7 @@ PartitionSpec: PARTITION BY ColId '(' part_params ')' { PartitionSpec *n = makeNode(PartitionSpec); - n->strategy = parsePartitionStrategy($3); + n->strategy = parsePartitionStrategy($3, @3, yyscanner); n->partParams = $5; n->location = @1; @@ -4981,6 +5102,10 @@ SeqOptElem: AS SimpleTypename { $$ = makeDefElem("increment", (Node *) $3, @1); } + | LOGGED + { + $$ = makeDefElem("logged", NULL, @1); + } | MAXVALUE NumericOnly { $$ = makeDefElem("maxvalue", (Node *) $2, @1); @@ -5003,7 +5128,6 @@ SeqOptElem: AS SimpleTypename } | SEQUENCE NAME_P any_name { - /* not documented, only used by pg_dump */ $$ = makeDefElem("sequence_name", (Node *) $3, @1); } | START opt_with NumericOnly @@ -5018,6 +5142,10 @@ SeqOptElem: AS SimpleTypename { $$ = makeDefElem("restart", (Node *) $3, @1); } + | UNLOGGED + { + $$ = makeDefElem("unlogged", NULL, @1); + } ; opt_by: BY @@ -5998,7 +6126,8 @@ CreateTrigStmt: if (n->replace) /* not supported, see CreateTrigger */ ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("CREATE OR REPLACE CONSTRAINT TRIGGER is not supported"))); + errmsg("CREATE OR REPLACE CONSTRAINT TRIGGER is not supported"), + parser_errposition(@1))); n->isconstraint = true; n->trigname = $5; n->relation = $9; @@ -6012,7 +6141,7 @@ CreateTrigStmt: n->transitionRels = NIL; processCASbits($11, @11, "TRIGGER", &n->deferrable, &n->initdeferred, NULL, - NULL, yyscanner); + NULL, NULL, yyscanner); n->constrrel = $10; $$ = (Node *) n; } @@ -6181,7 +6310,8 @@ ConstraintAttributeSpec: parser_errposition(@2))); /* generic message for other conflicts */ if ((newspec & (CAS_NOT_DEFERRABLE | CAS_DEFERRABLE)) == (CAS_NOT_DEFERRABLE | CAS_DEFERRABLE) || - (newspec & (CAS_INITIALLY_IMMEDIATE | CAS_INITIALLY_DEFERRED)) == (CAS_INITIALLY_IMMEDIATE | CAS_INITIALLY_DEFERRED)) + (newspec & (CAS_INITIALLY_IMMEDIATE | CAS_INITIALLY_DEFERRED)) == (CAS_INITIALLY_IMMEDIATE | CAS_INITIALLY_DEFERRED) || + (newspec & (CAS_NOT_ENFORCED | CAS_ENFORCED)) == (CAS_NOT_ENFORCED | CAS_ENFORCED)) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("conflicting constraint properties"), @@ -6197,6 +6327,8 @@ ConstraintAttributeElem: | INITIALLY DEFERRED { $$ = CAS_INITIALLY_DEFERRED; } | NOT VALID { $$ = CAS_NOT_VALID; } | NO INHERIT { $$ = CAS_NO_INHERIT; } + | NOT ENFORCED { $$ = CAS_NOT_ENFORCED; } + | ENFORCED { $$ = CAS_ENFORCED; } ; @@ -6283,7 +6415,8 @@ CreateAssertionStmt: { ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("CREATE ASSERTION is not yet implemented"))); + errmsg("CREATE ASSERTION is not yet implemented"), + parser_errposition(@1))); $$ = NULL; } @@ -6643,7 +6776,7 @@ opclass_item_list: ; opclass_item: - OPERATOR Iconst any_operator opclass_purpose opt_recheck + OPERATOR Iconst any_operator opclass_purpose { CreateOpClassItem *n = makeNode(CreateOpClassItem); ObjectWithArgs *owa = makeNode(ObjectWithArgs); @@ -6657,7 +6790,6 @@ opclass_item: $$ = (Node *) n; } | OPERATOR Iconst operator_with_argtypes opclass_purpose - opt_recheck { CreateOpClassItem *n = makeNode(CreateOpClassItem); @@ -6709,23 +6841,6 @@ opclass_purpose: FOR SEARCH { $$ = NIL; } | /*EMPTY*/ { $$ = NIL; } ; -opt_recheck: RECHECK - { - /* - * RECHECK no longer does anything in opclass definitions, - * but we still accept it to ease porting of old database - * dumps. - */ - ereport(NOTICE, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("RECHECK is no longer required"), - errhint("Update your data type."), - parser_errposition(@1))); - $$ = true; - } - | /*EMPTY*/ { $$ = false; } - ; - CreateOpFamilyStmt: CREATE OPERATOR FAMILY any_name USING name @@ -8145,6 +8260,7 @@ defacl_privilege_target: | SEQUENCES { $$ = OBJECT_SEQUENCE; } | TYPES_P { $$ = OBJECT_TYPE; } | SCHEMAS { $$ = OBJECT_SCHEMA; } + | LARGE_P OBJECTS_P { $$ = OBJECT_LARGEOBJECT; } ; @@ -8344,7 +8460,7 @@ CreateFunctionStmt: n->is_procedure = false; n->replace = $2; n->funcname = $4; - n->parameters = mergeTableFuncParameters($5, $9); + n->parameters = mergeTableFuncParameters($5, $9, yyscanner); n->returnType = TableFuncTypeName($9); n->returnType->location = @7; n->options = $11; @@ -8477,6 +8593,7 @@ func_arg: n->argType = $3; n->mode = $1; n->defexpr = NULL; + n->location = @1; $$ = n; } | param_name arg_class func_type @@ -8487,6 +8604,7 @@ func_arg: n->argType = $3; n->mode = $2; n->defexpr = NULL; + n->location = @1; $$ = n; } | param_name func_type @@ -8497,6 +8615,7 @@ func_arg: n->argType = $2; n->mode = FUNC_PARAM_DEFAULT; n->defexpr = NULL; + n->location = @1; $$ = n; } | arg_class func_type @@ -8507,6 +8626,7 @@ func_arg: n->argType = $2; n->mode = $1; n->defexpr = NULL; + n->location = @1; $$ = n; } | func_type @@ -8517,6 +8637,7 @@ func_arg: n->argType = $1; n->mode = FUNC_PARAM_DEFAULT; n->defexpr = NULL; + n->location = @1; $$ = n; } ; @@ -8853,6 +8974,7 @@ table_func_column: param_name func_type n->argType = $2; n->mode = FUNC_PARAM_TABLE; n->defexpr = NULL; + n->location = @1; $$ = n; } ; @@ -11977,7 +12099,7 @@ opt_name_list: ; vacuum_relation: - qualified_name opt_name_list + relation_expr opt_name_list { $$ = (Node *) makeVacuumRelation($1, InvalidOid, $2); } @@ -12200,7 +12322,7 @@ InsertStmt: { $5->relation = $4; $5->onConflictClause = $6; - $5->returningList = $7; + $5->returningClause = $7; $5->withClause = $1; $$ = (Node *) $5; } @@ -12333,8 +12455,45 @@ opt_conf_expr: ; returning_clause: - RETURNING target_list { $$ = $2; } - | /* EMPTY */ { $$ = NIL; } + RETURNING returning_with_clause target_list + { + ReturningClause *n = makeNode(ReturningClause); + + n->options = $2; + n->exprs = $3; + $$ = n; + } + | /* EMPTY */ + { + $$ = NULL; + } + ; + +returning_with_clause: + WITH '(' returning_options ')' { $$ = $3; } + | /* EMPTY */ { $$ = NIL; } + ; + +returning_options: + returning_option { $$ = list_make1($1); } + | returning_options ',' returning_option { $$ = lappend($1, $3); } + ; + +returning_option: + returning_option_kind AS ColId + { + ReturningOption *n = makeNode(ReturningOption); + + n->option = $1; + n->value = $3; + n->location = @1; + $$ = (Node *) n; + } + ; + +returning_option_kind: + OLD { $$ = RETURNING_OPTION_OLD; } + | NEW { $$ = RETURNING_OPTION_NEW; } ; @@ -12353,7 +12512,7 @@ DeleteStmt: opt_with_clause DELETE_P FROM relation_expr_opt_alias n->relation = $4; n->usingClause = $5; n->whereClause = $6; - n->returningList = $7; + n->returningClause = $7; n->withClause = $1; $$ = (Node *) n; } @@ -12427,7 +12586,7 @@ UpdateStmt: opt_with_clause UPDATE relation_expr_opt_alias n->targetList = $5; n->fromClause = $6; n->whereClause = $7; - n->returningList = $8; + n->returningClause = $8; n->withClause = $1; $$ = (Node *) n; } @@ -12504,7 +12663,7 @@ MergeStmt: m->sourceRelation = $6; m->joinCondition = $8; m->mergeWhenClauses = $9; - m->returningList = $10; + m->returningClause = $10; $$ = (Node *) m; } @@ -13183,11 +13342,13 @@ select_limit: { $$ = $1; ($$)->limitOffset = $2; + ($$)->offsetLoc = @2; } | offset_clause limit_clause { $$ = $2; ($$)->limitOffset = $1; + ($$)->offsetLoc = @1; } | limit_clause { @@ -13200,6 +13361,9 @@ select_limit: n->limitOffset = $1; n->limitCount = NULL; n->limitOption = LIMIT_OPTION_COUNT; + n->offsetLoc = @1; + n->countLoc = -1; + n->optionLoc = -1; $$ = n; } ; @@ -13217,6 +13381,9 @@ limit_clause: n->limitOffset = NULL; n->limitCount = $2; n->limitOption = LIMIT_OPTION_COUNT; + n->offsetLoc = -1; + n->countLoc = @1; + n->optionLoc = -1; $$ = n; } | LIMIT select_limit_value ',' select_offset_value @@ -13242,6 +13409,9 @@ limit_clause: n->limitOffset = NULL; n->limitCount = $3; n->limitOption = LIMIT_OPTION_COUNT; + n->offsetLoc = -1; + n->countLoc = @1; + n->optionLoc = -1; $$ = n; } | FETCH first_or_next select_fetch_first_value row_or_rows WITH TIES @@ -13251,6 +13421,9 @@ limit_clause: n->limitOffset = NULL; n->limitCount = $3; n->limitOption = LIMIT_OPTION_WITH_TIES; + n->offsetLoc = -1; + n->countLoc = @1; + n->optionLoc = @5; $$ = n; } | FETCH first_or_next row_or_rows ONLY @@ -13260,6 +13433,9 @@ limit_clause: n->limitOffset = NULL; n->limitCount = makeIntConst(1, -1); n->limitOption = LIMIT_OPTION_COUNT; + n->offsetLoc = -1; + n->countLoc = @1; + n->optionLoc = -1; $$ = n; } | FETCH first_or_next row_or_rows WITH TIES @@ -13269,6 +13445,9 @@ limit_clause: n->limitOffset = NULL; n->limitCount = makeIntConst(1, -1); n->limitOption = LIMIT_OPTION_WITH_TIES; + n->offsetLoc = -1; + n->countLoc = @1; + n->optionLoc = @4; $$ = n; } ; @@ -14113,7 +14292,7 @@ xmltable_column_el: parser_errposition(defel->location))); fc->colexpr = defel->arg; } - else if (strcmp(defel->defname, "is_not_null") == 0) + else if (strcmp(defel->defname, "__pg__is_not_null") == 0) { if (nullability_seen) ereport(ERROR, @@ -14156,13 +14335,20 @@ xmltable_column_option_list: xmltable_column_option_el: IDENT b_expr - { $$ = makeDefElem($1, $2, @1); } + { + if (strcmp($1, "__pg__is_not_null") == 0) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("option name \"%s\" cannot be used in XMLTABLE", $1), + parser_errposition(@1))); + $$ = makeDefElem($1, $2, @1); + } | DEFAULT b_expr { $$ = makeDefElem("default", $2, @1); } | NOT NULL_P - { $$ = makeDefElem("is_not_null", (Node *) makeBoolean(true), @1); } + { $$ = makeDefElem("__pg__is_not_null", (Node *) makeBoolean(true), @1); } | NULL_P - { $$ = makeDefElem("is_not_null", (Node *) makeBoolean(false), @1); } + { $$ = makeDefElem("__pg__is_not_null", (Node *) makeBoolean(false), @1); } | PATH b_expr { $$ = makeDefElem("path", $2, @1); } ; @@ -15163,49 +15349,50 @@ a_expr: c_expr { $$ = $1; } (Node *) list_make2($5, $7), @2); } - | a_expr IN_P in_expr + | a_expr IN_P select_with_parens { - /* in_expr returns a SubLink or a list of a_exprs */ - if (IsA($3, SubLink)) - { - /* generate foo = ANY (subquery) */ - SubLink *n = (SubLink *) $3; + /* generate foo = ANY (subquery) */ + SubLink *n = makeNode(SubLink); - n->subLinkType = ANY_SUBLINK; - n->subLinkId = 0; - n->testexpr = $1; - n->operName = NIL; /* show it's IN not = ANY */ - n->location = @2; - $$ = (Node *) n; - } - else - { - /* generate scalar IN expression */ - $$ = (Node *) makeSimpleA_Expr(AEXPR_IN, "=", $1, $3, @2); - } + n->subselect = $3; + n->subLinkType = ANY_SUBLINK; + n->subLinkId = 0; + n->testexpr = $1; + n->operName = NIL; /* show it's IN not = ANY */ + n->location = @2; + $$ = (Node *) n; } - | a_expr NOT_LA IN_P in_expr %prec NOT_LA + | a_expr IN_P '(' expr_list ')' { - /* in_expr returns a SubLink or a list of a_exprs */ - if (IsA($4, SubLink)) - { - /* generate NOT (foo = ANY (subquery)) */ - /* Make an = ANY node */ - SubLink *n = (SubLink *) $4; - - n->subLinkType = ANY_SUBLINK; - n->subLinkId = 0; - n->testexpr = $1; - n->operName = NIL; /* show it's IN not = ANY */ - n->location = @2; - /* Stick a NOT on top; must have same parse location */ - $$ = makeNotExpr((Node *) n, @2); - } - else - { - /* generate scalar NOT IN expression */ - $$ = (Node *) makeSimpleA_Expr(AEXPR_IN, "<>", $1, $4, @2); - } + /* generate scalar IN expression */ + A_Expr *n = makeSimpleA_Expr(AEXPR_IN, "=", $1, (Node *) $4, @2); + + n->rexpr_list_start = @3; + n->rexpr_list_end = @5; + $$ = (Node *) n; + } + | a_expr NOT_LA IN_P select_with_parens %prec NOT_LA + { + /* generate NOT (foo = ANY (subquery)) */ + SubLink *n = makeNode(SubLink); + + n->subselect = $4; + n->subLinkType = ANY_SUBLINK; + n->subLinkId = 0; + n->testexpr = $1; + n->operName = NIL; /* show it's IN not = ANY */ + n->location = @2; + /* Stick a NOT on top; must have same parse location */ + $$ = makeNotExpr((Node *) n, @2); + } + | a_expr NOT_LA IN_P '(' expr_list ')' + { + /* generate scalar NOT IN expression */ + A_Expr *n = makeSimpleA_Expr(AEXPR_IN, "<>", $1, (Node *) $5, @2); + + n->rexpr_list_start = @4; + n->rexpr_list_end = @6; + $$ = (Node *) n; } | a_expr subquery_Op sub_type select_with_parens %prec Op { @@ -16640,15 +16827,15 @@ type_list: Typename { $$ = list_make1($1); } array_expr: '[' expr_list ']' { - $$ = makeAArrayExpr($2, @1); + $$ = makeAArrayExpr($2, @1, @3); } | '[' array_expr_list ']' { - $$ = makeAArrayExpr($2, @1); + $$ = makeAArrayExpr($2, @1, @3); } | '[' ']' { - $$ = makeAArrayExpr(NIL, @1); + $$ = makeAArrayExpr(NIL, @1, @2); } ; @@ -16770,17 +16957,6 @@ trim_list: a_expr FROM expr_list { $$ = lappend($3, $1); } | expr_list { $$ = $1; } ; -in_expr: select_with_parens - { - SubLink *n = makeNode(SubLink); - - n->subselect = $1; - /* other fields will be filled later */ - $$ = (Node *) n; - } - | '(' expr_list ')' { $$ = (Node *) $2; } - ; - /* * Define SQL-style CASE clause. * - Full specification @@ -16981,7 +17157,8 @@ json_format_clause: else ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("unrecognized JSON encoding: %s", $4))); + errmsg("unrecognized JSON encoding: %s", $4), + parser_errposition(@4))); $$ = (Node *) makeJsonFormat(JS_FORMAT_JSON, encoding, @1); } @@ -17483,7 +17660,8 @@ PLpgSQL_Expr: opt_distinct_clause opt_target_list $9->limitOption == LIMIT_OPTION_WITH_TIES) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("WITH TIES cannot be specified without ORDER BY clause"))); + errmsg("WITH TIES cannot be specified without ORDER BY clause"), + parser_errposition($9->optionLoc))); n->limitOption = $9->limitOption; } n->lockingClause = $10; @@ -17667,6 +17845,7 @@ unreserved_keyword: | ENABLE_P | ENCODING | ENCRYPTED + | ENFORCED | ENUM_P | ERROR_P | ESCAPE @@ -17762,6 +17941,7 @@ unreserved_keyword: | NOWAIT | NULLS_P | OBJECT_P + | OBJECTS_P | OF | OFF | OIDS @@ -17784,6 +17964,7 @@ unreserved_keyword: | PASSING | PASSWORD | PATH + | PERIOD | PLAN | PLANS | POLICY @@ -17803,7 +17984,6 @@ unreserved_keyword: | RANGE | READ | REASSIGN - | RECHECK | RECURSIVE | REF_P | REFERENCING @@ -17900,6 +18080,7 @@ unreserved_keyword: | VERSION_P | VIEW | VIEWS + | VIRTUAL | VOLATILE | WHITESPACE_P | WITHIN @@ -18244,6 +18425,7 @@ bare_label_keyword: | ENCODING | ENCRYPTED | END_P + | ENFORCED | ENUM_P | ERROR_P | ESCAPE @@ -18382,6 +18564,7 @@ bare_label_keyword: | NULLS_P | NUMERIC | OBJECT_P + | OBJECTS_P | OF | OFF | OIDS @@ -18408,6 +18591,7 @@ bare_label_keyword: | PASSING | PASSWORD | PATH + | PERIOD | PLACING | PLAN | PLANS @@ -18431,7 +18615,6 @@ bare_label_keyword: | READ | REAL | REASSIGN - | RECHECK | RECURSIVE | REF_P | REFERENCES @@ -18554,6 +18737,7 @@ bare_label_keyword: | VERSION_P | VIEW | VIEWS + | VIRTUAL | VOLATILE | WHEN | WHITESPACE_P @@ -18621,10 +18805,10 @@ makeColumnRef(char *colname, List *indirection, int location, core_yyscan_t yyscanner) { /* - * Generate a ColumnRef node, with an A_Indirection node added if there - * is any subscripting in the specified indirection list. However, - * any field selection at the start of the indirection list must be - * transposed into the "fields" part of the ColumnRef node. + * Generate a ColumnRef node, with an A_Indirection node added if there is + * any subscripting in the specified indirection list. However, any field + * selection at the start of the indirection list must be transposed into + * the "fields" part of the ColumnRef node. */ ColumnRef *c = makeNode(ColumnRef); int nfields = 0; @@ -18696,7 +18880,7 @@ makeIntConst(int val, int location) n->val.ival.ival = val; n->location = location; - return (Node *)n; + return (Node *) n; } static Node * @@ -18708,42 +18892,42 @@ makeFloatConst(char *str, int location) n->val.fval.fval = str; n->location = location; - return (Node *)n; + return (Node *) n; } static Node * makeBoolAConst(bool state, int location) { - A_Const *n = makeNode(A_Const); + A_Const *n = makeNode(A_Const); n->val.boolval.type = T_Boolean; n->val.boolval.boolval = state; n->location = location; - return (Node *) n; + return (Node *) n; } static Node * makeBitStringConst(char *str, int location) { - A_Const *n = makeNode(A_Const); + A_Const *n = makeNode(A_Const); n->val.bsval.type = T_BitString; n->val.bsval.bsval = str; n->location = location; - return (Node *)n; + return (Node *) n; } static Node * makeNullAConst(int location) { - A_Const *n = makeNode(A_Const); + A_Const *n = makeNode(A_Const); n->isnull = true; n->location = location; - return (Node *)n; + return (Node *) n; } static Node * @@ -18827,7 +19011,7 @@ check_func_name(List *names, core_yyscan_t yyscanner) static List * check_indirection(List *indirection, core_yyscan_t yyscanner) { - ListCell *l; + ListCell *l; foreach(l, indirection) { @@ -18882,7 +19066,7 @@ makeOrderedSetArgs(List *directargs, List *orderedargs, core_yyscan_t yyscanner) { FunctionParameter *lastd = (FunctionParameter *) llast(directargs); - Integer *ndirectargs; + Integer *ndirectargs; /* No restriction unless last direct arg is VARIADIC */ if (lastd->mode == FUNC_PARAM_VARIADIC) @@ -18890,15 +19074,15 @@ makeOrderedSetArgs(List *directargs, List *orderedargs, FunctionParameter *firsto = (FunctionParameter *) linitial(orderedargs); /* - * We ignore the names, though the aggr_arg production allows them; - * it doesn't allow default values, so those need not be checked. + * We ignore the names, though the aggr_arg production allows them; it + * doesn't allow default values, so those need not be checked. */ if (list_length(orderedargs) != 1 || firsto->mode != FUNC_PARAM_VARIADIC) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("an ordered-set aggregate with a VARIADIC direct argument must have one VARIADIC aggregated argument of the same data type"), - parser_errposition(exprLocation((Node *) firsto)))); + parser_errposition(firsto->location))); /* OK, drop the duplicate VARIADIC argument from the internal form */ orderedargs = NIL; @@ -18946,7 +19130,7 @@ insertSelectOptions(SelectStmt *stmt, ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("multiple OFFSET clauses not allowed"), - parser_errposition(exprLocation(limitClause->limitOffset)))); + parser_errposition(limitClause->offsetLoc))); stmt->limitOffset = limitClause->limitOffset; } if (limitClause && limitClause->limitCount) @@ -18955,19 +19139,18 @@ insertSelectOptions(SelectStmt *stmt, ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("multiple LIMIT clauses not allowed"), - parser_errposition(exprLocation(limitClause->limitCount)))); + parser_errposition(limitClause->countLoc))); stmt->limitCount = limitClause->limitCount; } if (limitClause) { - if (stmt->limitOption) - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("multiple limit options not allowed"))); + /* If there was a conflict, we must have detected it above */ + Assert(!stmt->limitOption); if (!stmt->sortClause && limitClause->limitOption == LIMIT_OPTION_WITH_TIES) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("WITH TIES cannot be specified without ORDER BY clause"))); + errmsg("WITH TIES cannot be specified without ORDER BY clause"), + parser_errposition(limitClause->optionLoc))); if (limitClause->limitOption == LIMIT_OPTION_WITH_TIES && stmt->lockingClause) { ListCell *lc; @@ -18980,7 +19163,8 @@ insertSelectOptions(SelectStmt *stmt, ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("%s and %s options cannot be used together", - "SKIP LOCKED", "WITH TIES"))); + "SKIP LOCKED", "WITH TIES"), + parser_errposition(limitClause->optionLoc))); } } stmt->limitOption = limitClause->limitOption; @@ -19047,7 +19231,7 @@ doNegate(Node *n, int location) { if (IsA(n, A_Const)) { - A_Const *con = (A_Const *) n; + A_Const *con = (A_Const *) n; /* report the constant's location as that of the '-' sign */ con->location = location; @@ -19075,7 +19259,7 @@ doNegateFloat(Float *v) if (*oldval == '+') oldval++; if (*oldval == '-') - v->fval = oldval+1; /* just strip the '-' */ + v->fval = oldval + 1; /* just strip the '-' */ else v->fval = psprintf("-%s", oldval); } @@ -19121,12 +19305,14 @@ makeNotExpr(Node *expr, int location) } static Node * -makeAArrayExpr(List *elements, int location) +makeAArrayExpr(List *elements, int location, int location_end) { A_ArrayExpr *n = makeNode(A_ArrayExpr); n->elements = elements; n->location = location; + n->list_start = location; + n->list_end = location_end; return (Node *) n; } @@ -19146,10 +19332,11 @@ static Node * makeXmlExpr(XmlExprOp op, char *name, List *named_args, List *args, int location) { - XmlExpr *x = makeNode(XmlExpr); + XmlExpr *x = makeNode(XmlExpr); x->op = op; x->name = name; + /* * named_args is a list of ResTarget; it'll be split apart into separate * expression and name lists in transformXmlExpr(). @@ -19159,7 +19346,7 @@ makeXmlExpr(XmlExprOp op, char *name, List *named_args, List *args, x->args = args; /* xmloption, if relevant, must be filled in by caller */ /* type and typmod will be filled in during parse analysis */ - x->type = InvalidOid; /* marks the node as not analyzed */ + x->type = InvalidOid; /* marks the node as not analyzed */ x->location = location; return (Node *) x; } @@ -19168,7 +19355,7 @@ makeXmlExpr(XmlExprOp op, char *name, List *named_args, List *args, * Merge the input and output parameters of a table function. */ static List * -mergeTableFuncParameters(List *func_args, List *columns) +mergeTableFuncParameters(List *func_args, List *columns, core_yyscan_t yyscanner) { ListCell *lc; @@ -19182,7 +19369,8 @@ mergeTableFuncParameters(List *func_args, List *columns) p->mode != FUNC_PARAM_VARIADIC) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("OUT and INOUT arguments aren't allowed in TABLE functions"))); + errmsg("OUT and INOUT arguments aren't allowed in TABLE functions"), + parser_errposition(p->location))); } return list_concat(func_args, columns); @@ -19283,7 +19471,7 @@ makeRangeVarFromQualifiedName(char *name, List *namelist, int location, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("improper qualified name (too many dotted names): %s", NameListToString(lcons(makeString(name), namelist))), - parser_errposition(location))); + parser_errposition(location))); break; } @@ -19334,8 +19522,8 @@ SplitColQualList(List *qualList, */ static void processCASbits(int cas_bits, int location, const char *constrType, - bool *deferrable, bool *initdeferred, bool *not_valid, - bool *no_inherit, core_yyscan_t yyscanner) + bool *deferrable, bool *initdeferred, bool *is_enforced, + bool *not_valid, bool *no_inherit, core_yyscan_t yyscanner) { /* defaults */ if (deferrable) @@ -19344,6 +19532,8 @@ processCASbits(int cas_bits, int location, const char *constrType, *initdeferred = false; if (not_valid) *not_valid = false; + if (is_enforced) + *is_enforced = true; if (cas_bits & (CAS_DEFERRABLE | CAS_INITIALLY_DEFERRED)) { @@ -19352,7 +19542,7 @@ processCASbits(int cas_bits, int location, const char *constrType, else ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - /* translator: %s is CHECK, UNIQUE, or similar */ + /* translator: %s is CHECK, UNIQUE, or similar */ errmsg("%s constraints cannot be marked DEFERRABLE", constrType), parser_errposition(location))); @@ -19365,7 +19555,7 @@ processCASbits(int cas_bits, int location, const char *constrType, else ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - /* translator: %s is CHECK, UNIQUE, or similar */ + /* translator: %s is CHECK, UNIQUE, or similar */ errmsg("%s constraints cannot be marked DEFERRABLE", constrType), parser_errposition(location))); @@ -19378,7 +19568,7 @@ processCASbits(int cas_bits, int location, const char *constrType, else ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - /* translator: %s is CHECK, UNIQUE, or similar */ + /* translator: %s is CHECK, UNIQUE, or similar */ errmsg("%s constraints cannot be marked NOT VALID", constrType), parser_errposition(location))); @@ -19391,11 +19581,46 @@ processCASbits(int cas_bits, int location, const char *constrType, else ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - /* translator: %s is CHECK, UNIQUE, or similar */ + /* translator: %s is CHECK, UNIQUE, or similar */ errmsg("%s constraints cannot be marked NO INHERIT", constrType), parser_errposition(location))); } + + if (cas_bits & CAS_NOT_ENFORCED) + { + if (is_enforced) + *is_enforced = false; + else + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + /* translator: %s is CHECK, UNIQUE, or similar */ + errmsg("%s constraints cannot be marked NOT ENFORCED", + constrType), + parser_errposition(location))); + + /* + * NB: The validated status is irrelevant when the constraint is set to + * NOT ENFORCED, but for consistency, it should be set accordingly. + * This ensures that if the constraint is later changed to ENFORCED, it + * will automatically be in the correct NOT VALIDATED state. + */ + if (not_valid) + *not_valid = true; + } + + if (cas_bits & CAS_ENFORCED) + { + if (is_enforced) + *is_enforced = true; + else + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + /* translator: %s is CHECK, UNIQUE, or similar */ + errmsg("%s constraints cannot be marked ENFORCED", + constrType), + parser_errposition(location))); + } } /* @@ -19403,7 +19628,7 @@ processCASbits(int cas_bits, int location, const char *constrType, * PartitionStrategy representation, or die trying. */ static PartitionStrategy -parsePartitionStrategy(char *strategy) +parsePartitionStrategy(char *strategy, int location, core_yyscan_t yyscanner) { if (pg_strcasecmp(strategy, "list") == 0) return PARTITION_STRATEGY_LIST; @@ -19414,9 +19639,9 @@ parsePartitionStrategy(char *strategy) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("unrecognized partitioning strategy \"%s\"", - strategy))); - return PARTITION_STRATEGY_LIST; /* keep compiler quiet */ + errmsg("unrecognized partitioning strategy \"%s\"", strategy), + parser_errposition(location))); + return PARTITION_STRATEGY_LIST; /* keep compiler quiet */ } @@ -19487,8 +19712,8 @@ preprocess_pubobj_list(List *pubobjspec_list, core_yyscan_t yyscanner) parser_errposition(pubobj->location))); /* - * We can distinguish between the different type of schema - * objects based on whether name and pubtable is set. + * We can distinguish between the different type of schema objects + * based on whether name and pubtable is set. */ if (pubobj->name) pubobj->pubobjtype = PUBLICATIONOBJ_TABLES_IN_SCHEMA; @@ -19543,11 +19768,13 @@ makeRecursiveViewSelect(char *relname, List *aliases, Node *query) w->ctes = list_make1(cte); w->location = -1; - /* create target list for the new SELECT from the alias list of the - * recursive view specification */ - foreach (lc, aliases) + /* + * create target list for the new SELECT from the alias list of the + * recursive view specification + */ + foreach(lc, aliases) { - ResTarget *rt = makeNode(ResTarget); + ResTarget *rt = makeNode(ResTarget); rt->name = NULL; rt->indirection = NIL; @@ -19557,8 +19784,10 @@ makeRecursiveViewSelect(char *relname, List *aliases, Node *query) tl = lappend(tl, rt); } - /* create new SELECT combining WITH clause, target list, and fake FROM - * clause */ + /* + * create new SELECT combining WITH clause, target list, and fake FROM + * clause + */ s->withClause = w; s->targetList = tl; s->fromClause = list_make1(makeRangeVar(NULL, relname, -1)); diff --git a/src/parser/gram_minimal.y b/src/parser/gram_minimal.y index e11074e1f..dc540e1c9 100644 --- a/src/parser/gram_minimal.y +++ b/src/parser/gram_minimal.y @@ -6,8 +6,8 @@ * gram.y * POSTGRESQL BISON rules/actions * - * Portions Copyright (c) 2003-2024, PgPool Global Development Group - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2003-2025, PgPool Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -89,6 +89,8 @@ #define ATTRIBUTE_IDENTITY_ALWAYS 'a' #define ATTRIBUTE_IDENTITY_BY_DEFAULT 'd' +#define ATTRIBUTE_GENERATED_STORED 's' +#define ATTRIBUTE_GENERATED_VIRTUAL 'v' /* * Definition taken from * postgreSQL source code file: src/include/utils/xml.h @@ -102,40 +104,26 @@ typedef enum } XmlStandaloneType; /* - * Location tracking support --- simpler than bison's default, since we only - * want to track the start position not the end position of each nonterminal. + * Location tracking support. Unlike bison's default, we only want + * to track the start position not the end position of each nonterminal. + * Nonterminals that reduce to empty receive position "-1". Since a + * production's leading RHS nonterminal(s) may have reduced to empty, + * we have to scan to find the first one that's not -1. */ #define YYLLOC_DEFAULT(Current, Rhs, N) \ do { \ - if ((N) > 0) \ - (Current) = (Rhs)[1]; \ - else \ - (Current) = (-1); \ + (Current) = (-1); \ + for (int _i = 1; _i <= (N); _i++) \ + { \ + if ((Rhs)[_i] >= 0) \ + { \ + (Current) = (Rhs)[_i]; \ + break; \ + } \ + } \ } while (0) /* - * The above macro assigns -1 (unknown) as the parse location of any - * nonterminal that was reduced from an empty rule, or whose leftmost - * component was reduced from an empty rule. This is problematic - * for nonterminals defined like - * OptFooList: / * EMPTY * / { ... } | OptFooList Foo { ... } ; - * because we'll set -1 as the location during the first reduction and then - * copy it during each subsequent reduction, leaving us with -1 for the - * location even when the list is not empty. To fix that, do this in the - * action for the nonempty rule(s): - * if (@$ < 0) @$ = @2; - * (Although we have many nonterminals that follow this pattern, we only - * bother with fixing @$ like this when the nonterminal's parse location - * is actually referenced in some rule.) - * - * A cleaner answer would be to make YYLLOC_DEFAULT scan all the Rhs - * locations until it's found one that's not -1. Then we'd get a correct - * location for any nonterminal that isn't entirely empty. But this way - * would add overhead to every rule reduction, and so far there's not been - * a compelling reason to pay that overhead. - */ - -/* * Bison doesn't allocate anything that needs to live across parser calls, * so we can easily have it use palloc instead of malloc. This prevents * memory leaks if we error out during parsing. @@ -158,12 +146,15 @@ typedef struct ImportQual List *table_names; } ImportQual; -/* Private struct for the result of opt_select_limit production */ +/* Private struct for the result of select_limit & limit_clause productions */ typedef struct SelectLimit { Node *limitOffset; Node *limitCount; - LimitOption limitOption; + LimitOption limitOption; /* indicates presence of WITH TIES */ + ParseLoc offsetLoc; /* location of OFFSET token, if present */ + ParseLoc countLoc; /* location of LIMIT/FETCH token, if present */ + ParseLoc optionLoc; /* location of WITH TIES, if present */ } SelectLimit; /* Private struct for the result of group_clause production */ @@ -193,6 +184,8 @@ typedef struct KeyActions #define CAS_INITIALLY_DEFERRED 0x08 #define CAS_NOT_VALID 0x10 #define CAS_NO_INHERIT 0x20 +#define CAS_NOT_ENFORCED 0x40 +#define CAS_ENFORCED 0x80 #define parser_yyerror(msg) scanner_yyerror(msg, yyscanner) @@ -228,12 +221,12 @@ static void doNegateFloat(Float *v); static Node *makeAndExpr(Node *lexpr, Node *rexpr, int location); static Node *makeOrExpr(Node *lexpr, Node *rexpr, int location); static Node *makeNotExpr(Node *expr, int location); -static Node *makeAArrayExpr(List *elements, int location); +static Node *makeAArrayExpr(List *elements, int location, int end_location); static Node *makeSQLValueFunction(SQLValueFunctionOp op, int32 typmod, int location); static Node *makeXmlExpr(XmlExprOp op, char *name, List *named_args, List *args, int location); -static List *mergeTableFuncParameters(List *func_args, List *columns); +static List *mergeTableFuncParameters(List *func_args, List *columns, core_yyscan_t yyscanner); static TypeName *TableFuncTypeName(List *columns); static RangeVar *makeRangeVarFromAnyName(List *names, int position, core_yyscan_t yyscanner); static RangeVar *makeRangeVarFromQualifiedName(char *name, List *namelist, int location, @@ -242,9 +235,10 @@ static void SplitColQualList(List *qualList, List **constraintList, CollateClause **collClause, core_yyscan_t yyscanner); static void processCASbits(int cas_bits, int location, const char *constrType, - bool *deferrable, bool *initdeferred, bool *not_valid, - bool *no_inherit, core_yyscan_t yyscanner); -static PartitionStrategy parsePartitionStrategy(char *strategy); + bool *deferrable, bool *initdeferred, bool *is_enforced, + bool *not_valid, bool *no_inherit, core_yyscan_t yyscanner); +static PartitionStrategy parsePartitionStrategy(char *strategy, int location, + core_yyscan_t yyscanner); static void preprocess_pubobj_list(List *pubobjspec_list, core_yyscan_t yyscanner); static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); @@ -310,6 +304,8 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); MergeWhenClause *mergewhen; struct KeyActions *keyactions; struct KeyAction *keyaction; + ReturningClause *retclause; + ReturningOptionKind retoptionkind; } %type <node> stmt toplevel_stmt schema_stmt routine_body_stmt @@ -482,7 +478,8 @@ UpdateStmtShort opclass_purpose opt_opfamily transaction_mode_list_or_empty OptTableFuncElementList TableFuncElementList opt_type_modifiers prep_type_clause - execute_param_clause using_clause returning_clause + execute_param_clause using_clause + returning_with_clause returning_options opt_enum_val_list enum_val_list table_func_column_list create_generic_options alter_generic_options relation_expr_list dostmt_opt_list @@ -491,6 +488,9 @@ UpdateStmtShort vacuum_relation_list opt_vacuum_relation_list drop_option_list pub_obj_list +%type <retclause> returning_clause +%type <node> returning_option +%type <retoptionkind> returning_option_kind %type <node> opt_routine_body %type <groupclause> group_clause %type <list> group_by_list @@ -529,7 +529,7 @@ UpdateStmtShort %type <boolean> opt_instead %type <boolean> opt_unique opt_verbose opt_full -%type <boolean> opt_freeze opt_analyze opt_default opt_recheck +%type <boolean> opt_freeze opt_analyze opt_default %type <defelt> opt_binary copy_delimiter %type <boolean> copy_from opt_program @@ -559,14 +559,15 @@ UpdateStmtShort SetResetClause FunctionSetResetClause %type <node> TableElement TypedTableElement ConstraintElem DomainConstraintElem TableFuncElement -%type <node> columnDef columnOptions +%type <node> columnDef columnOptions optionalPeriodName %type <defelt> def_elem reloption_elem old_aggr_elem operator_def_elem %type <node> def_arg columnElem where_clause where_or_current_clause a_expr b_expr c_expr AexprConst indirection_el opt_slice_bound - columnref in_expr having_clause func_table xmltable array_expr + columnref having_clause func_table xmltable array_expr OptWhereClause operator_def_arg +%type <list> opt_column_and_period_list %type <list> rowsfrom_item rowsfrom_list opt_col_def_list -%type <boolean> opt_ordinality +%type <boolean> opt_ordinality opt_without_overlaps %type <list> ExclusionConstraintList ExclusionConstraintElem %type <list> func_arg_list func_arg_list_opt %type <node> func_arg_expr @@ -675,7 +676,7 @@ UpdateStmtShort %type <str> opt_existing_window_name %type <boolean> opt_if_not_exists %type <boolean> opt_unique_null_treatment -%type <ival> generated_when override_kind +%type <ival> generated_when override_kind opt_virtual_or_stored %type <partspec> PartitionSpec OptPartitionSpec %type <partelem> part_elem %type <list> part_params @@ -758,9 +759,9 @@ UpdateStmtShort DETACH DICTIONARY DISABLE_P DISCARD DISTINCT DO DOCUMENT_P DOMAIN_P DOUBLE_P DROP - EACH ELSE EMPTY_P ENABLE_P ENCODING ENCRYPTED END_P ENUM_P ERROR_P ESCAPE - EVENT EXCEPT EXCLUDE EXCLUDING EXCLUSIVE EXECUTE EXISTS EXPLAIN EXPRESSION - EXTENSION EXTERNAL EXTRACT + EACH ELSE EMPTY_P ENABLE_P ENCODING ENCRYPTED END_P ENFORCED ENUM_P ERROR_P + ESCAPE EVENT EXCEPT EXCLUDE EXCLUDING EXCLUSIVE EXECUTE EXISTS EXPLAIN + EXPRESSION EXTENSION EXTERNAL EXTRACT FALSE_P FAMILY FETCH FILTER FINALIZE FIRST_P FLOAT_P FOLLOWING FOR FORCE FOREIGN FORMAT FORWARD FREEZE FROM FULL FUNCTION FUNCTIONS @@ -791,18 +792,18 @@ UpdateStmtShort NOT NOTHING NOTIFY NOTNULL NOWAIT NULL_P NULLIF NULLS_P NUMERIC - OBJECT_P OF OFF OFFSET OIDS OLD OMIT ON ONLY OPERATOR OPTION OPTIONS OR + OBJECT_P OBJECTS_P OF OFF OFFSET OIDS OLD OMIT ON ONLY OPERATOR OPTION OPTIONS OR ORDER ORDINALITY OTHERS OUT_P OUTER_P OVER OVERLAPS OVERLAY OVERRIDING OWNED OWNER PARALLEL PARAMETER PARSER PARTIAL PARTITION PASSING PASSWORD PATH PGPOOL - PLACING PLAN PLANS POLICY + PERIOD PLACING PLAN PLANS POLICY POSITION PRECEDING PRECISION PRESERVE PREPARE PREPARED PRIMARY PRIOR PRIVILEGES PROCEDURAL PROCEDURE PROCEDURES PROGRAM PUBLICATION QUOTE QUOTES - RANGE READ REAL REASSIGN RECHECK RECURSIVE REF_P REFERENCES REFERENCING + RANGE READ REAL REASSIGN RECURSIVE REF_P REFERENCES REFERENCING REFRESH REINDEX RELATIVE_P RELEASE RENAME REPEATABLE REPLACE REPLICA RESET RESTART RESTRICT RETURN RETURNING RETURNS REVOKE RIGHT ROLE ROLLBACK ROLLUP ROUTINE ROUTINES ROW ROWS RULE @@ -823,7 +824,7 @@ UpdateStmtShort UNLISTEN UNLOGGED UNTIL UPDATE USER USING VACUUM VALID VALIDATE VALIDATOR VALUE_P VALUES VARCHAR VARIADIC VARYING - VERBOSE VERSION_P VIEW VIEWS VOLATILE + VERBOSE VERSION_P VIEW VIEWS VIRTUAL VOLATILE WHEN WHERE WHITESPACE_P WINDOW WITH WITHIN WITHOUT WORK WRAPPER WRITE @@ -964,7 +965,7 @@ parse_toplevel: | MODE_PLPGSQL_EXPR PLpgSQL_Expr { pg_yyget_extra(yyscanner)->parsetree = - list_make1(makeRawStmt($2, 0)); + list_make1(makeRawStmt($2, @2)); } | MODE_PLPGSQL_ASSIGN1 PLAssignStmt { @@ -972,7 +973,7 @@ parse_toplevel: n->nnames = 1; pg_yyget_extra(yyscanner)->parsetree = - list_make1(makeRawStmt((Node *) n, 0)); + list_make1(makeRawStmt((Node *) n, @2)); } | MODE_PLPGSQL_ASSIGN2 PLAssignStmt { @@ -980,7 +981,7 @@ parse_toplevel: n->nnames = 2; pg_yyget_extra(yyscanner)->parsetree = - list_make1(makeRawStmt((Node *) n, 0)); + list_make1(makeRawStmt((Node *) n, @2)); } | MODE_PLPGSQL_ASSIGN3 PLAssignStmt { @@ -988,19 +989,15 @@ parse_toplevel: n->nnames = 3; pg_yyget_extra(yyscanner)->parsetree = - list_make1(makeRawStmt((Node *) n, 0)); + list_make1(makeRawStmt((Node *) n, @2)); } ; /* * At top level, we wrap each stmt with a RawStmt node carrying start location - * and length of the stmt's text. Notice that the start loc/len are driven - * entirely from semicolon locations (@2). It would seem natural to use - * @1 or @3 to get the true start location of a stmt, but that doesn't work - * for statements that can start with empty nonterminals (opt_with_clause is - * the main offender here); as noted in the comments for YYLLOC_DEFAULT, - * we'd get -1 for the location in such cases. - * We also take care to discard empty statements entirely. + * and length of the stmt's text. + * We also take care to discard empty statements entirely (which among other + * things dodges the problem of assigning them a location). */ stmtmulti: stmtmulti ';' toplevel_stmt { @@ -1010,14 +1007,14 @@ stmtmulti: stmtmulti ';' toplevel_stmt updateRawStmtEnd(llast_node(RawStmt, $1), @2); } if ($3 != NULL) - $$ = lappend($1, makeRawStmt($3, @2 + 1)); + $$ = lappend($1, makeRawStmt($3, @3)); else $$ = $1; } | toplevel_stmt { if ($1 != NULL) - $$ = list_make1(makeRawStmt($1, 0)); + $$ = list_make1(makeRawStmt($1, @1)); else $$ = NIL; } @@ -1618,8 +1615,6 @@ CreateSchemaStmt: OptSchemaEltList: OptSchemaEltList schema_stmt { - if (@$ < 0) /* see comments for YYLLOC_DEFAULT */ - @$ = @2; $$ = lappend($1, $2); } | /* EMPTY */ @@ -1657,6 +1652,13 @@ VariableSetStmt: n->is_local = false; $$ = (Node *) n; } + | PGPOOL set_rest_more + { + VariableSetStmt *n = $2; + n->type = T_PgpoolQueryCacheStmt; /* Hack to keep changes minimum */ + n->is_local = false; + $$ = (Node *) n; + } | SET set_rest { VariableSetStmt *n = $2; @@ -1688,6 +1690,8 @@ set_rest: n->kind = VAR_SET_MULTI; n->name = "TRANSACTION"; n->args = $2; + n->jumble_args = true; + n->location = -1; $$ = n; } | SESSION CHARACTERISTICS AS TRANSACTION transaction_mode_list @@ -1697,6 +1701,8 @@ set_rest: n->kind = VAR_SET_MULTI; n->name = "SESSION CHARACTERISTICS"; n->args = $5; + n->jumble_args = true; + n->location = -1; $$ = n; } | set_rest_more @@ -1710,6 +1716,7 @@ generic_set: n->kind = VAR_SET_VALUE; n->name = $1; n->args = $3; + n->location = @3; $$ = n; } | var_name '=' var_list @@ -1719,6 +1726,7 @@ generic_set: n->kind = VAR_SET_VALUE; n->name = $1; n->args = $3; + n->location = @3; $$ = n; } | var_name TO DEFAULT @@ -1727,6 +1735,7 @@ generic_set: n->kind = VAR_SET_DEFAULT; n->name = $1; + n->location = -1; $$ = n; } | var_name '=' DEFAULT @@ -1735,6 +1744,7 @@ generic_set: n->kind = VAR_SET_DEFAULT; n->name = $1; + n->location = -1; $$ = n; } ; @@ -1747,6 +1757,7 @@ set_rest_more: /* Generic SET syntaxes: */ n->kind = VAR_SET_CURRENT; n->name = $1; + n->location = -1; $$ = n; } /* Special syntaxes mandated by SQL standard: */ @@ -1756,6 +1767,8 @@ set_rest_more: /* Generic SET syntaxes: */ n->kind = VAR_SET_VALUE; n->name = "timezone"; + n->location = -1; + n->jumble_args = true; if ($3 != NULL) n->args = list_make1($3); else @@ -1777,6 +1790,7 @@ set_rest_more: /* Generic SET syntaxes: */ n->kind = VAR_SET_VALUE; n->name = "search_path"; n->args = list_make1(makeStringConst($2, @2)); + n->location = @2; $$ = n; } | NAMES opt_encoding @@ -1785,6 +1799,7 @@ set_rest_more: /* Generic SET syntaxes: */ n->kind = VAR_SET_VALUE; n->name = "client_encoding"; + n->location = @2; if ($2 != NULL) n->args = list_make1(makeStringConst($2, @2)); else @@ -1798,6 +1813,7 @@ set_rest_more: /* Generic SET syntaxes: */ n->kind = VAR_SET_VALUE; n->name = "role"; n->args = list_make1(makeStringConst($2, @2)); + n->location = @2; $$ = n; } | SESSION AUTHORIZATION NonReservedWord_or_Sconst @@ -1807,6 +1823,7 @@ set_rest_more: /* Generic SET syntaxes: */ n->kind = VAR_SET_VALUE; n->name = "session_authorization"; n->args = list_make1(makeStringConst($3, @3)); + n->location = @3; $$ = n; } | SESSION AUTHORIZATION DEFAULT @@ -1815,6 +1832,7 @@ set_rest_more: /* Generic SET syntaxes: */ n->kind = VAR_SET_DEFAULT; n->name = "session_authorization"; + n->location = -1; $$ = n; } | XML_P OPTION document_or_content @@ -1824,6 +1842,8 @@ set_rest_more: /* Generic SET syntaxes: */ n->kind = VAR_SET_VALUE; n->name = "xmloption"; n->args = list_make1(makeStringConst($3 == XMLOPTION_DOCUMENT ? "DOCUMENT" : "CONTENT", @3)); + n->jumble_args = true; + n->location = -1; $$ = n; } /* Special syntaxes invented by PostgreSQL: */ @@ -1834,6 +1854,14 @@ set_rest_more: /* Generic SET syntaxes: */ n->kind = VAR_SET_MULTI; n->name = "TRANSACTION SNAPSHOT"; n->args = list_make1(makeStringConst($3, @3)); + n->location = @3; + $$ = n; + } + /* PGPOOL CACHE DELETE */ + | SET CACHE DELETE_P Sconst + { + VariableSetStmt *n = makeNode(VariableSetStmt); + n->name = $4; /* query to delete query cache */ $$ = n; } ; @@ -1947,6 +1975,7 @@ reset_rest: n->kind = VAR_RESET; n->name = "timezone"; + n->location = -1; $$ = n; } | TRANSACTION ISOLATION LEVEL @@ -1955,6 +1984,7 @@ reset_rest: n->kind = VAR_RESET; n->name = "transaction_isolation"; + n->location = -1; $$ = n; } | SESSION AUTHORIZATION @@ -1963,6 +1993,7 @@ reset_rest: n->kind = VAR_RESET; n->name = "session_authorization"; + n->location = -1; $$ = n; } ; @@ -1974,6 +2005,7 @@ generic_reset: n->kind = VAR_RESET; n->name = $1; + n->location = -1; $$ = n; } | ALL @@ -1981,6 +2013,7 @@ generic_reset: VariableSetStmt *n = makeNode(VariableSetStmt); n->kind = VAR_RESET_ALL; + n->location = -1; $$ = n; } ; @@ -2703,15 +2736,45 @@ alter_table_cmd: | ALTER CONSTRAINT name ConstraintAttributeSpec { AlterTableCmd *n = makeNode(AlterTableCmd); - Constraint *c = makeNode(Constraint); + ATAlterConstraint *c = makeNode(ATAlterConstraint); + n->subtype = AT_AlterConstraint; n->def = (Node *) c; - c->contype = CONSTR_FOREIGN; /* others not supported, yet */ c->conname = $3; - processCASbits($4, @4, "ALTER CONSTRAINT statement", + if ($4 & (CAS_NOT_ENFORCED | CAS_ENFORCED)) + c->alterEnforceability = true; + if ($4 & (CAS_DEFERRABLE | CAS_NOT_DEFERRABLE | + CAS_INITIALLY_DEFERRED | CAS_INITIALLY_IMMEDIATE)) + c->alterDeferrability = true; + if ($4 & CAS_NO_INHERIT) + c->alterInheritability = true; + /* handle unsupported case with specific error message */ + if ($4 & CAS_NOT_VALID) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("constraints cannot be altered to be NOT VALID"), + parser_errposition(@4))); + processCASbits($4, @4, "FOREIGN KEY", &c->deferrable, &c->initdeferred, - NULL, NULL, yyscanner); + &c->is_enforced, + NULL, + &c->noinherit, + yyscanner); + $$ = (Node *) n; + } + /* ALTER TABLE <name> ALTER CONSTRAINT INHERIT */ + | ALTER CONSTRAINT name INHERIT + { + AlterTableCmd *n = makeNode(AlterTableCmd); + ATAlterConstraint *c = makeNode(ATAlterConstraint); + + n->subtype = AT_AlterConstraint; + n->def = (Node *) c; + c->conname = $3; + c->alterInheritability = true; + c->noinherit = false; + $$ = (Node *) n; } /* ALTER TABLE <name> VALIDATE CONSTRAINT ... */ @@ -3202,11 +3265,13 @@ PartitionBoundSpec: if (n->modulus == -1) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("modulus for hash partition must be specified"))); + errmsg("modulus for hash partition must be specified"), + parser_errposition(@3))); if (n->remainder == -1) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("remainder for hash partition must be specified"))); + errmsg("remainder for hash partition must be specified"), + parser_errposition(@3))); n->location = @3; @@ -3958,12 +4023,16 @@ ColConstraint: * or be part of a_expr NOT LIKE or similar constructs). */ ColConstraintElem: - NOT NULL_P + NOT NULL_P opt_no_inherit { Constraint *n = makeNode(Constraint); n->contype = CONSTR_NOTNULL; n->location = @1; + n->is_no_inherit = $3; + n->is_enforced = true; + n->skip_validation = false; + n->initially_valid = true; $$ = (Node *) n; } | NULL_P @@ -4008,6 +4077,7 @@ ColConstraintElem: n->is_no_inherit = $5; n->raw_expr = $3; n->cooked_expr = NULL; + n->is_enforced = true; n->skip_validation = false; n->initially_valid = true; $$ = (Node *) n; @@ -4034,7 +4104,7 @@ ColConstraintElem: n->location = @1; $$ = (Node *) n; } - | GENERATED generated_when AS '(' a_expr ')' STORED + | GENERATED generated_when AS '(' a_expr ')' opt_virtual_or_stored { Constraint *n = makeNode(Constraint); @@ -4042,6 +4112,7 @@ ColConstraintElem: n->generated_when = $2; n->raw_expr = $5; n->cooked_expr = NULL; + n->generated_kind = $7; n->location = @1; /* @@ -4071,6 +4142,7 @@ ColConstraintElem: n->fk_upd_action = ($5)->updateAction->action; n->fk_del_action = ($5)->deleteAction->action; n->fk_del_set_cols = ($5)->deleteAction->cols; + n->is_enforced = true; n->skip_validation = false; n->initially_valid = true; $$ = (Node *) n; @@ -4088,6 +4160,12 @@ generated_when: | BY DEFAULT { $$ = ATTRIBUTE_IDENTITY_BY_DEFAULT; } ; +opt_virtual_or_stored: + STORED { $$ = ATTRIBUTE_GENERATED_STORED; } + | VIRTUAL { $$ = ATTRIBUTE_GENERATED_VIRTUAL; } + | /*EMPTY*/ { $$ = ATTRIBUTE_GENERATED_VIRTUAL; } + ; + /* * ConstraintAttr represents constraint attributes, which we parse as if * they were independent constraint clauses, in order to avoid shift/reduce @@ -4136,6 +4214,22 @@ ConstraintAttr: n->location = @1; $$ = (Node *) n; } + | ENFORCED + { + Constraint *n = makeNode(Constraint); + + n->contype = CONSTR_ATTR_ENFORCED; + n->location = @1; + $$ = (Node *) n; + } + | NOT ENFORCED + { + Constraint *n = makeNode(Constraint); + + n->contype = CONSTR_ATTR_NOT_ENFORCED; + n->location = @1; + $$ = (Node *) n; + } ; @@ -4197,12 +4291,25 @@ ConstraintElem: n->raw_expr = $3; n->cooked_expr = NULL; processCASbits($5, @5, "CHECK", - NULL, NULL, &n->skip_validation, + NULL, NULL, &n->is_enforced, &n->skip_validation, + &n->is_no_inherit, yyscanner); + n->initially_valid = !n->skip_validation; + $$ = (Node *) n; + } + | NOT NULL_P ColId ConstraintAttributeSpec + { + Constraint *n = makeNode(Constraint); + + n->contype = CONSTR_NOTNULL; + n->location = @1; + n->keys = list_make1(makeString($3)); + processCASbits($4, @4, "NOT NULL", + NULL, NULL, NULL, &n->skip_validation, &n->is_no_inherit, yyscanner); n->initially_valid = !n->skip_validation; $$ = (Node *) n; } - | UNIQUE opt_unique_null_treatment '(' columnList ')' opt_c_include opt_definition OptConsTableSpace + | UNIQUE opt_unique_null_treatment '(' columnList opt_without_overlaps ')' opt_c_include opt_definition OptConsTableSpace ConstraintAttributeSpec { Constraint *n = makeNode(Constraint); @@ -4211,13 +4318,14 @@ ConstraintElem: n->location = @1; n->nulls_not_distinct = !$2; n->keys = $4; - n->including = $6; - n->options = $7; + n->without_overlaps = $5; + n->including = $7; + n->options = $8; n->indexname = NULL; - n->indexspace = $8; - processCASbits($9, @9, "UNIQUE", + n->indexspace = $9; + processCASbits($10, @10, "UNIQUE", &n->deferrable, &n->initdeferred, NULL, - NULL, yyscanner); + NULL, NULL, yyscanner); $$ = (Node *) n; } | UNIQUE ExistingIndex ConstraintAttributeSpec @@ -4233,10 +4341,10 @@ ConstraintElem: n->indexspace = NULL; processCASbits($3, @3, "UNIQUE", &n->deferrable, &n->initdeferred, NULL, - NULL, yyscanner); + NULL, NULL, yyscanner); $$ = (Node *) n; } - | PRIMARY KEY '(' columnList ')' opt_c_include opt_definition OptConsTableSpace + | PRIMARY KEY '(' columnList opt_without_overlaps ')' opt_c_include opt_definition OptConsTableSpace ConstraintAttributeSpec { Constraint *n = makeNode(Constraint); @@ -4244,13 +4352,14 @@ ConstraintElem: n->contype = CONSTR_PRIMARY; n->location = @1; n->keys = $4; - n->including = $6; - n->options = $7; + n->without_overlaps = $5; + n->including = $7; + n->options = $8; n->indexname = NULL; - n->indexspace = $8; - processCASbits($9, @9, "PRIMARY KEY", + n->indexspace = $9; + processCASbits($10, @10, "PRIMARY KEY", &n->deferrable, &n->initdeferred, NULL, - NULL, yyscanner); + NULL, NULL, yyscanner); $$ = (Node *) n; } | PRIMARY KEY ExistingIndex ConstraintAttributeSpec @@ -4266,7 +4375,7 @@ ConstraintElem: n->indexspace = NULL; processCASbits($4, @4, "PRIMARY KEY", &n->deferrable, &n->initdeferred, NULL, - NULL, yyscanner); + NULL, NULL, yyscanner); $$ = (Node *) n; } | EXCLUDE access_method_clause '(' ExclusionConstraintList ')' @@ -4286,26 +4395,36 @@ ConstraintElem: n->where_clause = $9; processCASbits($10, @10, "EXCLUDE", &n->deferrable, &n->initdeferred, NULL, - NULL, yyscanner); + NULL, NULL, yyscanner); $$ = (Node *) n; } - | FOREIGN KEY '(' columnList ')' REFERENCES qualified_name - opt_column_list key_match key_actions ConstraintAttributeSpec + | FOREIGN KEY '(' columnList optionalPeriodName ')' REFERENCES qualified_name + opt_column_and_period_list key_match key_actions ConstraintAttributeSpec { Constraint *n = makeNode(Constraint); n->contype = CONSTR_FOREIGN; n->location = @1; - n->pktable = $7; + n->pktable = $8; n->fk_attrs = $4; - n->pk_attrs = $8; - n->fk_matchtype = $9; - n->fk_upd_action = ($10)->updateAction->action; - n->fk_del_action = ($10)->deleteAction->action; - n->fk_del_set_cols = ($10)->deleteAction->cols; - processCASbits($11, @11, "FOREIGN KEY", + if ($5) + { + n->fk_attrs = lappend(n->fk_attrs, $5); + n->fk_with_period = true; + } + n->pk_attrs = linitial($9); + if (lsecond($9)) + { + n->pk_attrs = lappend(n->pk_attrs, lsecond($9)); + n->pk_with_period = true; + } + n->fk_matchtype = $10; + n->fk_upd_action = ($11)->updateAction->action; + n->fk_del_action = ($11)->deleteAction->action; + n->fk_del_set_cols = ($11)->deleteAction->cols; + processCASbits($12, @12, "FOREIGN KEY", &n->deferrable, &n->initdeferred, - &n->skip_validation, NULL, + &n->is_enforced, &n->skip_validation, NULL, yyscanner); n->initially_valid = !n->skip_validation; $$ = (Node *) n; @@ -4345,8 +4464,9 @@ DomainConstraintElem: n->raw_expr = $3; n->cooked_expr = NULL; processCASbits($5, @5, "CHECK", - NULL, NULL, &n->skip_validation, + NULL, NULL, NULL, &n->skip_validation, &n->is_no_inherit, yyscanner); + n->is_enforced = true; n->initially_valid = !n->skip_validation; $$ = (Node *) n; } @@ -4357,10 +4477,10 @@ DomainConstraintElem: n->contype = CONSTR_NOTNULL; n->location = @1; n->keys = list_make1(makeString("value")); - /* no NOT VALID support yet */ + /* no NOT VALID, NO INHERIT support */ processCASbits($3, @3, "NOT NULL", NULL, NULL, NULL, - &n->is_no_inherit, yyscanner); + NULL, NULL, yyscanner); n->initially_valid = true; $$ = (Node *) n; } @@ -4370,6 +4490,11 @@ opt_no_inherit: NO INHERIT { $$ = true; } | /* EMPTY */ { $$ = false; } ; +opt_without_overlaps: + WITHOUT OVERLAPS { $$ = true; } + | /*EMPTY*/ { $$ = false; } + ; + opt_column_list: '(' columnList ')' { $$ = $2; } | /*EMPTY*/ { $$ = NIL; } @@ -4380,6 +4505,16 @@ columnList: | columnList ',' columnElem { $$ = lappend($1, $3); } ; +optionalPeriodName: + ',' PERIOD columnElem { $$ = $3; } + | /*EMPTY*/ { $$ = NULL; } + ; + +opt_column_and_period_list: + '(' columnList optionalPeriodName ')' { $$ = list_make2($2, $3); } + | /*EMPTY*/ { $$ = list_make2(NIL, NULL); } + ; + columnElem: ColId { $$ = (Node *) makeString($1); @@ -4559,7 +4694,7 @@ PartitionSpec: PARTITION BY ColId '(' part_params ')' { PartitionSpec *n = makeNode(PartitionSpec); - n->strategy = parsePartitionStrategy($3); + n->strategy = parsePartitionStrategy($3, @3, yyscanner); n->partParams = $5; n->location = @1; @@ -4969,6 +5104,10 @@ SeqOptElem: AS SimpleTypename { $$ = makeDefElem("increment", (Node *) $3, @1); } + | LOGGED + { + $$ = makeDefElem("logged", NULL, @1); + } | MAXVALUE NumericOnly { $$ = makeDefElem("maxvalue", (Node *) $2, @1); @@ -4991,7 +5130,6 @@ SeqOptElem: AS SimpleTypename } | SEQUENCE NAME_P any_name { - /* not documented, only used by pg_dump */ $$ = makeDefElem("sequence_name", (Node *) $3, @1); } | START opt_with NumericOnly @@ -5006,6 +5144,10 @@ SeqOptElem: AS SimpleTypename { $$ = makeDefElem("restart", (Node *) $3, @1); } + | UNLOGGED + { + $$ = makeDefElem("unlogged", NULL, @1); + } ; opt_by: BY @@ -5986,7 +6128,8 @@ CreateTrigStmt: if (n->replace) /* not supported, see CreateTrigger */ ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("CREATE OR REPLACE CONSTRAINT TRIGGER is not supported"))); + errmsg("CREATE OR REPLACE CONSTRAINT TRIGGER is not supported"), + parser_errposition(@1))); n->isconstraint = true; n->trigname = $5; n->relation = $9; @@ -6000,7 +6143,7 @@ CreateTrigStmt: n->transitionRels = NIL; processCASbits($11, @11, "TRIGGER", &n->deferrable, &n->initdeferred, NULL, - NULL, yyscanner); + NULL, NULL, yyscanner); n->constrrel = $10; $$ = (Node *) n; } @@ -6169,7 +6312,8 @@ ConstraintAttributeSpec: parser_errposition(@2))); /* generic message for other conflicts */ if ((newspec & (CAS_NOT_DEFERRABLE | CAS_DEFERRABLE)) == (CAS_NOT_DEFERRABLE | CAS_DEFERRABLE) || - (newspec & (CAS_INITIALLY_IMMEDIATE | CAS_INITIALLY_DEFERRED)) == (CAS_INITIALLY_IMMEDIATE | CAS_INITIALLY_DEFERRED)) + (newspec & (CAS_INITIALLY_IMMEDIATE | CAS_INITIALLY_DEFERRED)) == (CAS_INITIALLY_IMMEDIATE | CAS_INITIALLY_DEFERRED) || + (newspec & (CAS_NOT_ENFORCED | CAS_ENFORCED)) == (CAS_NOT_ENFORCED | CAS_ENFORCED)) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("conflicting constraint properties"), @@ -6185,6 +6329,8 @@ ConstraintAttributeElem: | INITIALLY DEFERRED { $$ = CAS_INITIALLY_DEFERRED; } | NOT VALID { $$ = CAS_NOT_VALID; } | NO INHERIT { $$ = CAS_NO_INHERIT; } + | NOT ENFORCED { $$ = CAS_NOT_ENFORCED; } + | ENFORCED { $$ = CAS_ENFORCED; } ; @@ -6271,7 +6417,8 @@ CreateAssertionStmt: { ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("CREATE ASSERTION is not yet implemented"))); + errmsg("CREATE ASSERTION is not yet implemented"), + parser_errposition(@1))); $$ = NULL; } @@ -6631,7 +6778,7 @@ opclass_item_list: ; opclass_item: - OPERATOR Iconst any_operator opclass_purpose opt_recheck + OPERATOR Iconst any_operator opclass_purpose { CreateOpClassItem *n = makeNode(CreateOpClassItem); ObjectWithArgs *owa = makeNode(ObjectWithArgs); @@ -6645,7 +6792,6 @@ opclass_item: $$ = (Node *) n; } | OPERATOR Iconst operator_with_argtypes opclass_purpose - opt_recheck { CreateOpClassItem *n = makeNode(CreateOpClassItem); @@ -6697,23 +6843,6 @@ opclass_purpose: FOR SEARCH { $$ = NIL; } | /*EMPTY*/ { $$ = NIL; } ; -opt_recheck: RECHECK - { - /* - * RECHECK no longer does anything in opclass definitions, - * but we still accept it to ease porting of old database - * dumps. - */ - ereport(NOTICE, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("RECHECK is no longer required"), - errhint("Update your data type."), - parser_errposition(@1))); - $$ = true; - } - | /*EMPTY*/ { $$ = false; } - ; - CreateOpFamilyStmt: CREATE OPERATOR FAMILY any_name USING name @@ -8133,6 +8262,7 @@ defacl_privilege_target: | SEQUENCES { $$ = OBJECT_SEQUENCE; } | TYPES_P { $$ = OBJECT_TYPE; } | SCHEMAS { $$ = OBJECT_SCHEMA; } + | LARGE_P OBJECTS_P { $$ = OBJECT_LARGEOBJECT; } ; @@ -8332,7 +8462,7 @@ CreateFunctionStmt: n->is_procedure = false; n->replace = $2; n->funcname = $4; - n->parameters = mergeTableFuncParameters($5, $9); + n->parameters = mergeTableFuncParameters($5, $9, yyscanner); n->returnType = TableFuncTypeName($9); n->returnType->location = @7; n->options = $11; @@ -8465,6 +8595,7 @@ func_arg: n->argType = $3; n->mode = $1; n->defexpr = NULL; + n->location = @1; $$ = n; } | param_name arg_class func_type @@ -8475,6 +8606,7 @@ func_arg: n->argType = $3; n->mode = $2; n->defexpr = NULL; + n->location = @1; $$ = n; } | param_name func_type @@ -8485,6 +8617,7 @@ func_arg: n->argType = $2; n->mode = FUNC_PARAM_DEFAULT; n->defexpr = NULL; + n->location = @1; $$ = n; } | arg_class func_type @@ -8495,6 +8628,7 @@ func_arg: n->argType = $2; n->mode = $1; n->defexpr = NULL; + n->location = @1; $$ = n; } | func_type @@ -8505,6 +8639,7 @@ func_arg: n->argType = $1; n->mode = FUNC_PARAM_DEFAULT; n->defexpr = NULL; + n->location = @1; $$ = n; } ; @@ -8841,6 +8976,7 @@ table_func_column: param_name func_type n->argType = $2; n->mode = FUNC_PARAM_TABLE; n->defexpr = NULL; + n->location = @1; $$ = n; } ; @@ -11965,7 +12101,7 @@ opt_name_list: ; vacuum_relation: - qualified_name opt_name_list + relation_expr opt_name_list { $$ = (Node *) makeVacuumRelation($1, InvalidOid, $2); } @@ -12188,7 +12324,7 @@ InsertStmt: { $5->relation = $4; $5->onConflictClause = $6; - $5->returningList = $7; + $5->returningClause = $7; $5->withClause = $1; $$ = (Node *) $5; } @@ -12335,8 +12471,45 @@ opt_conf_expr: ; returning_clause: - RETURNING target_list { $$ = $2; } - | /* EMPTY */ { $$ = NIL; } + RETURNING returning_with_clause target_list + { + ReturningClause *n = makeNode(ReturningClause); + + n->options = $2; + n->exprs = $3; + $$ = n; + } + | /* EMPTY */ + { + $$ = NULL; + } + ; + +returning_with_clause: + WITH '(' returning_options ')' { $$ = $3; } + | /* EMPTY */ { $$ = NIL; } + ; + +returning_options: + returning_option { $$ = list_make1($1); } + | returning_options ',' returning_option { $$ = lappend($1, $3); } + ; + +returning_option: + returning_option_kind AS ColId + { + ReturningOption *n = makeNode(ReturningOption); + + n->option = $1; + n->value = $3; + n->location = @1; + $$ = (Node *) n; + } + ; + +returning_option_kind: + OLD { $$ = RETURNING_OPTION_OLD; } + | NEW { $$ = RETURNING_OPTION_NEW; } ; @@ -12355,7 +12528,7 @@ DeleteStmt: opt_with_clause DELETE_P FROM relation_expr_opt_alias n->relation = $4; n->usingClause = $5; n->whereClause = $6; - n->returningList = $7; + n->returningClause = $7; n->withClause = $1; $$ = (Node *) n; } @@ -12429,7 +12602,7 @@ UpdateStmt: opt_with_clause UPDATE relation_expr_opt_alias n->targetList = $5; n->fromClause = $6; n->whereClause = $7; - n->returningList = $8; + n->returningClause = $8; n->withClause = $1; $$ = (Node *) n; } @@ -12441,7 +12614,7 @@ UpdateStmtShort: opt_with_clause UPDATE relation_expr_opt_alias n->targetList = NULL; n->fromClause = NULL; n->whereClause = NULL; - n->returningList = NULL; + n->returningClause = NULL; n->withClause = $1; $$ = (Node *)n; pg_yyget_extra(yyscanner)->parsetree = list_make1(makeRawStmt($$, 0)); @@ -12520,7 +12693,7 @@ MergeStmt: m->sourceRelation = $6; m->joinCondition = $8; m->mergeWhenClauses = $9; - m->returningList = $10; + m->returningClause = $10; $$ = (Node *) m; } @@ -13199,11 +13372,13 @@ select_limit: { $$ = $1; ($$)->limitOffset = $2; + ($$)->offsetLoc = @2; } | offset_clause limit_clause { $$ = $2; ($$)->limitOffset = $1; + ($$)->offsetLoc = @1; } | limit_clause { @@ -13216,6 +13391,9 @@ select_limit: n->limitOffset = $1; n->limitCount = NULL; n->limitOption = LIMIT_OPTION_COUNT; + n->offsetLoc = @1; + n->countLoc = -1; + n->optionLoc = -1; $$ = n; } ; @@ -13233,6 +13411,9 @@ limit_clause: n->limitOffset = NULL; n->limitCount = $2; n->limitOption = LIMIT_OPTION_COUNT; + n->offsetLoc = -1; + n->countLoc = @1; + n->optionLoc = -1; $$ = n; } | LIMIT select_limit_value ',' select_offset_value @@ -13258,6 +13439,9 @@ limit_clause: n->limitOffset = NULL; n->limitCount = $3; n->limitOption = LIMIT_OPTION_COUNT; + n->offsetLoc = -1; + n->countLoc = @1; + n->optionLoc = -1; $$ = n; } | FETCH first_or_next select_fetch_first_value row_or_rows WITH TIES @@ -13267,6 +13451,9 @@ limit_clause: n->limitOffset = NULL; n->limitCount = $3; n->limitOption = LIMIT_OPTION_WITH_TIES; + n->offsetLoc = -1; + n->countLoc = @1; + n->optionLoc = @5; $$ = n; } | FETCH first_or_next row_or_rows ONLY @@ -13276,6 +13463,9 @@ limit_clause: n->limitOffset = NULL; n->limitCount = makeIntConst(1, -1); n->limitOption = LIMIT_OPTION_COUNT; + n->offsetLoc = -1; + n->countLoc = @1; + n->optionLoc = -1; $$ = n; } | FETCH first_or_next row_or_rows WITH TIES @@ -13285,6 +13475,9 @@ limit_clause: n->limitOffset = NULL; n->limitCount = makeIntConst(1, -1); n->limitOption = LIMIT_OPTION_WITH_TIES; + n->offsetLoc = -1; + n->countLoc = @1; + n->optionLoc = @4; $$ = n; } ; @@ -14129,7 +14322,7 @@ xmltable_column_el: parser_errposition(defel->location))); fc->colexpr = defel->arg; } - else if (strcmp(defel->defname, "is_not_null") == 0) + else if (strcmp(defel->defname, "__pg__is_not_null") == 0) { if (nullability_seen) ereport(ERROR, @@ -14172,13 +14365,20 @@ xmltable_column_option_list: xmltable_column_option_el: IDENT b_expr - { $$ = makeDefElem($1, $2, @1); } + { + if (strcmp($1, "__pg__is_not_null") == 0) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("option name \"%s\" cannot be used in XMLTABLE", $1), + parser_errposition(@1))); + $$ = makeDefElem($1, $2, @1); + } | DEFAULT b_expr { $$ = makeDefElem("default", $2, @1); } | NOT NULL_P - { $$ = makeDefElem("is_not_null", (Node *) makeBoolean(true), @1); } + { $$ = makeDefElem("__pg__is_not_null", (Node *) makeBoolean(true), @1); } | NULL_P - { $$ = makeDefElem("is_not_null", (Node *) makeBoolean(false), @1); } + { $$ = makeDefElem("__pg__is_not_null", (Node *) makeBoolean(false), @1); } | PATH b_expr { $$ = makeDefElem("path", $2, @1); } ; @@ -15179,49 +15379,50 @@ a_expr: c_expr { $$ = $1; } (Node *) list_make2($5, $7), @2); } - | a_expr IN_P in_expr + | a_expr IN_P select_with_parens { - /* in_expr returns a SubLink or a list of a_exprs */ - if (IsA($3, SubLink)) - { - /* generate foo = ANY (subquery) */ - SubLink *n = (SubLink *) $3; + /* generate foo = ANY (subquery) */ + SubLink *n = makeNode(SubLink); - n->subLinkType = ANY_SUBLINK; - n->subLinkId = 0; - n->testexpr = $1; - n->operName = NIL; /* show it's IN not = ANY */ - n->location = @2; - $$ = (Node *) n; - } - else - { - /* generate scalar IN expression */ - $$ = (Node *) makeSimpleA_Expr(AEXPR_IN, "=", $1, $3, @2); - } + n->subselect = $3; + n->subLinkType = ANY_SUBLINK; + n->subLinkId = 0; + n->testexpr = $1; + n->operName = NIL; /* show it's IN not = ANY */ + n->location = @2; + $$ = (Node *) n; } - | a_expr NOT_LA IN_P in_expr %prec NOT_LA + | a_expr IN_P '(' expr_list ')' { - /* in_expr returns a SubLink or a list of a_exprs */ - if (IsA($4, SubLink)) - { - /* generate NOT (foo = ANY (subquery)) */ - /* Make an = ANY node */ - SubLink *n = (SubLink *) $4; - - n->subLinkType = ANY_SUBLINK; - n->subLinkId = 0; - n->testexpr = $1; - n->operName = NIL; /* show it's IN not = ANY */ - n->location = @2; - /* Stick a NOT on top; must have same parse location */ - $$ = makeNotExpr((Node *) n, @2); - } - else - { - /* generate scalar NOT IN expression */ - $$ = (Node *) makeSimpleA_Expr(AEXPR_IN, "<>", $1, $4, @2); - } + /* generate scalar IN expression */ + A_Expr *n = makeSimpleA_Expr(AEXPR_IN, "=", $1, (Node *) $4, @2); + + n->rexpr_list_start = @3; + n->rexpr_list_end = @5; + $$ = (Node *) n; + } + | a_expr NOT_LA IN_P select_with_parens %prec NOT_LA + { + /* generate NOT (foo = ANY (subquery)) */ + SubLink *n = makeNode(SubLink); + + n->subselect = $4; + n->subLinkType = ANY_SUBLINK; + n->subLinkId = 0; + n->testexpr = $1; + n->operName = NIL; /* show it's IN not = ANY */ + n->location = @2; + /* Stick a NOT on top; must have same parse location */ + $$ = makeNotExpr((Node *) n, @2); + } + | a_expr NOT_LA IN_P '(' expr_list ')' + { + /* generate scalar NOT IN expression */ + A_Expr *n = makeSimpleA_Expr(AEXPR_IN, "<>", $1, (Node *) $5, @2); + + n->rexpr_list_start = @4; + n->rexpr_list_end = @6; + $$ = (Node *) n; } | a_expr subquery_Op sub_type select_with_parens %prec Op { @@ -16656,15 +16857,15 @@ type_list: Typename { $$ = list_make1($1); } array_expr: '[' expr_list ']' { - $$ = makeAArrayExpr($2, @1); + $$ = makeAArrayExpr($2, @1, @3); } | '[' array_expr_list ']' { - $$ = makeAArrayExpr($2, @1); + $$ = makeAArrayExpr($2, @1, @3); } | '[' ']' { - $$ = makeAArrayExpr(NIL, @1); + $$ = makeAArrayExpr(NIL, @1, @2); } ; @@ -16786,17 +16987,6 @@ trim_list: a_expr FROM expr_list { $$ = lappend($3, $1); } | expr_list { $$ = $1; } ; -in_expr: select_with_parens - { - SubLink *n = makeNode(SubLink); - - n->subselect = $1; - /* other fields will be filled later */ - $$ = (Node *) n; - } - | '(' expr_list ')' { $$ = (Node *) $2; } - ; - /* * Define SQL-style CASE clause. * - Full specification @@ -16997,7 +17187,8 @@ json_format_clause: else ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("unrecognized JSON encoding: %s", $4))); + errmsg("unrecognized JSON encoding: %s", $4), + parser_errposition(@4))); $$ = (Node *) makeJsonFormat(JS_FORMAT_JSON, encoding, @1); } @@ -17499,7 +17690,8 @@ PLpgSQL_Expr: opt_distinct_clause opt_target_list $9->limitOption == LIMIT_OPTION_WITH_TIES) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("WITH TIES cannot be specified without ORDER BY clause"))); + errmsg("WITH TIES cannot be specified without ORDER BY clause"), + parser_errposition($9->optionLoc))); n->limitOption = $9->limitOption; } n->lockingClause = $10; @@ -17683,6 +17875,7 @@ unreserved_keyword: | ENABLE_P | ENCODING | ENCRYPTED + | ENFORCED | ENUM_P | ERROR_P | ESCAPE @@ -17778,6 +17971,7 @@ unreserved_keyword: | NOWAIT | NULLS_P | OBJECT_P + | OBJECTS_P | OF | OFF | OIDS @@ -17800,6 +17994,7 @@ unreserved_keyword: | PASSING | PASSWORD | PATH + | PERIOD | PLAN | PLANS | POLICY @@ -17819,7 +18014,6 @@ unreserved_keyword: | RANGE | READ | REASSIGN - | RECHECK | RECURSIVE | REF_P | REFERENCING @@ -17916,6 +18110,7 @@ unreserved_keyword: | VERSION_P | VIEW | VIEWS + | VIRTUAL | VOLATILE | WHITESPACE_P | WITHIN @@ -18260,6 +18455,7 @@ bare_label_keyword: | ENCODING | ENCRYPTED | END_P + | ENFORCED | ENUM_P | ERROR_P | ESCAPE @@ -18398,6 +18594,7 @@ bare_label_keyword: | NULLS_P | NUMERIC | OBJECT_P + | OBJECTS_P | OF | OFF | OIDS @@ -18424,6 +18621,7 @@ bare_label_keyword: | PASSING | PASSWORD | PATH + | PERIOD | PLACING | PLAN | PLANS @@ -18447,7 +18645,6 @@ bare_label_keyword: | READ | REAL | REASSIGN - | RECHECK | RECURSIVE | REF_P | REFERENCES @@ -18570,6 +18767,7 @@ bare_label_keyword: | VERSION_P | VIEW | VIEWS + | VIRTUAL | VOLATILE | WHEN | WHITESPACE_P @@ -18637,10 +18835,10 @@ makeColumnRef(char *colname, List *indirection, int location, core_yyscan_t yyscanner) { /* - * Generate a ColumnRef node, with an A_Indirection node added if there - * is any subscripting in the specified indirection list. However, - * any field selection at the start of the indirection list must be - * transposed into the "fields" part of the ColumnRef node. + * Generate a ColumnRef node, with an A_Indirection node added if there is + * any subscripting in the specified indirection list. However, any field + * selection at the start of the indirection list must be transposed into + * the "fields" part of the ColumnRef node. */ ColumnRef *c = makeNode(ColumnRef); int nfields = 0; @@ -18695,42 +18893,42 @@ makeFloatConst(char *str, int location) n->val.fval.fval = str; n->location = location; - return (Node *)n; + return (Node *) n; } static Node * makeBoolAConst(bool state, int location) { - A_Const *n = makeNode(A_Const); + A_Const *n = makeNode(A_Const); n->val.boolval.type = T_Boolean; n->val.boolval.boolval = state; n->location = location; - return (Node *) n; + return (Node *) n; } static Node * makeBitStringConst(char *str, int location) { - A_Const *n = makeNode(A_Const); + A_Const *n = makeNode(A_Const); n->val.bsval.type = T_BitString; n->val.bsval.bsval = str; n->location = location; - return (Node *)n; + return (Node *) n; } static Node * makeNullAConst(int location) { - A_Const *n = makeNode(A_Const); + A_Const *n = makeNode(A_Const); n->isnull = true; n->location = location; - return (Node *)n; + return (Node *) n; } static Node * @@ -18814,7 +19012,7 @@ check_func_name(List *names, core_yyscan_t yyscanner) static List * check_indirection(List *indirection, core_yyscan_t yyscanner) { - ListCell *l; + ListCell *l; foreach(l, indirection) { @@ -18869,7 +19067,7 @@ makeOrderedSetArgs(List *directargs, List *orderedargs, core_yyscan_t yyscanner) { FunctionParameter *lastd = (FunctionParameter *) llast(directargs); - Integer *ndirectargs; + Integer *ndirectargs; /* No restriction unless last direct arg is VARIADIC */ if (lastd->mode == FUNC_PARAM_VARIADIC) @@ -18877,15 +19075,15 @@ makeOrderedSetArgs(List *directargs, List *orderedargs, FunctionParameter *firsto = (FunctionParameter *) linitial(orderedargs); /* - * We ignore the names, though the aggr_arg production allows them; - * it doesn't allow default values, so those need not be checked. + * We ignore the names, though the aggr_arg production allows them; it + * doesn't allow default values, so those need not be checked. */ if (list_length(orderedargs) != 1 || firsto->mode != FUNC_PARAM_VARIADIC) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("an ordered-set aggregate with a VARIADIC direct argument must have one VARIADIC aggregated argument of the same data type"), - parser_errposition(exprLocation((Node *) firsto)))); + parser_errposition(firsto->location))); /* OK, drop the duplicate VARIADIC argument from the internal form */ orderedargs = NIL; @@ -18933,7 +19131,7 @@ insertSelectOptions(SelectStmt *stmt, ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("multiple OFFSET clauses not allowed"), - parser_errposition(exprLocation(limitClause->limitOffset)))); + parser_errposition(limitClause->offsetLoc))); stmt->limitOffset = limitClause->limitOffset; } if (limitClause && limitClause->limitCount) @@ -18942,19 +19140,18 @@ insertSelectOptions(SelectStmt *stmt, ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("multiple LIMIT clauses not allowed"), - parser_errposition(exprLocation(limitClause->limitCount)))); + parser_errposition(limitClause->countLoc))); stmt->limitCount = limitClause->limitCount; } if (limitClause) { - if (stmt->limitOption) - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("multiple limit options not allowed"))); + /* If there was a conflict, we must have detected it above */ + Assert(!stmt->limitOption); if (!stmt->sortClause && limitClause->limitOption == LIMIT_OPTION_WITH_TIES) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("WITH TIES cannot be specified without ORDER BY clause"))); + errmsg("WITH TIES cannot be specified without ORDER BY clause"), + parser_errposition(limitClause->optionLoc))); if (limitClause->limitOption == LIMIT_OPTION_WITH_TIES && stmt->lockingClause) { ListCell *lc; @@ -18967,7 +19164,8 @@ insertSelectOptions(SelectStmt *stmt, ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("%s and %s options cannot be used together", - "SKIP LOCKED", "WITH TIES"))); + "SKIP LOCKED", "WITH TIES"), + parser_errposition(limitClause->optionLoc))); } } stmt->limitOption = limitClause->limitOption; @@ -19013,7 +19211,7 @@ doNegate(Node *n, int location) { if (IsA(n, A_Const)) { - A_Const *con = (A_Const *) n; + A_Const *con = (A_Const *) n; /* report the constant's location as that of the '-' sign */ con->location = location; @@ -19041,7 +19239,7 @@ doNegateFloat(Float *v) if (*oldval == '+') oldval++; if (*oldval == '-') - v->fval = oldval+1; /* just strip the '-' */ + v->fval = oldval + 1; /* just strip the '-' */ else v->fval = psprintf("-%s", oldval); } @@ -19087,12 +19285,14 @@ makeNotExpr(Node *expr, int location) } static Node * -makeAArrayExpr(List *elements, int location) +makeAArrayExpr(List *elements, int location, int location_end) { A_ArrayExpr *n = makeNode(A_ArrayExpr); n->elements = elements; n->location = location; + n->list_start = location; + n->list_end = location_end; return (Node *) n; } @@ -19112,10 +19312,11 @@ static Node * makeXmlExpr(XmlExprOp op, char *name, List *named_args, List *args, int location) { - XmlExpr *x = makeNode(XmlExpr); + XmlExpr *x = makeNode(XmlExpr); x->op = op; x->name = name; + /* * named_args is a list of ResTarget; it'll be split apart into separate * expression and name lists in transformXmlExpr(). @@ -19125,7 +19326,7 @@ makeXmlExpr(XmlExprOp op, char *name, List *named_args, List *args, x->args = args; /* xmloption, if relevant, must be filled in by caller */ /* type and typmod will be filled in during parse analysis */ - x->type = InvalidOid; /* marks the node as not analyzed */ + x->type = InvalidOid; /* marks the node as not analyzed */ x->location = location; return (Node *) x; } @@ -19134,7 +19335,7 @@ makeXmlExpr(XmlExprOp op, char *name, List *named_args, List *args, * Merge the input and output parameters of a table function. */ static List * -mergeTableFuncParameters(List *func_args, List *columns) +mergeTableFuncParameters(List *func_args, List *columns, core_yyscan_t yyscanner) { ListCell *lc; @@ -19148,7 +19349,8 @@ mergeTableFuncParameters(List *func_args, List *columns) p->mode != FUNC_PARAM_VARIADIC) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("OUT and INOUT arguments aren't allowed in TABLE functions"))); + errmsg("OUT and INOUT arguments aren't allowed in TABLE functions"), + parser_errposition(p->location))); } return list_concat(func_args, columns); @@ -19249,7 +19451,7 @@ makeRangeVarFromQualifiedName(char *name, List *namelist, int location, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("improper qualified name (too many dotted names): %s", NameListToString(lcons(makeString(name), namelist))), - parser_errposition(location))); + parser_errposition(location))); break; } @@ -19300,8 +19502,8 @@ SplitColQualList(List *qualList, */ static void processCASbits(int cas_bits, int location, const char *constrType, - bool *deferrable, bool *initdeferred, bool *not_valid, - bool *no_inherit, core_yyscan_t yyscanner) + bool *deferrable, bool *initdeferred, bool *is_enforced, + bool *not_valid, bool *no_inherit, core_yyscan_t yyscanner) { /* defaults */ if (deferrable) @@ -19310,6 +19512,8 @@ processCASbits(int cas_bits, int location, const char *constrType, *initdeferred = false; if (not_valid) *not_valid = false; + if (is_enforced) + *is_enforced = true; if (cas_bits & (CAS_DEFERRABLE | CAS_INITIALLY_DEFERRED)) { @@ -19318,7 +19522,7 @@ processCASbits(int cas_bits, int location, const char *constrType, else ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - /* translator: %s is CHECK, UNIQUE, or similar */ + /* translator: %s is CHECK, UNIQUE, or similar */ errmsg("%s constraints cannot be marked DEFERRABLE", constrType), parser_errposition(location))); @@ -19331,7 +19535,7 @@ processCASbits(int cas_bits, int location, const char *constrType, else ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - /* translator: %s is CHECK, UNIQUE, or similar */ + /* translator: %s is CHECK, UNIQUE, or similar */ errmsg("%s constraints cannot be marked DEFERRABLE", constrType), parser_errposition(location))); @@ -19344,7 +19548,7 @@ processCASbits(int cas_bits, int location, const char *constrType, else ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - /* translator: %s is CHECK, UNIQUE, or similar */ + /* translator: %s is CHECK, UNIQUE, or similar */ errmsg("%s constraints cannot be marked NOT VALID", constrType), parser_errposition(location))); @@ -19357,11 +19561,46 @@ processCASbits(int cas_bits, int location, const char *constrType, else ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - /* translator: %s is CHECK, UNIQUE, or similar */ + /* translator: %s is CHECK, UNIQUE, or similar */ errmsg("%s constraints cannot be marked NO INHERIT", constrType), parser_errposition(location))); } + + if (cas_bits & CAS_NOT_ENFORCED) + { + if (is_enforced) + *is_enforced = false; + else + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + /* translator: %s is CHECK, UNIQUE, or similar */ + errmsg("%s constraints cannot be marked NOT ENFORCED", + constrType), + parser_errposition(location))); + + /* + * NB: The validated status is irrelevant when the constraint is set to + * NOT ENFORCED, but for consistency, it should be set accordingly. + * This ensures that if the constraint is later changed to ENFORCED, it + * will automatically be in the correct NOT VALIDATED state. + */ + if (not_valid) + *not_valid = true; + } + + if (cas_bits & CAS_ENFORCED) + { + if (is_enforced) + *is_enforced = true; + else + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + /* translator: %s is CHECK, UNIQUE, or similar */ + errmsg("%s constraints cannot be marked ENFORCED", + constrType), + parser_errposition(location))); + } } /* @@ -19369,7 +19608,7 @@ processCASbits(int cas_bits, int location, const char *constrType, * PartitionStrategy representation, or die trying. */ static PartitionStrategy -parsePartitionStrategy(char *strategy) +parsePartitionStrategy(char *strategy, int location, core_yyscan_t yyscanner) { if (pg_strcasecmp(strategy, "list") == 0) return PARTITION_STRATEGY_LIST; @@ -19380,9 +19619,9 @@ parsePartitionStrategy(char *strategy) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("unrecognized partitioning strategy \"%s\"", - strategy))); - return PARTITION_STRATEGY_LIST; /* keep compiler quiet */ + errmsg("unrecognized partitioning strategy \"%s\"", strategy), + parser_errposition(location))); + return PARTITION_STRATEGY_LIST; /* keep compiler quiet */ } @@ -19453,8 +19692,8 @@ preprocess_pubobj_list(List *pubobjspec_list, core_yyscan_t yyscanner) parser_errposition(pubobj->location))); /* - * We can distinguish between the different type of schema - * objects based on whether name and pubtable is set. + * We can distinguish between the different type of schema objects + * based on whether name and pubtable is set. */ if (pubobj->name) pubobj->pubobjtype = PUBLICATIONOBJ_TABLES_IN_SCHEMA; @@ -19509,11 +19748,13 @@ makeRecursiveViewSelect(char *relname, List *aliases, Node *query) w->ctes = list_make1(cte); w->location = -1; - /* create target list for the new SELECT from the alias list of the - * recursive view specification */ - foreach (lc, aliases) + /* + * create target list for the new SELECT from the alias list of the + * recursive view specification + */ + foreach(lc, aliases) { - ResTarget *rt = makeNode(ResTarget); + ResTarget *rt = makeNode(ResTarget); rt->name = NULL; rt->indirection = NIL; @@ -19523,8 +19764,10 @@ makeRecursiveViewSelect(char *relname, List *aliases, Node *query) tl = lappend(tl, rt); } - /* create new SELECT combining WITH clause, target list, and fake FROM - * clause */ + /* + * create new SELECT combining WITH clause, target list, and fake FROM + * clause + */ s->withClause = w; s->targetList = tl; s->fromClause = list_make1(makeRangeVar(NULL, relname, -1)); diff --git a/src/parser/gram_template.y b/src/parser/gram_template.y index fdb4e8106..4ade68365 100644 --- a/src/parser/gram_template.y +++ b/src/parser/gram_template.y @@ -6,8 +6,8 @@ * gram.y * POSTGRESQL BISON rules/actions * - * Portions Copyright (c) 2003-2024, PgPool Global Development Group - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2003-2025, PgPool Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -89,6 +89,8 @@ #define ATTRIBUTE_IDENTITY_ALWAYS 'a' #define ATTRIBUTE_IDENTITY_BY_DEFAULT 'd' +#define ATTRIBUTE_GENERATED_STORED 's' +#define ATTRIBUTE_GENERATED_VIRTUAL 'v' /* * Definition taken from * postgreSQL source code file: src/include/utils/xml.h @@ -102,40 +104,26 @@ typedef enum } XmlStandaloneType; /* - * Location tracking support --- simpler than bison's default, since we only - * want to track the start position not the end position of each nonterminal. + * Location tracking support. Unlike bison's default, we only want + * to track the start position not the end position of each nonterminal. + * Nonterminals that reduce to empty receive position "-1". Since a + * production's leading RHS nonterminal(s) may have reduced to empty, + * we have to scan to find the first one that's not -1. */ #define YYLLOC_DEFAULT(Current, Rhs, N) \ do { \ - if ((N) > 0) \ - (Current) = (Rhs)[1]; \ - else \ - (Current) = (-1); \ + (Current) = (-1); \ + for (int _i = 1; _i <= (N); _i++) \ + { \ + if ((Rhs)[_i] >= 0) \ + { \ + (Current) = (Rhs)[_i]; \ + break; \ + } \ + } \ } while (0) /* - * The above macro assigns -1 (unknown) as the parse location of any - * nonterminal that was reduced from an empty rule, or whose leftmost - * component was reduced from an empty rule. This is problematic - * for nonterminals defined like - * OptFooList: / * EMPTY * / { ... } | OptFooList Foo { ... } ; - * because we'll set -1 as the location during the first reduction and then - * copy it during each subsequent reduction, leaving us with -1 for the - * location even when the list is not empty. To fix that, do this in the - * action for the nonempty rule(s): - * if (@$ < 0) @$ = @2; - * (Although we have many nonterminals that follow this pattern, we only - * bother with fixing @$ like this when the nonterminal's parse location - * is actually referenced in some rule.) - * - * A cleaner answer would be to make YYLLOC_DEFAULT scan all the Rhs - * locations until it's found one that's not -1. Then we'd get a correct - * location for any nonterminal that isn't entirely empty. But this way - * would add overhead to every rule reduction, and so far there's not been - * a compelling reason to pay that overhead. - */ - -/* * Bison doesn't allocate anything that needs to live across parser calls, * so we can easily have it use palloc instead of malloc. This prevents * memory leaks if we error out during parsing. @@ -158,12 +146,15 @@ typedef struct ImportQual List *table_names; } ImportQual; -/* Private struct for the result of opt_select_limit production */ +/* Private struct for the result of select_limit & limit_clause productions */ typedef struct SelectLimit { Node *limitOffset; Node *limitCount; - LimitOption limitOption; + LimitOption limitOption; /* indicates presence of WITH TIES */ + ParseLoc offsetLoc; /* location of OFFSET token, if present */ + ParseLoc countLoc; /* location of LIMIT/FETCH token, if present */ + ParseLoc optionLoc; /* location of WITH TIES, if present */ } SelectLimit; /* Private struct for the result of group_clause production */ @@ -193,6 +184,8 @@ typedef struct KeyActions #define CAS_INITIALLY_DEFERRED 0x08 #define CAS_NOT_VALID 0x10 #define CAS_NO_INHERIT 0x20 +#define CAS_NOT_ENFORCED 0x40 +#define CAS_ENFORCED 0x80 #define parser_yyerror(msg) scanner_yyerror(msg, yyscanner) @@ -233,12 +226,12 @@ static void doNegateFloat(Float *v); static Node *makeAndExpr(Node *lexpr, Node *rexpr, int location); static Node *makeOrExpr(Node *lexpr, Node *rexpr, int location); static Node *makeNotExpr(Node *expr, int location); -static Node *makeAArrayExpr(List *elements, int location); +static Node *makeAArrayExpr(List *elements, int location, int end_location); static Node *makeSQLValueFunction(SQLValueFunctionOp op, int32 typmod, int location); static Node *makeXmlExpr(XmlExprOp op, char *name, List *named_args, List *args, int location); -static List *mergeTableFuncParameters(List *func_args, List *columns); +static List *mergeTableFuncParameters(List *func_args, List *columns, core_yyscan_t yyscanner); static TypeName *TableFuncTypeName(List *columns); static RangeVar *makeRangeVarFromAnyName(List *names, int position, core_yyscan_t yyscanner); static RangeVar *makeRangeVarFromQualifiedName(char *name, List *namelist, int location, @@ -247,9 +240,10 @@ static void SplitColQualList(List *qualList, List **constraintList, CollateClause **collClause, core_yyscan_t yyscanner); static void processCASbits(int cas_bits, int location, const char *constrType, - bool *deferrable, bool *initdeferred, bool *not_valid, - bool *no_inherit, core_yyscan_t yyscanner); -static PartitionStrategy parsePartitionStrategy(char *strategy); + bool *deferrable, bool *initdeferred, bool *is_enforced, + bool *not_valid, bool *no_inherit, core_yyscan_t yyscanner); +static PartitionStrategy parsePartitionStrategy(char *strategy, int location, + core_yyscan_t yyscanner); static void preprocess_pubobj_list(List *pubobjspec_list, core_yyscan_t yyscanner); static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); @@ -319,6 +313,8 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); MergeWhenClause *mergewhen; struct KeyActions *keyactions; struct KeyAction *keyaction; + ReturningClause *retclause; + ReturningOptionKind retoptionkind; } %type <node> stmt toplevel_stmt schema_stmt routine_body_stmt @@ -495,7 +491,8 @@ UpdateStmtShort opclass_purpose opt_opfamily transaction_mode_list_or_empty OptTableFuncElementList TableFuncElementList opt_type_modifiers prep_type_clause - execute_param_clause using_clause returning_clause + execute_param_clause using_clause + returning_with_clause returning_options opt_enum_val_list enum_val_list table_func_column_list create_generic_options alter_generic_options relation_expr_list dostmt_opt_list @@ -504,6 +501,9 @@ UpdateStmtShort vacuum_relation_list opt_vacuum_relation_list drop_option_list pub_obj_list +%type <retclause> returning_clause +%type <node> returning_option +%type <retoptionkind> returning_option_kind %type <node> opt_routine_body %type <groupclause> group_clause %type <list> group_by_list @@ -542,7 +542,7 @@ UpdateStmtShort %type <boolean> opt_instead %type <boolean> opt_unique opt_verbose opt_full -%type <boolean> opt_freeze opt_analyze opt_default opt_recheck +%type <boolean> opt_freeze opt_analyze opt_default %type <defelt> opt_binary copy_delimiter %type <boolean> copy_from opt_program @@ -572,14 +572,15 @@ UpdateStmtShort SetResetClause FunctionSetResetClause %type <node> TableElement TypedTableElement ConstraintElem DomainConstraintElem TableFuncElement -%type <node> columnDef columnOptions +%type <node> columnDef columnOptions optionalPeriodName %type <defelt> def_elem reloption_elem old_aggr_elem operator_def_elem %type <node> def_arg columnElem where_clause where_or_current_clause a_expr b_expr c_expr AexprConst indirection_el opt_slice_bound - columnref in_expr having_clause func_table xmltable array_expr + columnref having_clause func_table xmltable array_expr OptWhereClause operator_def_arg +%type <list> opt_column_and_period_list %type <list> rowsfrom_item rowsfrom_list opt_col_def_list -%type <boolean> opt_ordinality +%type <boolean> opt_ordinality opt_without_overlaps %type <list> ExclusionConstraintList ExclusionConstraintElem %type <list> func_arg_list func_arg_list_opt %type <node> func_arg_expr @@ -688,7 +689,7 @@ UpdateStmtShort %type <str> opt_existing_window_name %type <boolean> opt_if_not_exists %type <boolean> opt_unique_null_treatment -%type <ival> generated_when override_kind +%type <ival> generated_when override_kind opt_virtual_or_stored %type <partspec> PartitionSpec OptPartitionSpec %type <partelem> part_elem %type <list> part_params @@ -771,9 +772,9 @@ UpdateStmtShort DETACH DICTIONARY DISABLE_P DISCARD DISTINCT DO DOCUMENT_P DOMAIN_P DOUBLE_P DROP - EACH ELSE EMPTY_P ENABLE_P ENCODING ENCRYPTED END_P ENUM_P ERROR_P ESCAPE - EVENT EXCEPT EXCLUDE EXCLUDING EXCLUSIVE EXECUTE EXISTS EXPLAIN EXPRESSION - EXTENSION EXTERNAL EXTRACT + EACH ELSE EMPTY_P ENABLE_P ENCODING ENCRYPTED END_P ENFORCED ENUM_P ERROR_P + ESCAPE EVENT EXCEPT EXCLUDE EXCLUDING EXCLUSIVE EXECUTE EXISTS EXPLAIN + EXPRESSION EXTENSION EXTERNAL EXTRACT FALSE_P FAMILY FETCH FILTER FINALIZE FIRST_P FLOAT_P FOLLOWING FOR FORCE FOREIGN FORMAT FORWARD FREEZE FROM FULL FUNCTION FUNCTIONS @@ -804,18 +805,18 @@ UpdateStmtShort NOT NOTHING NOTIFY NOTNULL NOWAIT NULL_P NULLIF NULLS_P NUMERIC - OBJECT_P OF OFF OFFSET OIDS OLD OMIT ON ONLY OPERATOR OPTION OPTIONS OR + OBJECT_P OBJECTS_P OF OFF OFFSET OIDS OLD OMIT ON ONLY OPERATOR OPTION OPTIONS OR ORDER ORDINALITY OTHERS OUT_P OUTER_P OVER OVERLAPS OVERLAY OVERRIDING OWNED OWNER PARALLEL PARAMETER PARSER PARTIAL PARTITION PASSING PASSWORD PATH PGPOOL - PLACING PLAN PLANS POLICY + PERIOD PLACING PLAN PLANS POLICY POSITION PRECEDING PRECISION PRESERVE PREPARE PREPARED PRIMARY PRIOR PRIVILEGES PROCEDURAL PROCEDURE PROCEDURES PROGRAM PUBLICATION QUOTE QUOTES - RANGE READ REAL REASSIGN RECHECK RECURSIVE REF_P REFERENCES REFERENCING + RANGE READ REAL REASSIGN RECURSIVE REF_P REFERENCES REFERENCING REFRESH REINDEX RELATIVE_P RELEASE RENAME REPEATABLE REPLACE REPLICA RESET RESTART RESTRICT RETURN RETURNING RETURNS REVOKE RIGHT ROLE ROLLBACK ROLLUP ROUTINE ROUTINES ROW ROWS RULE @@ -836,7 +837,7 @@ UpdateStmtShort UNLISTEN UNLOGGED UNTIL UPDATE USER USING VACUUM VALID VALIDATE VALIDATOR VALUE_P VALUES VARCHAR VARIADIC VARYING - VERBOSE VERSION_P VIEW VIEWS VOLATILE + VERBOSE VERSION_P VIEW VIEWS VIRTUAL VOLATILE WHEN WHERE WHITESPACE_P WINDOW WITH WITHIN WITHOUT WORK WRAPPER WRITE @@ -977,7 +978,7 @@ parse_toplevel: | MODE_PLPGSQL_EXPR PLpgSQL_Expr { pg_yyget_extra(yyscanner)->parsetree = - list_make1(makeRawStmt($2, 0)); + list_make1(makeRawStmt($2, @2)); } | MODE_PLPGSQL_ASSIGN1 PLAssignStmt { @@ -985,7 +986,7 @@ parse_toplevel: n->nnames = 1; pg_yyget_extra(yyscanner)->parsetree = - list_make1(makeRawStmt((Node *) n, 0)); + list_make1(makeRawStmt((Node *) n, @2)); } | MODE_PLPGSQL_ASSIGN2 PLAssignStmt { @@ -993,7 +994,7 @@ parse_toplevel: n->nnames = 2; pg_yyget_extra(yyscanner)->parsetree = - list_make1(makeRawStmt((Node *) n, 0)); + list_make1(makeRawStmt((Node *) n, @2)); } | MODE_PLPGSQL_ASSIGN3 PLAssignStmt { @@ -1001,19 +1002,15 @@ parse_toplevel: n->nnames = 3; pg_yyget_extra(yyscanner)->parsetree = - list_make1(makeRawStmt((Node *) n, 0)); + list_make1(makeRawStmt((Node *) n, @2)); } ; /* * At top level, we wrap each stmt with a RawStmt node carrying start location - * and length of the stmt's text. Notice that the start loc/len are driven - * entirely from semicolon locations (@2). It would seem natural to use - * @1 or @3 to get the true start location of a stmt, but that doesn't work - * for statements that can start with empty nonterminals (opt_with_clause is - * the main offender here); as noted in the comments for YYLLOC_DEFAULT, - * we'd get -1 for the location in such cases. - * We also take care to discard empty statements entirely. + * and length of the stmt's text. + * We also take care to discard empty statements entirely (which among other + * things dodges the problem of assigning them a location). */ stmtmulti: stmtmulti ';' toplevel_stmt { @@ -1023,14 +1020,14 @@ stmtmulti: stmtmulti ';' toplevel_stmt updateRawStmtEnd(llast_node(RawStmt, $1), @2); } if ($3 != NULL) - $$ = lappend($1, makeRawStmt($3, @2 + 1)); + $$ = lappend($1, makeRawStmt($3, @3)); else $$ = $1; } | toplevel_stmt { if ($1 != NULL) - $$ = list_make1(makeRawStmt($1, 0)); + $$ = list_make1(makeRawStmt($1, @1)); else $$ = NIL; } @@ -1639,8 +1636,6 @@ CreateSchemaStmt: OptSchemaEltList: OptSchemaEltList schema_stmt { - if (@$ < 0) /* see comments for YYLLOC_DEFAULT */ - @$ = @2; $$ = lappend($1, $2); } | /* EMPTY */ @@ -1678,6 +1673,13 @@ VariableSetStmt: n->is_local = false; $$ = (Node *) n; } + | PGPOOL set_rest_more + { + VariableSetStmt *n = $2; + n->type = T_PgpoolQueryCacheStmt; /* Hack to keep changes minimum */ + n->is_local = false; + $$ = (Node *) n; + } | SET set_rest { VariableSetStmt *n = $2; @@ -1709,6 +1711,8 @@ set_rest: n->kind = VAR_SET_MULTI; n->name = "TRANSACTION"; n->args = $2; + n->jumble_args = true; + n->location = -1; $$ = n; } | SESSION CHARACTERISTICS AS TRANSACTION transaction_mode_list @@ -1718,6 +1722,8 @@ set_rest: n->kind = VAR_SET_MULTI; n->name = "SESSION CHARACTERISTICS"; n->args = $5; + n->jumble_args = true; + n->location = -1; $$ = n; } | set_rest_more @@ -1731,6 +1737,7 @@ generic_set: n->kind = VAR_SET_VALUE; n->name = $1; n->args = $3; + n->location = @3; $$ = n; } | var_name '=' var_list @@ -1740,6 +1747,7 @@ generic_set: n->kind = VAR_SET_VALUE; n->name = $1; n->args = $3; + n->location = @3; $$ = n; } | var_name TO DEFAULT @@ -1748,6 +1756,7 @@ generic_set: n->kind = VAR_SET_DEFAULT; n->name = $1; + n->location = -1; $$ = n; } | var_name '=' DEFAULT @@ -1756,6 +1765,7 @@ generic_set: n->kind = VAR_SET_DEFAULT; n->name = $1; + n->location = -1; $$ = n; } ; @@ -1768,6 +1778,7 @@ set_rest_more: /* Generic SET syntaxes: */ n->kind = VAR_SET_CURRENT; n->name = $1; + n->location = -1; $$ = n; } /* Special syntaxes mandated by SQL standard: */ @@ -1777,6 +1788,8 @@ set_rest_more: /* Generic SET syntaxes: */ n->kind = VAR_SET_VALUE; n->name = "timezone"; + n->location = -1; + n->jumble_args = true; if ($3 != NULL) n->args = list_make1($3); else @@ -1798,6 +1811,7 @@ set_rest_more: /* Generic SET syntaxes: */ n->kind = VAR_SET_VALUE; n->name = "search_path"; n->args = list_make1(makeStringConst($2, @2)); + n->location = @2; $$ = n; } | NAMES opt_encoding @@ -1806,6 +1820,7 @@ set_rest_more: /* Generic SET syntaxes: */ n->kind = VAR_SET_VALUE; n->name = "client_encoding"; + n->location = @2; if ($2 != NULL) n->args = list_make1(makeStringConst($2, @2)); else @@ -1819,6 +1834,7 @@ set_rest_more: /* Generic SET syntaxes: */ n->kind = VAR_SET_VALUE; n->name = "role"; n->args = list_make1(makeStringConst($2, @2)); + n->location = @2; $$ = n; } | SESSION AUTHORIZATION NonReservedWord_or_Sconst @@ -1828,6 +1844,7 @@ set_rest_more: /* Generic SET syntaxes: */ n->kind = VAR_SET_VALUE; n->name = "session_authorization"; n->args = list_make1(makeStringConst($3, @3)); + n->location = @3; $$ = n; } | SESSION AUTHORIZATION DEFAULT @@ -1836,6 +1853,7 @@ set_rest_more: /* Generic SET syntaxes: */ n->kind = VAR_SET_DEFAULT; n->name = "session_authorization"; + n->location = -1; $$ = n; } | XML_P OPTION document_or_content @@ -1845,6 +1863,8 @@ set_rest_more: /* Generic SET syntaxes: */ n->kind = VAR_SET_VALUE; n->name = "xmloption"; n->args = list_make1(makeStringConst($3 == XMLOPTION_DOCUMENT ? "DOCUMENT" : "CONTENT", @3)); + n->jumble_args = true; + n->location = -1; $$ = n; } /* Special syntaxes invented by PostgreSQL: */ @@ -1855,6 +1875,14 @@ set_rest_more: /* Generic SET syntaxes: */ n->kind = VAR_SET_MULTI; n->name = "TRANSACTION SNAPSHOT"; n->args = list_make1(makeStringConst($3, @3)); + n->location = @3; + $$ = n; + } + /* PGPOOL CACHE DELETE */ + | SET CACHE DELETE_P Sconst + { + VariableSetStmt *n = makeNode(VariableSetStmt); + n->name = $4; /* query to delete query cache */ $$ = n; } ; @@ -1968,6 +1996,7 @@ reset_rest: n->kind = VAR_RESET; n->name = "timezone"; + n->location = -1; $$ = n; } | TRANSACTION ISOLATION LEVEL @@ -1976,6 +2005,7 @@ reset_rest: n->kind = VAR_RESET; n->name = "transaction_isolation"; + n->location = -1; $$ = n; } | SESSION AUTHORIZATION @@ -1984,6 +2014,7 @@ reset_rest: n->kind = VAR_RESET; n->name = "session_authorization"; + n->location = -1; $$ = n; } ; @@ -1995,6 +2026,7 @@ generic_reset: n->kind = VAR_RESET; n->name = $1; + n->location = -1; $$ = n; } | ALL @@ -2002,6 +2034,7 @@ generic_reset: VariableSetStmt *n = makeNode(VariableSetStmt); n->kind = VAR_RESET_ALL; + n->location = -1; $$ = n; } ; @@ -2724,15 +2757,45 @@ alter_table_cmd: | ALTER CONSTRAINT name ConstraintAttributeSpec { AlterTableCmd *n = makeNode(AlterTableCmd); - Constraint *c = makeNode(Constraint); + ATAlterConstraint *c = makeNode(ATAlterConstraint); + n->subtype = AT_AlterConstraint; n->def = (Node *) c; - c->contype = CONSTR_FOREIGN; /* others not supported, yet */ c->conname = $3; - processCASbits($4, @4, "ALTER CONSTRAINT statement", + if ($4 & (CAS_NOT_ENFORCED | CAS_ENFORCED)) + c->alterEnforceability = true; + if ($4 & (CAS_DEFERRABLE | CAS_NOT_DEFERRABLE | + CAS_INITIALLY_DEFERRED | CAS_INITIALLY_IMMEDIATE)) + c->alterDeferrability = true; + if ($4 & CAS_NO_INHERIT) + c->alterInheritability = true; + /* handle unsupported case with specific error message */ + if ($4 & CAS_NOT_VALID) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("constraints cannot be altered to be NOT VALID"), + parser_errposition(@4))); + processCASbits($4, @4, "FOREIGN KEY", &c->deferrable, &c->initdeferred, - NULL, NULL, yyscanner); + &c->is_enforced, + NULL, + &c->noinherit, + yyscanner); + $$ = (Node *) n; + } + /* ALTER TABLE <name> ALTER CONSTRAINT INHERIT */ + | ALTER CONSTRAINT name INHERIT + { + AlterTableCmd *n = makeNode(AlterTableCmd); + ATAlterConstraint *c = makeNode(ATAlterConstraint); + + n->subtype = AT_AlterConstraint; + n->def = (Node *) c; + c->conname = $3; + c->alterInheritability = true; + c->noinherit = false; + $$ = (Node *) n; } /* ALTER TABLE <name> VALIDATE CONSTRAINT ... */ @@ -3223,11 +3286,13 @@ PartitionBoundSpec: if (n->modulus == -1) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("modulus for hash partition must be specified"))); + errmsg("modulus for hash partition must be specified"), + parser_errposition(@3))); if (n->remainder == -1) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("remainder for hash partition must be specified"))); + errmsg("remainder for hash partition must be specified"), + parser_errposition(@3))); n->location = @3; @@ -3979,12 +4044,16 @@ ColConstraint: * or be part of a_expr NOT LIKE or similar constructs). */ ColConstraintElem: - NOT NULL_P + NOT NULL_P opt_no_inherit { Constraint *n = makeNode(Constraint); n->contype = CONSTR_NOTNULL; n->location = @1; + n->is_no_inherit = $3; + n->is_enforced = true; + n->skip_validation = false; + n->initially_valid = true; $$ = (Node *) n; } | NULL_P @@ -4029,6 +4098,7 @@ ColConstraintElem: n->is_no_inherit = $5; n->raw_expr = $3; n->cooked_expr = NULL; + n->is_enforced = true; n->skip_validation = false; n->initially_valid = true; $$ = (Node *) n; @@ -4055,7 +4125,7 @@ ColConstraintElem: n->location = @1; $$ = (Node *) n; } - | GENERATED generated_when AS '(' a_expr ')' STORED + | GENERATED generated_when AS '(' a_expr ')' opt_virtual_or_stored { Constraint *n = makeNode(Constraint); @@ -4063,6 +4133,7 @@ ColConstraintElem: n->generated_when = $2; n->raw_expr = $5; n->cooked_expr = NULL; + n->generated_kind = $7; n->location = @1; /* @@ -4092,6 +4163,7 @@ ColConstraintElem: n->fk_upd_action = ($5)->updateAction->action; n->fk_del_action = ($5)->deleteAction->action; n->fk_del_set_cols = ($5)->deleteAction->cols; + n->is_enforced = true; n->skip_validation = false; n->initially_valid = true; $$ = (Node *) n; @@ -4109,6 +4181,12 @@ generated_when: | BY DEFAULT { $$ = ATTRIBUTE_IDENTITY_BY_DEFAULT; } ; +opt_virtual_or_stored: + STORED { $$ = ATTRIBUTE_GENERATED_STORED; } + | VIRTUAL { $$ = ATTRIBUTE_GENERATED_VIRTUAL; } + | /*EMPTY*/ { $$ = ATTRIBUTE_GENERATED_VIRTUAL; } + ; + /* * ConstraintAttr represents constraint attributes, which we parse as if * they were independent constraint clauses, in order to avoid shift/reduce @@ -4157,6 +4235,22 @@ ConstraintAttr: n->location = @1; $$ = (Node *) n; } + | ENFORCED + { + Constraint *n = makeNode(Constraint); + + n->contype = CONSTR_ATTR_ENFORCED; + n->location = @1; + $$ = (Node *) n; + } + | NOT ENFORCED + { + Constraint *n = makeNode(Constraint); + + n->contype = CONSTR_ATTR_NOT_ENFORCED; + n->location = @1; + $$ = (Node *) n; + } ; @@ -4218,12 +4312,25 @@ ConstraintElem: n->raw_expr = $3; n->cooked_expr = NULL; processCASbits($5, @5, "CHECK", - NULL, NULL, &n->skip_validation, + NULL, NULL, &n->is_enforced, &n->skip_validation, + &n->is_no_inherit, yyscanner); + n->initially_valid = !n->skip_validation; + $$ = (Node *) n; + } + | NOT NULL_P ColId ConstraintAttributeSpec + { + Constraint *n = makeNode(Constraint); + + n->contype = CONSTR_NOTNULL; + n->location = @1; + n->keys = list_make1(makeString($3)); + processCASbits($4, @4, "NOT NULL", + NULL, NULL, NULL, &n->skip_validation, &n->is_no_inherit, yyscanner); n->initially_valid = !n->skip_validation; $$ = (Node *) n; } - | UNIQUE opt_unique_null_treatment '(' columnList ')' opt_c_include opt_definition OptConsTableSpace + | UNIQUE opt_unique_null_treatment '(' columnList opt_without_overlaps ')' opt_c_include opt_definition OptConsTableSpace ConstraintAttributeSpec { Constraint *n = makeNode(Constraint); @@ -4232,13 +4339,14 @@ ConstraintElem: n->location = @1; n->nulls_not_distinct = !$2; n->keys = $4; - n->including = $6; - n->options = $7; + n->without_overlaps = $5; + n->including = $7; + n->options = $8; n->indexname = NULL; - n->indexspace = $8; - processCASbits($9, @9, "UNIQUE", + n->indexspace = $9; + processCASbits($10, @10, "UNIQUE", &n->deferrable, &n->initdeferred, NULL, - NULL, yyscanner); + NULL, NULL, yyscanner); $$ = (Node *) n; } | UNIQUE ExistingIndex ConstraintAttributeSpec @@ -4254,10 +4362,10 @@ ConstraintElem: n->indexspace = NULL; processCASbits($3, @3, "UNIQUE", &n->deferrable, &n->initdeferred, NULL, - NULL, yyscanner); + NULL, NULL, yyscanner); $$ = (Node *) n; } - | PRIMARY KEY '(' columnList ')' opt_c_include opt_definition OptConsTableSpace + | PRIMARY KEY '(' columnList opt_without_overlaps ')' opt_c_include opt_definition OptConsTableSpace ConstraintAttributeSpec { Constraint *n = makeNode(Constraint); @@ -4265,13 +4373,14 @@ ConstraintElem: n->contype = CONSTR_PRIMARY; n->location = @1; n->keys = $4; - n->including = $6; - n->options = $7; + n->without_overlaps = $5; + n->including = $7; + n->options = $8; n->indexname = NULL; - n->indexspace = $8; - processCASbits($9, @9, "PRIMARY KEY", + n->indexspace = $9; + processCASbits($10, @10, "PRIMARY KEY", &n->deferrable, &n->initdeferred, NULL, - NULL, yyscanner); + NULL, NULL, yyscanner); $$ = (Node *) n; } | PRIMARY KEY ExistingIndex ConstraintAttributeSpec @@ -4287,7 +4396,7 @@ ConstraintElem: n->indexspace = NULL; processCASbits($4, @4, "PRIMARY KEY", &n->deferrable, &n->initdeferred, NULL, - NULL, yyscanner); + NULL, NULL, yyscanner); $$ = (Node *) n; } | EXCLUDE access_method_clause '(' ExclusionConstraintList ')' @@ -4307,26 +4416,36 @@ ConstraintElem: n->where_clause = $9; processCASbits($10, @10, "EXCLUDE", &n->deferrable, &n->initdeferred, NULL, - NULL, yyscanner); + NULL, NULL, yyscanner); $$ = (Node *) n; } - | FOREIGN KEY '(' columnList ')' REFERENCES qualified_name - opt_column_list key_match key_actions ConstraintAttributeSpec + | FOREIGN KEY '(' columnList optionalPeriodName ')' REFERENCES qualified_name + opt_column_and_period_list key_match key_actions ConstraintAttributeSpec { Constraint *n = makeNode(Constraint); n->contype = CONSTR_FOREIGN; n->location = @1; - n->pktable = $7; + n->pktable = $8; n->fk_attrs = $4; - n->pk_attrs = $8; - n->fk_matchtype = $9; - n->fk_upd_action = ($10)->updateAction->action; - n->fk_del_action = ($10)->deleteAction->action; - n->fk_del_set_cols = ($10)->deleteAction->cols; - processCASbits($11, @11, "FOREIGN KEY", + if ($5) + { + n->fk_attrs = lappend(n->fk_attrs, $5); + n->fk_with_period = true; + } + n->pk_attrs = linitial($9); + if (lsecond($9)) + { + n->pk_attrs = lappend(n->pk_attrs, lsecond($9)); + n->pk_with_period = true; + } + n->fk_matchtype = $10; + n->fk_upd_action = ($11)->updateAction->action; + n->fk_del_action = ($11)->deleteAction->action; + n->fk_del_set_cols = ($11)->deleteAction->cols; + processCASbits($12, @12, "FOREIGN KEY", &n->deferrable, &n->initdeferred, - &n->skip_validation, NULL, + &n->is_enforced, &n->skip_validation, NULL, yyscanner); n->initially_valid = !n->skip_validation; $$ = (Node *) n; @@ -4366,8 +4485,9 @@ DomainConstraintElem: n->raw_expr = $3; n->cooked_expr = NULL; processCASbits($5, @5, "CHECK", - NULL, NULL, &n->skip_validation, + NULL, NULL, NULL, &n->skip_validation, &n->is_no_inherit, yyscanner); + n->is_enforced = true; n->initially_valid = !n->skip_validation; $$ = (Node *) n; } @@ -4378,10 +4498,10 @@ DomainConstraintElem: n->contype = CONSTR_NOTNULL; n->location = @1; n->keys = list_make1(makeString("value")); - /* no NOT VALID support yet */ + /* no NOT VALID, NO INHERIT support */ processCASbits($3, @3, "NOT NULL", NULL, NULL, NULL, - &n->is_no_inherit, yyscanner); + NULL, NULL, yyscanner); n->initially_valid = true; $$ = (Node *) n; } @@ -4391,6 +4511,11 @@ opt_no_inherit: NO INHERIT { $$ = true; } | /* EMPTY */ { $$ = false; } ; +opt_without_overlaps: + WITHOUT OVERLAPS { $$ = true; } + | /*EMPTY*/ { $$ = false; } + ; + opt_column_list: '(' columnList ')' { $$ = $2; } | /*EMPTY*/ { $$ = NIL; } @@ -4401,6 +4526,16 @@ columnList: | columnList ',' columnElem { $$ = lappend($1, $3); } ; +optionalPeriodName: + ',' PERIOD columnElem { $$ = $3; } + | /*EMPTY*/ { $$ = NULL; } + ; + +opt_column_and_period_list: + '(' columnList optionalPeriodName ')' { $$ = list_make2($2, $3); } + | /*EMPTY*/ { $$ = list_make2(NIL, NULL); } + ; + columnElem: ColId { $$ = (Node *) makeString($1); @@ -4580,7 +4715,7 @@ PartitionSpec: PARTITION BY ColId '(' part_params ')' { PartitionSpec *n = makeNode(PartitionSpec); - n->strategy = parsePartitionStrategy($3); + n->strategy = parsePartitionStrategy($3, @3, yyscanner); n->partParams = $5; n->location = @1; @@ -4990,6 +5125,10 @@ SeqOptElem: AS SimpleTypename { $$ = makeDefElem("increment", (Node *) $3, @1); } + | LOGGED + { + $$ = makeDefElem("logged", NULL, @1); + } | MAXVALUE NumericOnly { $$ = makeDefElem("maxvalue", (Node *) $2, @1); @@ -5012,7 +5151,6 @@ SeqOptElem: AS SimpleTypename } | SEQUENCE NAME_P any_name { - /* not documented, only used by pg_dump */ $$ = makeDefElem("sequence_name", (Node *) $3, @1); } | START opt_with NumericOnly @@ -5027,6 +5165,10 @@ SeqOptElem: AS SimpleTypename { $$ = makeDefElem("restart", (Node *) $3, @1); } + | UNLOGGED + { + $$ = makeDefElem("unlogged", NULL, @1); + } ; opt_by: BY @@ -6007,7 +6149,8 @@ CreateTrigStmt: if (n->replace) /* not supported, see CreateTrigger */ ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("CREATE OR REPLACE CONSTRAINT TRIGGER is not supported"))); + errmsg("CREATE OR REPLACE CONSTRAINT TRIGGER is not supported"), + parser_errposition(@1))); n->isconstraint = true; n->trigname = $5; n->relation = $9; @@ -6021,7 +6164,7 @@ CreateTrigStmt: n->transitionRels = NIL; processCASbits($11, @11, "TRIGGER", &n->deferrable, &n->initdeferred, NULL, - NULL, yyscanner); + NULL, NULL, yyscanner); n->constrrel = $10; $$ = (Node *) n; } @@ -6190,7 +6333,8 @@ ConstraintAttributeSpec: parser_errposition(@2))); /* generic message for other conflicts */ if ((newspec & (CAS_NOT_DEFERRABLE | CAS_DEFERRABLE)) == (CAS_NOT_DEFERRABLE | CAS_DEFERRABLE) || - (newspec & (CAS_INITIALLY_IMMEDIATE | CAS_INITIALLY_DEFERRED)) == (CAS_INITIALLY_IMMEDIATE | CAS_INITIALLY_DEFERRED)) + (newspec & (CAS_INITIALLY_IMMEDIATE | CAS_INITIALLY_DEFERRED)) == (CAS_INITIALLY_IMMEDIATE | CAS_INITIALLY_DEFERRED) || + (newspec & (CAS_NOT_ENFORCED | CAS_ENFORCED)) == (CAS_NOT_ENFORCED | CAS_ENFORCED)) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("conflicting constraint properties"), @@ -6206,6 +6350,8 @@ ConstraintAttributeElem: | INITIALLY DEFERRED { $$ = CAS_INITIALLY_DEFERRED; } | NOT VALID { $$ = CAS_NOT_VALID; } | NO INHERIT { $$ = CAS_NO_INHERIT; } + | NOT ENFORCED { $$ = CAS_NOT_ENFORCED; } + | ENFORCED { $$ = CAS_ENFORCED; } ; @@ -6292,7 +6438,8 @@ CreateAssertionStmt: { ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("CREATE ASSERTION is not yet implemented"))); + errmsg("CREATE ASSERTION is not yet implemented"), + parser_errposition(@1))); $$ = NULL; } @@ -6652,7 +6799,7 @@ opclass_item_list: ; opclass_item: - OPERATOR Iconst any_operator opclass_purpose opt_recheck + OPERATOR Iconst any_operator opclass_purpose { CreateOpClassItem *n = makeNode(CreateOpClassItem); ObjectWithArgs *owa = makeNode(ObjectWithArgs); @@ -6666,7 +6813,6 @@ opclass_item: $$ = (Node *) n; } | OPERATOR Iconst operator_with_argtypes opclass_purpose - opt_recheck { CreateOpClassItem *n = makeNode(CreateOpClassItem); @@ -6718,23 +6864,6 @@ opclass_purpose: FOR SEARCH { $$ = NIL; } | /*EMPTY*/ { $$ = NIL; } ; -opt_recheck: RECHECK - { - /* - * RECHECK no longer does anything in opclass definitions, - * but we still accept it to ease porting of old database - * dumps. - */ - ereport(NOTICE, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("RECHECK is no longer required"), - errhint("Update your data type."), - parser_errposition(@1))); - $$ = true; - } - | /*EMPTY*/ { $$ = false; } - ; - CreateOpFamilyStmt: CREATE OPERATOR FAMILY any_name USING name @@ -8154,6 +8283,7 @@ defacl_privilege_target: | SEQUENCES { $$ = OBJECT_SEQUENCE; } | TYPES_P { $$ = OBJECT_TYPE; } | SCHEMAS { $$ = OBJECT_SCHEMA; } + | LARGE_P OBJECTS_P { $$ = OBJECT_LARGEOBJECT; } ; @@ -8353,7 +8483,7 @@ CreateFunctionStmt: n->is_procedure = false; n->replace = $2; n->funcname = $4; - n->parameters = mergeTableFuncParameters($5, $9); + n->parameters = mergeTableFuncParameters($5, $9, yyscanner); n->returnType = TableFuncTypeName($9); n->returnType->location = @7; n->options = $11; @@ -8486,6 +8616,7 @@ func_arg: n->argType = $3; n->mode = $1; n->defexpr = NULL; + n->location = @1; $$ = n; } | param_name arg_class func_type @@ -8496,6 +8627,7 @@ func_arg: n->argType = $3; n->mode = $2; n->defexpr = NULL; + n->location = @1; $$ = n; } | param_name func_type @@ -8506,6 +8638,7 @@ func_arg: n->argType = $2; n->mode = FUNC_PARAM_DEFAULT; n->defexpr = NULL; + n->location = @1; $$ = n; } | arg_class func_type @@ -8516,6 +8649,7 @@ func_arg: n->argType = $2; n->mode = $1; n->defexpr = NULL; + n->location = @1; $$ = n; } | func_type @@ -8526,6 +8660,7 @@ func_arg: n->argType = $1; n->mode = FUNC_PARAM_DEFAULT; n->defexpr = NULL; + n->location = @1; $$ = n; } ; @@ -8862,6 +8997,7 @@ table_func_column: param_name func_type n->argType = $2; n->mode = FUNC_PARAM_TABLE; n->defexpr = NULL; + n->location = @1; $$ = n; } ; @@ -11986,7 +12122,7 @@ opt_name_list: ; vacuum_relation: - qualified_name opt_name_list + relation_expr opt_name_list { $$ = (Node *) makeVacuumRelation($1, InvalidOid, $2); } @@ -12209,7 +12345,7 @@ InsertStmt: { $5->relation = $4; $5->onConflictClause = $6; - $5->returningList = $7; + $5->returningClause = $7; $5->withClause = $1; $$ = (Node *) $5; } @@ -12358,8 +12494,45 @@ opt_conf_expr: ; returning_clause: - RETURNING target_list { $$ = $2; } - | /* EMPTY */ { $$ = NIL; } + RETURNING returning_with_clause target_list + { + ReturningClause *n = makeNode(ReturningClause); + + n->options = $2; + n->exprs = $3; + $$ = n; + } + | /* EMPTY */ + { + $$ = NULL; + } + ; + +returning_with_clause: + WITH '(' returning_options ')' { $$ = $3; } + | /* EMPTY */ { $$ = NIL; } + ; + +returning_options: + returning_option { $$ = list_make1($1); } + | returning_options ',' returning_option { $$ = lappend($1, $3); } + ; + +returning_option: + returning_option_kind AS ColId + { + ReturningOption *n = makeNode(ReturningOption); + + n->option = $1; + n->value = $3; + n->location = @1; + $$ = (Node *) n; + } + ; + +returning_option_kind: + OLD { $$ = RETURNING_OPTION_OLD; } + | NEW { $$ = RETURNING_OPTION_NEW; } ; @@ -12378,7 +12551,7 @@ DeleteStmt: opt_with_clause DELETE_P FROM relation_expr_opt_alias n->relation = $4; n->usingClause = $5; n->whereClause = $6; - n->returningList = $7; + n->returningClause = $7; n->withClause = $1; $$ = (Node *) n; } @@ -12452,7 +12625,7 @@ UpdateStmt: opt_with_clause UPDATE relation_expr_opt_alias n->targetList = $5; n->fromClause = $6; n->whereClause = $7; - n->returningList = $8; + n->returningClause = $8; n->withClause = $1; $$ = (Node *) n; } @@ -12465,7 +12638,7 @@ UpdateStmtShort: opt_with_clause UPDATE relation_expr_opt_alias n->targetList = NULL; n->fromClause = NULL; n->whereClause = NULL; - n->returningList = NULL; + n->returningClause = NULL; n->withClause = $1; $$ = (Node *)n; pg_yyget_extra(yyscanner)->parsetree = list_make1(makeRawStmt($$, 0)); @@ -12545,7 +12718,7 @@ MergeStmt: m->sourceRelation = $6; m->joinCondition = $8; m->mergeWhenClauses = $9; - m->returningList = $10; + m->returningClause = $10; $$ = (Node *) m; } @@ -13224,11 +13397,13 @@ select_limit: { $$ = $1; ($$)->limitOffset = $2; + ($$)->offsetLoc = @2; } | offset_clause limit_clause { $$ = $2; ($$)->limitOffset = $1; + ($$)->offsetLoc = @1; } | limit_clause { @@ -13241,6 +13416,9 @@ select_limit: n->limitOffset = $1; n->limitCount = NULL; n->limitOption = LIMIT_OPTION_COUNT; + n->offsetLoc = @1; + n->countLoc = -1; + n->optionLoc = -1; $$ = n; } ; @@ -13258,6 +13436,9 @@ limit_clause: n->limitOffset = NULL; n->limitCount = $2; n->limitOption = LIMIT_OPTION_COUNT; + n->offsetLoc = -1; + n->countLoc = @1; + n->optionLoc = -1; $$ = n; } | LIMIT select_limit_value ',' select_offset_value @@ -13283,6 +13464,9 @@ limit_clause: n->limitOffset = NULL; n->limitCount = $3; n->limitOption = LIMIT_OPTION_COUNT; + n->offsetLoc = -1; + n->countLoc = @1; + n->optionLoc = -1; $$ = n; } | FETCH first_or_next select_fetch_first_value row_or_rows WITH TIES @@ -13292,6 +13476,9 @@ limit_clause: n->limitOffset = NULL; n->limitCount = $3; n->limitOption = LIMIT_OPTION_WITH_TIES; + n->offsetLoc = -1; + n->countLoc = @1; + n->optionLoc = @5; $$ = n; } | FETCH first_or_next row_or_rows ONLY @@ -13301,6 +13488,9 @@ limit_clause: n->limitOffset = NULL; n->limitCount = makeIntConst(1, -1); n->limitOption = LIMIT_OPTION_COUNT; + n->offsetLoc = -1; + n->countLoc = @1; + n->optionLoc = -1; $$ = n; } | FETCH first_or_next row_or_rows WITH TIES @@ -13310,6 +13500,9 @@ limit_clause: n->limitOffset = NULL; n->limitCount = makeIntConst(1, -1); n->limitOption = LIMIT_OPTION_WITH_TIES; + n->offsetLoc = -1; + n->countLoc = @1; + n->optionLoc = @4; $$ = n; } ; @@ -14154,7 +14347,7 @@ xmltable_column_el: parser_errposition(defel->location))); fc->colexpr = defel->arg; } - else if (strcmp(defel->defname, "is_not_null") == 0) + else if (strcmp(defel->defname, "__pg__is_not_null") == 0) { if (nullability_seen) ereport(ERROR, @@ -14197,13 +14390,20 @@ xmltable_column_option_list: xmltable_column_option_el: IDENT b_expr - { $$ = makeDefElem($1, $2, @1); } + { + if (strcmp($1, "__pg__is_not_null") == 0) + ereport(ERROR, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("option name \"%s\" cannot be used in XMLTABLE", $1), + parser_errposition(@1))); + $$ = makeDefElem($1, $2, @1); + } | DEFAULT b_expr { $$ = makeDefElem("default", $2, @1); } | NOT NULL_P - { $$ = makeDefElem("is_not_null", (Node *) makeBoolean(true), @1); } + { $$ = makeDefElem("__pg__is_not_null", (Node *) makeBoolean(true), @1); } | NULL_P - { $$ = makeDefElem("is_not_null", (Node *) makeBoolean(false), @1); } + { $$ = makeDefElem("__pg__is_not_null", (Node *) makeBoolean(false), @1); } | PATH b_expr { $$ = makeDefElem("path", $2, @1); } ; @@ -15204,49 +15404,50 @@ a_expr: c_expr { $$ = $1; } (Node *) list_make2($5, $7), @2); } - | a_expr IN_P in_expr + | a_expr IN_P select_with_parens { - /* in_expr returns a SubLink or a list of a_exprs */ - if (IsA($3, SubLink)) - { - /* generate foo = ANY (subquery) */ - SubLink *n = (SubLink *) $3; + /* generate foo = ANY (subquery) */ + SubLink *n = makeNode(SubLink); - n->subLinkType = ANY_SUBLINK; - n->subLinkId = 0; - n->testexpr = $1; - n->operName = NIL; /* show it's IN not = ANY */ - n->location = @2; - $$ = (Node *) n; - } - else - { - /* generate scalar IN expression */ - $$ = (Node *) makeSimpleA_Expr(AEXPR_IN, "=", $1, $3, @2); - } + n->subselect = $3; + n->subLinkType = ANY_SUBLINK; + n->subLinkId = 0; + n->testexpr = $1; + n->operName = NIL; /* show it's IN not = ANY */ + n->location = @2; + $$ = (Node *) n; } - | a_expr NOT_LA IN_P in_expr %prec NOT_LA + | a_expr IN_P '(' expr_list ')' { - /* in_expr returns a SubLink or a list of a_exprs */ - if (IsA($4, SubLink)) - { - /* generate NOT (foo = ANY (subquery)) */ - /* Make an = ANY node */ - SubLink *n = (SubLink *) $4; - - n->subLinkType = ANY_SUBLINK; - n->subLinkId = 0; - n->testexpr = $1; - n->operName = NIL; /* show it's IN not = ANY */ - n->location = @2; - /* Stick a NOT on top; must have same parse location */ - $$ = makeNotExpr((Node *) n, @2); - } - else - { - /* generate scalar NOT IN expression */ - $$ = (Node *) makeSimpleA_Expr(AEXPR_IN, "<>", $1, $4, @2); - } + /* generate scalar IN expression */ + A_Expr *n = makeSimpleA_Expr(AEXPR_IN, "=", $1, (Node *) $4, @2); + + n->rexpr_list_start = @3; + n->rexpr_list_end = @5; + $$ = (Node *) n; + } + | a_expr NOT_LA IN_P select_with_parens %prec NOT_LA + { + /* generate NOT (foo = ANY (subquery)) */ + SubLink *n = makeNode(SubLink); + + n->subselect = $4; + n->subLinkType = ANY_SUBLINK; + n->subLinkId = 0; + n->testexpr = $1; + n->operName = NIL; /* show it's IN not = ANY */ + n->location = @2; + /* Stick a NOT on top; must have same parse location */ + $$ = makeNotExpr((Node *) n, @2); + } + | a_expr NOT_LA IN_P '(' expr_list ')' + { + /* generate scalar NOT IN expression */ + A_Expr *n = makeSimpleA_Expr(AEXPR_IN, "<>", $1, (Node *) $5, @2); + + n->rexpr_list_start = @4; + n->rexpr_list_end = @6; + $$ = (Node *) n; } | a_expr subquery_Op sub_type select_with_parens %prec Op { @@ -16681,15 +16882,15 @@ type_list: Typename { $$ = list_make1($1); } array_expr: '[' expr_list ']' { - $$ = makeAArrayExpr($2, @1); + $$ = makeAArrayExpr($2, @1, @3); } | '[' array_expr_list ']' { - $$ = makeAArrayExpr($2, @1); + $$ = makeAArrayExpr($2, @1, @3); } | '[' ']' { - $$ = makeAArrayExpr(NIL, @1); + $$ = makeAArrayExpr(NIL, @1, @2); } ; @@ -16811,17 +17012,6 @@ trim_list: a_expr FROM expr_list { $$ = lappend($3, $1); } | expr_list { $$ = $1; } ; -in_expr: select_with_parens - { - SubLink *n = makeNode(SubLink); - - n->subselect = $1; - /* other fields will be filled later */ - $$ = (Node *) n; - } - | '(' expr_list ')' { $$ = (Node *) $2; } - ; - /* * Define SQL-style CASE clause. * - Full specification @@ -17022,7 +17212,8 @@ json_format_clause: else ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("unrecognized JSON encoding: %s", $4))); + errmsg("unrecognized JSON encoding: %s", $4), + parser_errposition(@4))); $$ = (Node *) makeJsonFormat(JS_FORMAT_JSON, encoding, @1); } @@ -17524,7 +17715,8 @@ PLpgSQL_Expr: opt_distinct_clause opt_target_list $9->limitOption == LIMIT_OPTION_WITH_TIES) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("WITH TIES cannot be specified without ORDER BY clause"))); + errmsg("WITH TIES cannot be specified without ORDER BY clause"), + parser_errposition($9->optionLoc))); n->limitOption = $9->limitOption; } n->lockingClause = $10; @@ -17708,6 +17900,7 @@ unreserved_keyword: | ENABLE_P | ENCODING | ENCRYPTED + | ENFORCED | ENUM_P | ERROR_P | ESCAPE @@ -17803,6 +17996,7 @@ unreserved_keyword: | NOWAIT | NULLS_P | OBJECT_P + | OBJECTS_P | OF | OFF | OIDS @@ -17825,6 +18019,7 @@ unreserved_keyword: | PASSING | PASSWORD | PATH + | PERIOD | PLAN | PLANS | POLICY @@ -17844,7 +18039,6 @@ unreserved_keyword: | RANGE | READ | REASSIGN - | RECHECK | RECURSIVE | REF_P | REFERENCING @@ -17941,6 +18135,7 @@ unreserved_keyword: | VERSION_P | VIEW | VIEWS + | VIRTUAL | VOLATILE | WHITESPACE_P | WITHIN @@ -18285,6 +18480,7 @@ bare_label_keyword: | ENCODING | ENCRYPTED | END_P + | ENFORCED | ENUM_P | ERROR_P | ESCAPE @@ -18423,6 +18619,7 @@ bare_label_keyword: | NULLS_P | NUMERIC | OBJECT_P + | OBJECTS_P | OF | OFF | OIDS @@ -18449,6 +18646,7 @@ bare_label_keyword: | PASSING | PASSWORD | PATH + | PERIOD | PLACING | PLAN | PLANS @@ -18472,7 +18670,6 @@ bare_label_keyword: | READ | REAL | REASSIGN - | RECHECK | RECURSIVE | REF_P | REFERENCES @@ -18595,6 +18792,7 @@ bare_label_keyword: | VERSION_P | VIEW | VIEWS + | VIRTUAL | VOLATILE | WHEN | WHITESPACE_P @@ -18666,10 +18864,10 @@ makeColumnRef(char *colname, List *indirection, int location, core_yyscan_t yyscanner) { /* - * Generate a ColumnRef node, with an A_Indirection node added if there - * is any subscripting in the specified indirection list. However, - * any field selection at the start of the indirection list must be - * transposed into the "fields" part of the ColumnRef node. + * Generate a ColumnRef node, with an A_Indirection node added if there is + * any subscripting in the specified indirection list. However, any field + * selection at the start of the indirection list must be transposed into + * the "fields" part of the ColumnRef node. */ ColumnRef *c = makeNode(ColumnRef); int nfields = 0; @@ -18744,7 +18942,7 @@ makeIntConst(int val, int location) n->val.ival.ival = val; n->location = location; - return (Node *)n; + return (Node *) n; } #endif @@ -18757,42 +18955,42 @@ makeFloatConst(char *str, int location) n->val.fval.fval = str; n->location = location; - return (Node *)n; + return (Node *) n; } static Node * makeBoolAConst(bool state, int location) { - A_Const *n = makeNode(A_Const); + A_Const *n = makeNode(A_Const); n->val.boolval.type = T_Boolean; n->val.boolval.boolval = state; n->location = location; - return (Node *) n; + return (Node *) n; } static Node * makeBitStringConst(char *str, int location) { - A_Const *n = makeNode(A_Const); + A_Const *n = makeNode(A_Const); n->val.bsval.type = T_BitString; n->val.bsval.bsval = str; n->location = location; - return (Node *)n; + return (Node *) n; } static Node * makeNullAConst(int location) { - A_Const *n = makeNode(A_Const); + A_Const *n = makeNode(A_Const); n->isnull = true; n->location = location; - return (Node *)n; + return (Node *) n; } static Node * @@ -18876,7 +19074,7 @@ check_func_name(List *names, core_yyscan_t yyscanner) static List * check_indirection(List *indirection, core_yyscan_t yyscanner) { - ListCell *l; + ListCell *l; foreach(l, indirection) { @@ -18931,7 +19129,7 @@ makeOrderedSetArgs(List *directargs, List *orderedargs, core_yyscan_t yyscanner) { FunctionParameter *lastd = (FunctionParameter *) llast(directargs); - Integer *ndirectargs; + Integer *ndirectargs; /* No restriction unless last direct arg is VARIADIC */ if (lastd->mode == FUNC_PARAM_VARIADIC) @@ -18939,15 +19137,15 @@ makeOrderedSetArgs(List *directargs, List *orderedargs, FunctionParameter *firsto = (FunctionParameter *) linitial(orderedargs); /* - * We ignore the names, though the aggr_arg production allows them; - * it doesn't allow default values, so those need not be checked. + * We ignore the names, though the aggr_arg production allows them; it + * doesn't allow default values, so those need not be checked. */ if (list_length(orderedargs) != 1 || firsto->mode != FUNC_PARAM_VARIADIC) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("an ordered-set aggregate with a VARIADIC direct argument must have one VARIADIC aggregated argument of the same data type"), - parser_errposition(exprLocation((Node *) firsto)))); + parser_errposition(firsto->location))); /* OK, drop the duplicate VARIADIC argument from the internal form */ orderedargs = NIL; @@ -18995,7 +19193,7 @@ insertSelectOptions(SelectStmt *stmt, ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("multiple OFFSET clauses not allowed"), - parser_errposition(exprLocation(limitClause->limitOffset)))); + parser_errposition(limitClause->offsetLoc))); stmt->limitOffset = limitClause->limitOffset; } if (limitClause && limitClause->limitCount) @@ -19004,19 +19202,18 @@ insertSelectOptions(SelectStmt *stmt, ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("multiple LIMIT clauses not allowed"), - parser_errposition(exprLocation(limitClause->limitCount)))); + parser_errposition(limitClause->countLoc))); stmt->limitCount = limitClause->limitCount; } if (limitClause) { - if (stmt->limitOption) - ereport(ERROR, - (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("multiple limit options not allowed"))); + /* If there was a conflict, we must have detected it above */ + Assert(!stmt->limitOption); if (!stmt->sortClause && limitClause->limitOption == LIMIT_OPTION_WITH_TIES) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("WITH TIES cannot be specified without ORDER BY clause"))); + errmsg("WITH TIES cannot be specified without ORDER BY clause"), + parser_errposition(limitClause->optionLoc))); if (limitClause->limitOption == LIMIT_OPTION_WITH_TIES && stmt->lockingClause) { ListCell *lc; @@ -19029,7 +19226,8 @@ insertSelectOptions(SelectStmt *stmt, ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("%s and %s options cannot be used together", - "SKIP LOCKED", "WITH TIES"))); + "SKIP LOCKED", "WITH TIES"), + parser_errposition(limitClause->optionLoc))); } } stmt->limitOption = limitClause->limitOption; @@ -19098,7 +19296,7 @@ doNegate(Node *n, int location) { if (IsA(n, A_Const)) { - A_Const *con = (A_Const *) n; + A_Const *con = (A_Const *) n; /* report the constant's location as that of the '-' sign */ con->location = location; @@ -19126,7 +19324,7 @@ doNegateFloat(Float *v) if (*oldval == '+') oldval++; if (*oldval == '-') - v->fval = oldval+1; /* just strip the '-' */ + v->fval = oldval + 1; /* just strip the '-' */ else v->fval = psprintf("-%s", oldval); } @@ -19172,12 +19370,14 @@ makeNotExpr(Node *expr, int location) } static Node * -makeAArrayExpr(List *elements, int location) +makeAArrayExpr(List *elements, int location, int location_end) { A_ArrayExpr *n = makeNode(A_ArrayExpr); n->elements = elements; n->location = location; + n->list_start = location; + n->list_end = location_end; return (Node *) n; } @@ -19197,10 +19397,11 @@ static Node * makeXmlExpr(XmlExprOp op, char *name, List *named_args, List *args, int location) { - XmlExpr *x = makeNode(XmlExpr); + XmlExpr *x = makeNode(XmlExpr); x->op = op; x->name = name; + /* * named_args is a list of ResTarget; it'll be split apart into separate * expression and name lists in transformXmlExpr(). @@ -19210,7 +19411,7 @@ makeXmlExpr(XmlExprOp op, char *name, List *named_args, List *args, x->args = args; /* xmloption, if relevant, must be filled in by caller */ /* type and typmod will be filled in during parse analysis */ - x->type = InvalidOid; /* marks the node as not analyzed */ + x->type = InvalidOid; /* marks the node as not analyzed */ x->location = location; return (Node *) x; } @@ -19219,7 +19420,7 @@ makeXmlExpr(XmlExprOp op, char *name, List *named_args, List *args, * Merge the input and output parameters of a table function. */ static List * -mergeTableFuncParameters(List *func_args, List *columns) +mergeTableFuncParameters(List *func_args, List *columns, core_yyscan_t yyscanner) { ListCell *lc; @@ -19233,7 +19434,8 @@ mergeTableFuncParameters(List *func_args, List *columns) p->mode != FUNC_PARAM_VARIADIC) ereport(ERROR, (errcode(ERRCODE_SYNTAX_ERROR), - errmsg("OUT and INOUT arguments aren't allowed in TABLE functions"))); + errmsg("OUT and INOUT arguments aren't allowed in TABLE functions"), + parser_errposition(p->location))); } return list_concat(func_args, columns); @@ -19334,7 +19536,7 @@ makeRangeVarFromQualifiedName(char *name, List *namelist, int location, (errcode(ERRCODE_SYNTAX_ERROR), errmsg("improper qualified name (too many dotted names): %s", NameListToString(lcons(makeString(name), namelist))), - parser_errposition(location))); + parser_errposition(location))); break; } @@ -19385,8 +19587,8 @@ SplitColQualList(List *qualList, */ static void processCASbits(int cas_bits, int location, const char *constrType, - bool *deferrable, bool *initdeferred, bool *not_valid, - bool *no_inherit, core_yyscan_t yyscanner) + bool *deferrable, bool *initdeferred, bool *is_enforced, + bool *not_valid, bool *no_inherit, core_yyscan_t yyscanner) { /* defaults */ if (deferrable) @@ -19395,6 +19597,8 @@ processCASbits(int cas_bits, int location, const char *constrType, *initdeferred = false; if (not_valid) *not_valid = false; + if (is_enforced) + *is_enforced = true; if (cas_bits & (CAS_DEFERRABLE | CAS_INITIALLY_DEFERRED)) { @@ -19403,7 +19607,7 @@ processCASbits(int cas_bits, int location, const char *constrType, else ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - /* translator: %s is CHECK, UNIQUE, or similar */ + /* translator: %s is CHECK, UNIQUE, or similar */ errmsg("%s constraints cannot be marked DEFERRABLE", constrType), parser_errposition(location))); @@ -19416,7 +19620,7 @@ processCASbits(int cas_bits, int location, const char *constrType, else ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - /* translator: %s is CHECK, UNIQUE, or similar */ + /* translator: %s is CHECK, UNIQUE, or similar */ errmsg("%s constraints cannot be marked DEFERRABLE", constrType), parser_errposition(location))); @@ -19429,7 +19633,7 @@ processCASbits(int cas_bits, int location, const char *constrType, else ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - /* translator: %s is CHECK, UNIQUE, or similar */ + /* translator: %s is CHECK, UNIQUE, or similar */ errmsg("%s constraints cannot be marked NOT VALID", constrType), parser_errposition(location))); @@ -19442,11 +19646,46 @@ processCASbits(int cas_bits, int location, const char *constrType, else ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - /* translator: %s is CHECK, UNIQUE, or similar */ + /* translator: %s is CHECK, UNIQUE, or similar */ errmsg("%s constraints cannot be marked NO INHERIT", constrType), parser_errposition(location))); } + + if (cas_bits & CAS_NOT_ENFORCED) + { + if (is_enforced) + *is_enforced = false; + else + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + /* translator: %s is CHECK, UNIQUE, or similar */ + errmsg("%s constraints cannot be marked NOT ENFORCED", + constrType), + parser_errposition(location))); + + /* + * NB: The validated status is irrelevant when the constraint is set to + * NOT ENFORCED, but for consistency, it should be set accordingly. + * This ensures that if the constraint is later changed to ENFORCED, it + * will automatically be in the correct NOT VALIDATED state. + */ + if (not_valid) + *not_valid = true; + } + + if (cas_bits & CAS_ENFORCED) + { + if (is_enforced) + *is_enforced = true; + else + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + /* translator: %s is CHECK, UNIQUE, or similar */ + errmsg("%s constraints cannot be marked ENFORCED", + constrType), + parser_errposition(location))); + } } /* @@ -19454,7 +19693,7 @@ processCASbits(int cas_bits, int location, const char *constrType, * PartitionStrategy representation, or die trying. */ static PartitionStrategy -parsePartitionStrategy(char *strategy) +parsePartitionStrategy(char *strategy, int location, core_yyscan_t yyscanner) { if (pg_strcasecmp(strategy, "list") == 0) return PARTITION_STRATEGY_LIST; @@ -19465,9 +19704,9 @@ parsePartitionStrategy(char *strategy) ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("unrecognized partitioning strategy \"%s\"", - strategy))); - return PARTITION_STRATEGY_LIST; /* keep compiler quiet */ + errmsg("unrecognized partitioning strategy \"%s\"", strategy), + parser_errposition(location))); + return PARTITION_STRATEGY_LIST; /* keep compiler quiet */ } @@ -19538,8 +19777,8 @@ preprocess_pubobj_list(List *pubobjspec_list, core_yyscan_t yyscanner) parser_errposition(pubobj->location))); /* - * We can distinguish between the different type of schema - * objects based on whether name and pubtable is set. + * We can distinguish between the different type of schema objects + * based on whether name and pubtable is set. */ if (pubobj->name) pubobj->pubobjtype = PUBLICATIONOBJ_TABLES_IN_SCHEMA; @@ -19594,11 +19833,13 @@ makeRecursiveViewSelect(char *relname, List *aliases, Node *query) w->ctes = list_make1(cte); w->location = -1; - /* create target list for the new SELECT from the alias list of the - * recursive view specification */ - foreach (lc, aliases) + /* + * create target list for the new SELECT from the alias list of the + * recursive view specification + */ + foreach(lc, aliases) { - ResTarget *rt = makeNode(ResTarget); + ResTarget *rt = makeNode(ResTarget); rt->name = NULL; rt->indirection = NIL; @@ -19608,8 +19849,10 @@ makeRecursiveViewSelect(char *relname, List *aliases, Node *query) tl = lappend(tl, rt); } - /* create new SELECT combining WITH clause, target list, and fake FROM - * clause */ + /* + * create new SELECT combining WITH clause, target list, and fake FROM + * clause + */ s->withClause = w; s->targetList = tl; s->fromClause = list_make1(makeRangeVar(NULL, relname, -1)); diff --git a/src/parser/keywords.c b/src/parser/keywords.c index 83feb9f47..835ddfeb5 100644 --- a/src/parser/keywords.c +++ b/src/parser/keywords.c @@ -4,8 +4,8 @@ * PostgreSQL's list of SQL keywords * * - * Portions Copyright (c) 2003-2024, PgPool Global Development Group - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2003-2025, PgPool Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/parser/kwlookup.c b/src/parser/kwlookup.c index d4364dc27..ff2498cf8 100644 --- a/src/parser/kwlookup.c +++ b/src/parser/kwlookup.c @@ -4,8 +4,8 @@ * Key word lookup for PostgreSQL * * - * Portions Copyright (c) 2003-2024, PgPool Global Development Group - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2003-2025, PgPool Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/parser/list.c b/src/parser/list.c index 909517632..17f394fb0 100644 --- a/src/parser/list.c +++ b/src/parser/list.c @@ -5,8 +5,8 @@ * * See comments in pg_list.h * - * Portions Copyright (c) 2003-2024, PgPool Global Development Group - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2003-2025, PgPool Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/parser/makefuncs.c b/src/parser/makefuncs.c index 3777c66af..be807d982 100644 --- a/src/parser/makefuncs.c +++ b/src/parser/makefuncs.c @@ -4,8 +4,8 @@ * creator functions for various nodes. The functions here are for the * most frequently created nodes. * - * Portions Copyright (c) 2003-2024, PgPool Global Development Group - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2003-2025, PgPool Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -54,7 +54,7 @@ makeSimpleA_Expr(A_Expr_Kind kind, char *name, A_Expr *a = makeNode(A_Expr); a->kind = kind; - a->name = list_make1(makeString((char *) name)); + a->name = list_make1(makeString(name)); a->lexpr = lexpr; a->rexpr = rexpr; a->location = location; @@ -83,12 +83,14 @@ makeVar(int varno, var->varlevelsup = varlevelsup; /* - * Only a few callers need to make Var nodes with non-null varnullingrels, - * or with varnosyn/varattnosyn different from varno/varattno. We don't - * provide separate arguments for them, but just initialize them to NULL - * and the given varno/varattno. This reduces code clutter and chance of - * error for most callers. + * Only a few callers need to make Var nodes with varreturningtype + * different from VAR_RETURNING_DEFAULT, non-null varnullingrels, or with + * varnosyn/varattnosyn different from varno/varattno. We don't provide + * separate arguments for them, but just initialize them to sensible + * default values. This reduces code clutter and chance of error for most + * callers. */ + var->varreturningtype = VAR_RETURNING_DEFAULT; var->varnullingrels = NULL; var->varnosyn = (Index) varno; var->varattnosyn = varattno; @@ -163,6 +165,53 @@ makeWholeRowVar(RangeTblEntry *rte, varlevelsup); break; + case RTE_SUBQUERY: + + /* + * For a standard subquery, the Var should be of RECORD type. + * However, if we're looking at a subquery that was expanded from + * a view or SRF (only possible during planning), we must use the + * appropriate rowtype, so that the resulting Var has the same + * type that we would have produced from the original RTE. + */ + if (OidIsValid(rte->relid)) + { + /* Subquery was expanded from a view */ + toid = get_rel_type_id(rte->relid); + if (!OidIsValid(toid)) + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("relation \"%s\" does not have a composite type", + get_rel_name(rte->relid)))); + } + else if (rte->functions) + { + /* + * Subquery was expanded from a set-returning function. That + * would not have happened if there's more than one function + * or ordinality was requested. We also needn't worry about + * the allowScalar case, since the planner doesn't use that. + * Otherwise this must match the RTE_FUNCTION code below. + */ + Assert(!allowScalar); + fexpr = ((RangeTblFunction *) linitial(rte->functions))->funcexpr; + toid = exprType(fexpr); + if (!type_is_rowtype(toid)) + toid = RECORDOID; + } + else + { + /* Normal subquery-in-FROM */ + toid = RECORDOID; + } + result = makeVar(varno, + InvalidAttrNumber, + toid, + -1, + InvalidOid, + varlevelsup); + break; + case RTE_FUNCTION: /* @@ -219,8 +268,8 @@ makeWholeRowVar(RangeTblEntry *rte, default: /* - * RTE is a join, subselect, tablefunc, or VALUES. We represent - * this as a whole-row Var of RECORD type. (Note that in most + * RTE is a join, tablefunc, VALUES, CTE, etc. We represent these + * cases as a whole-row Var of RECORD type. (Note that in most * cases the Var will be expanded to a RowExpr during planning, * but that is not our concern here.) */ @@ -438,6 +487,30 @@ makeRangeVar(char *schemaname, char *relname, int location) } /* + * makeNotNullConstraint - + * creates a Constraint node for NOT NULL constraints + */ +Constraint * +makeNotNullConstraint(String *colname) +{ + Constraint *notnull; + + notnull = makeNode(Constraint); + notnull->contype = CONSTR_NOTNULL; + notnull->conname = NULL; + notnull->is_no_inherit = false; + notnull->deferrable = false; + notnull->initdeferred = false; + notnull->location = -1; + notnull->keys = list_make1(colname); + notnull->is_enforced = true; + notnull->skip_validation = false; + notnull->initially_valid = true; + + return notnull; +} + +/* * makeTypeName - * build a TypeName node for an unqualified name. * diff --git a/src/parser/outfuncs.c b/src/parser/outfuncs.c index f98af2b6e..529ac347c 100644 --- a/src/parser/outfuncs.c +++ b/src/parser/outfuncs.c @@ -3,8 +3,8 @@ * outfuncs.c * Output functions for Postgres tree nodes. * - * Portions Copyright (c) 2003-2024, PgPool Global Development Group - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2003-2025, PgPool Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * @@ -72,6 +72,7 @@ static void _outCoerceToDomainValue(StringInfo str, CoerceToDomainValue *node); static void _outSetToDefault(StringInfo str, SetToDefault *node); static void _outCurrentOfExpr(StringInfo str, CurrentOfExpr *node); static void _outInferenceElem(StringInfo str, InferenceElem *node); +static void _outReturningExpr(StringInfo str, ReturningExpr *node); static void _outTargetEntry(StringInfo str, TargetEntry *node); static void _outRangeTblRef(StringInfo str, RangeTblRef *node); static void _outJoinExpr(StringInfo str, JoinExpr *node); @@ -100,6 +101,8 @@ static void _outCTECycleClause(StringInfo str, CTECycleClause *node); static void _outCommonTableExpr(StringInfo str, CommonTableExpr *node); static void _outMergeWhenClauses(StringInfo str, List *node); static void _outMergeAction(StringInfo str, MergeAction *node); +static void _outReturningOption(StringInfo str, List *node); +static void _outReturningClause(StringInfo str, ReturningClause *node); static void _outSetOperationStmt(StringInfo str, SetOperationStmt *node); static void _outTableSampleClause(StringInfo str, TableSampleClause *node); static void _outA_Expr(StringInfo str, A_Expr *node); @@ -185,6 +188,7 @@ static void _outFuncName(StringInfo str, List *func_name); static void _outSetRest(StringInfo str, VariableSetStmt *node); static void _outSetTransactionModeList(StringInfo str, List *list); static void _outAlterTableCmd(StringInfo str, AlterTableCmd *node); +static void _outATAlterConstraint(StringInfo str, ATAlterConstraint *node); static void _outOptSeqList(StringInfo str, List *options); static void _outObjectWithArgs(StringInfo str, ObjectWithArgs *node); static void _outFunctionParameter(StringInfo str, FunctionParameter *node); @@ -811,6 +815,12 @@ _outInferenceElem(StringInfo str, InferenceElem *node) } static void +_outReturningExpr(StringInfo str, ReturningExpr *node) +{ + +} + +static void _outTargetEntry(StringInfo str, TargetEntry *node) { @@ -924,9 +934,17 @@ static void _outCreateStmt(StringInfo str, CreateStmt *node) { appendStringInfoString(str, "CREATE "); + if (node->relation->relpersistence == RELPERSISTENCE_TEMP) appendStringInfoString(str, "TEMP "); + else if (node->relation->relpersistence == RELPERSISTENCE_UNLOGGED) + appendStringInfoString(str, "UNLOGGED "); + appendStringInfoString(str, "TABLE "); + + if (node->if_not_exists) + appendStringInfoString(str, "IF NOT EXISTS "); + _outNode(str, node->relation); appendStringInfoString(str, " ("); _outNode(str, node->tableElts); @@ -939,6 +957,12 @@ _outCreateStmt(StringInfo str, CreateStmt *node) appendStringInfoString(str, ")"); } + if (node->accessMethod) + { + appendStringInfoString(str, " USING "); + appendStringInfoString(str, node->accessMethod); + } + if (node->options) _outWithDefinition(str, node->options); @@ -972,9 +996,17 @@ static void _outCreateTableAsStmt(StringInfo str, CreateTableAsStmt *node) { appendStringInfoString(str, "CREATE "); + if (node->into->rel->relpersistence == RELPERSISTENCE_TEMP) appendStringInfoString(str, "TEMP "); + else if (node->into->rel->relpersistence == RELPERSISTENCE_UNLOGGED) + appendStringInfoString(str, "UNLOGGED "); + appendStringInfoString(str, "TABLE "); + + if (node->if_not_exists) + appendStringInfoString(str, "IF NOT EXISTS "); + _outNode(str, node->into->rel); if (node->into->colNames) @@ -984,6 +1016,12 @@ _outCreateTableAsStmt(StringInfo str, CreateTableAsStmt *node) appendStringInfoString(str, ") "); } + if (node->into->accessMethod) + { + appendStringInfoString(str, " USING "); + appendStringInfoString(str, node->into->accessMethod); + } + if (node->into->options) _outWithDefinition(str, node->into->options); @@ -1017,6 +1055,14 @@ _outCreateTableAsStmt(StringInfo str, CreateTableAsStmt *node) appendStringInfoString(str, " AS"); _outSelectStmt(str, (SelectStmt *) node->query); } + + if (node->into->skipData) + { + if (node->into->skipData == TRUE) + appendStringInfoString(str, " WITH NO DATA"); + else + appendStringInfoString(str, " WITH DATA"); + } } static void @@ -1180,6 +1226,8 @@ _outSelectStmt(StringInfo str, SelectStmt *node) appendStringInfoString(str, "CREATE "); if (rel->relpersistence == RELPERSISTENCE_TEMP) appendStringInfoString(str, "TEMP "); + else if (rel->relpersistence == RELPERSISTENCE_UNLOGGED) + appendStringInfoString(str, "UNLOGGED "); appendStringInfoString(str, "TABLE "); _outNode(str, into->rel); @@ -1835,6 +1883,48 @@ _outMergeAction(StringInfo str, MergeAction *node) } static void +_outReturningOption(StringInfo str, List *node) +{ + ListCell *lc; + char comma = 0; + + appendStringInfoString(str, "WITH ("); + + foreach(lc, node) + { + ReturningOption *r = (ReturningOption *) lfirst(lc); + + if (comma == 0) + comma = 1; + else + appendStringInfoString(str, ", "); + + if (r->option == RETURNING_OPTION_OLD) + appendStringInfoString(str, "OLD "); + else if (r->option == RETURNING_OPTION_NEW) + appendStringInfoString(str, "NEW "); + + appendStringInfoString(str, "AS "); + appendStringInfoString(str, "\""); + appendStringInfoString(str, r->value); + appendStringInfoString(str, "\""); + } + + appendStringInfoString(str, ") "); +} + +static void +_outReturningClause(StringInfo str, ReturningClause *node) +{ + + if (node->options) + _outReturningOption(str, node->options); + + if (node->exprs) + _outList(str, node->exprs); +} + +static void _outSetOperationStmt(StringInfo str, SetOperationStmt *node) { @@ -2604,10 +2694,10 @@ _outInsertStmt(StringInfo str, InsertStmt *node) _outOnConflictClause(str, node->onConflictClause); } - if (node->returningList) + if (node->returningClause) { appendStringInfoString(str, " RETURNING "); - _outNode(str, node->returningList); + _outNode(str, node->returningClause); } } @@ -2719,10 +2809,10 @@ _outUpdateStmt(StringInfo str, UpdateStmt *node) _outNode(str, node->whereClause); } - if (node->returningList) + if (node->returningClause) { appendStringInfoString(str, " RETURNING "); - _outNode(str, node->returningList); + _outNode(str, node->returningClause); } } @@ -2748,10 +2838,10 @@ _outDeleteStmt(StringInfo str, DeleteStmt *node) _outNode(str, node->whereClause); } - if (node->returningList) + if (node->returningClause) { appendStringInfoString(str, " RETURNING "); - _outNode(str, node->returningList); + _outNode(str, node->returningClause); } } @@ -2778,10 +2868,10 @@ _outMergeStmt(StringInfo str, MergeStmt *node) _outMergeWhenClauses(str, node->mergeWhenClauses); } - if (node->returningList) + if (node->returningClause) { appendStringInfoString(str, " RETURNING "); - _outNode(str, node->returningList); + _outNode(str, node->returningClause); } } @@ -3843,6 +3933,11 @@ _outAlterTableCmd(StringInfo str, AlterTableCmd *node) } static void +_outATAlterConstraint(StringInfo str, ATAlterConstraint *node) +{ +} + +static void _outAlterTableStmt(StringInfo str, AlterTableStmt *node) { if (node->objtype == OBJECT_TABLE) @@ -3912,9 +4007,17 @@ static void _outCreateSeqStmt(StringInfo str, CreateSeqStmt *node) { appendStringInfoString(str, "CREATE "); + if (node->sequence->relpersistence == RELPERSISTENCE_TEMP) appendStringInfoString(str, "TEMP "); + else if (node->sequence->relpersistence == RELPERSISTENCE_UNLOGGED) + appendStringInfoString(str, "UNLOGGED "); + appendStringInfoString(str, "SEQUENCE "); + + if (node->if_not_exists) + appendStringInfoString(str, "IF NOT EXISTS "); + _outNode(str, node->sequence); _outOptSeqList(str, node->options); @@ -6076,11 +6179,6 @@ _outPartitionRangeDatum(StringInfo str, PartitionRangeDatum *node) { } -static void -_outSinglePartitionSpec(StringInfo str, const SinglePartitionSpec *node) -{ -} - /* * _outNode - * converts a Node into ascii string and append it to 'str' @@ -6297,6 +6395,9 @@ _outNode(StringInfo str, void *obj) case T_InferenceElem: _outInferenceElem(str, obj); break; + case T_ReturningExpr: + _outReturningExpr(str, obj); + break; case T_TargetEntry: _outTargetEntry(str, obj); break; @@ -6398,6 +6499,12 @@ _outNode(StringInfo str, void *obj) case T_MergeWhenClause: _outMergeWhenClauses(str, obj); break; + case T_ReturningOption: + _outReturningOption(str, obj); + break; + case T_ReturningClause: + _outReturningClause(str, obj); + break; case T_SetOperationStmt: _outSetOperationStmt(str, obj); break; @@ -6546,9 +6653,6 @@ _outNode(StringInfo str, void *obj) case T_PartitionRangeDatum: _outPartitionRangeDatum(str, obj); break; - case T_SinglePartitionSpec: - _outSinglePartitionSpec(str, obj); - break; case T_InsertStmt: _outInsertStmt(str, obj); @@ -6662,6 +6766,10 @@ _outNode(StringInfo str, void *obj) _outAlterTableCmd(str, obj); break; + case T_ATAlterConstraint: + _outATAlterConstraint(str, obj); + break; + case T_CreateSeqStmt: _outCreateSeqStmt(str, obj); break; diff --git a/src/parser/parser.c b/src/parser/parser.c index 878220be9..997c175fb 100644 --- a/src/parser/parser.c +++ b/src/parser/parser.c @@ -10,8 +10,8 @@ * analyze.c and related files. * * - * Portions Copyright (c) 2003-2024, PgPool Global Development Group - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2003-2025, PgPool Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION diff --git a/src/parser/scan.l b/src/parser/scan.l index 03f86b5f1..011728cc8 100644 --- a/src/parser/scan.l +++ b/src/parser/scan.l @@ -22,8 +22,8 @@ * Postgres 9.2, this check is made automatically by the Makefile.) * * - * Portions Copyright (c) 2003-2024, PgPool Global Development Group - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2003-2025, PgPool Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION @@ -42,10 +42,12 @@ #include "scansup.h" #include "kwlookup.h" #include "pg_wchar.h" +#include "miscnodes.h" #include "gram.h" #include "utils/palloc.h" #include "utils/elog.h" +#include "utils/elog.h" } %{ @@ -96,12 +98,6 @@ const uint16 ScanKeywordTokens[] = { #define YYSTYPE core_YYSTYPE /* - * Set the type of yyextra. All state variables used by the scanner should - * be in yyextra, *not* statically allocated. - */ -#define YY_EXTRA_TYPE core_yy_extra_type * - -/* * Each call to yylex must set yylloc to the location of the found token * (expressed as a byte offset from the start of the input text). * When we parse a token that requires multiple lexer rules to process, @@ -142,15 +138,6 @@ static void addunicode(pg_wchar c, yyscan_t yyscanner); static void check_string_escape_warning(unsigned char ychar, core_yyscan_t yyscanner); static void check_escape_warning(core_yyscan_t yyscanner); -/* - * Work around a bug in flex 2.5.35: it emits a couple of functions that - * it forgets to emit declarations for. Since we use -Wmissing-prototypes, - * this would cause warnings. Providing our own declarations should be - * harmless even when the bug gets fixed. - */ -extern int core_yyget_column(yyscan_t yyscanner); -extern void core_yyset_column(int column_no, yyscan_t yyscanner); - %} %option reentrant @@ -167,6 +154,7 @@ extern void core_yyset_column(int column_no, yyscan_t yyscanner); %option noyyfree %option warn %option prefix="core_yy" +%option extra-type="core_yy_extra_type *" /* * OK, here is a short description of lex/flex rules behavior. @@ -418,16 +406,30 @@ numericfail {decinteger}\.\. real ({decinteger}|{numeric})[Ee][-+]?{decinteger} realfail ({decinteger}|{numeric})[Ee][-+] -decinteger_junk {decinteger}{ident_start} -hexinteger_junk {hexinteger}{ident_start} -octinteger_junk {octinteger}{ident_start} -bininteger_junk {bininteger}{ident_start} -numeric_junk {numeric}{ident_start} -real_junk {real}{ident_start} - /* Positional parameters don't accept underscores. */ param \${decdigit}+ -param_junk \${decdigit}+{ident_start} + +/* + * An identifier immediately following an integer literal is disallowed because + * in some cases it's ambiguous what is meant: for example, 0x1234 could be + * either a hexinteger or a decinteger "0" and an identifier "x1234". We can + * detect such problems by seeing if integer_junk matches a longer substring + * than any of the XXXinteger patterns (decinteger, hexinteger, octinteger, + * bininteger). One "junk" pattern is sufficient because + * {decinteger}{identifier} will match all the same strings we'd match with + * {hexinteger}{identifier} etc. + * + * Note that the rule for integer_junk must appear after the ones for + * XXXinteger to make this work correctly: 0x1234 will match both hexinteger + * and integer_junk, and we need hexinteger to be chosen in that case. + * + * Also disallow strings matched by numeric_junk, real_junk and param_junk + * for consistency. + */ +integer_junk {decinteger}{identifier} +numeric_junk {numeric}{identifier} +real_junk {real}{identifier} +param_junk \${decdigit}+{identifier} other . @@ -1057,19 +1059,7 @@ other . SET_YYLLOC(); yyerror("trailing junk after numeric literal"); } -{decinteger_junk} { - SET_YYLLOC(); - yyerror("trailing junk after numeric literal"); - } -{hexinteger_junk} { - SET_YYLLOC(); - yyerror("trailing junk after numeric literal"); - } -{octinteger_junk} { - SET_YYLLOC(); - yyerror("trailing junk after numeric literal"); - } -{bininteger_junk} { +{integer_junk} { SET_YYLLOC(); yyerror("trailing junk after numeric literal"); } @@ -1210,7 +1200,7 @@ setup_scanner_errposition_callback(ScannerCallbackState *scbstate, scbstate->yyscanner = yyscanner; scbstate->location = location; scbstate->errcallback.callback = scb_error_callback; - scbstate->errcallback.arg = (void *) scbstate; + scbstate->errcallback.arg = scbstate; scbstate->errcallback.previous = error_context_stack; error_context_stack = &scbstate->errcallback; } @@ -1490,10 +1480,10 @@ check_escape_warning(core_yyscan_t yyscanner) ereport(WARNING, (errcode(ERRCODE_NONSTANDARD_USE_OF_ESCAPE_CHARACTER), errmsg("nonstandard use of escape in a string literal"), - errhint("Use the escape string syntax for escapes, e.g., E'\\r\\n'."), + errhint("Use the escape string syntax for escapes, e.g., E'\\r\\n'."), lexer_errposition())); #endif - yyextra->warn_on_first_escape = false; /* warn only once per string */ + yyextra->warn_on_first_escape = false; /* warn only once per string */ } /* diff --git a/src/parser/scansup.c b/src/parser/scansup.c index 27df0468a..943fb358b 100644 --- a/src/parser/scansup.c +++ b/src/parser/scansup.c @@ -3,8 +3,8 @@ * scansup.c * scanner support routines used by the core lexer * - * Portions Copyright (c) 2003-2024, PgPool Global Development Group - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2003-2025, PgPool Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * diff --git a/src/parser/snprintf.c b/src/parser/snprintf.c index c3564935e..e82832f24 100644 --- a/src/parser/snprintf.c +++ b/src/parser/snprintf.c @@ -1,9 +1,9 @@ /* - * Copyright (c) 2003-2024, PgPool Global Development Group + * Copyright (c) 2003-2025, PgPool Global Development Group * Copyright (c) 1983, 1995, 1996 Eric P. Allman * Copyright (c) 1988, 1993 * The Regents of the University of California. All rights reserved. - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -32,17 +32,14 @@ * src/port/snprintf.c */ -#if 0 -#include "c.h" -#endif - +#include <ctype.h> +#include <errno.h> +#include <math.h> #include <stdarg.h> -#include <stdio.h> #include <stdint.h> +#include <stdio.h> #include <stdlib.h> #include <string.h> -#include <ctype.h> -#include <errno.h> #include "pool_parser.h" #include "stringinfo.h" #include "utils/palloc.h" @@ -397,13 +394,22 @@ static void leading_pad(int zpad, int signvalue, int *padlen, static void trailing_pad(int padlen, PrintfTarget * target); /* - * If strchrnul exists (it's a glibc-ism), it's a good bit faster than the - * equivalent manual loop. If it doesn't exist, provide a replacement. + * If strchrnul exists (it's a glibc-ism, but since adopted by some other + * platforms), it's a good bit faster than the equivalent manual loop. + * Use it if possible, and if it doesn't exist, use this replacement. * * Note: glibc declares this as returning "char *", but that would require * casting away const internally, so we don't follow that detail. + * + * Note: macOS has this too as of Sequoia 15.4, but it's hidden behind + * a deployment-target check that causes compile errors if the deployment + * target isn't high enough. So !HAVE_DECL_STRCHRNUL may mean "yes it's + * declared, but it doesn't compile". To avoid failing in that scenario, + * use a macro to avoid matching <string.h>'s name. */ -#ifndef HAVE_STRCHRNUL +#if !HAVE_DECL_STRCHRNUL + +#define strchrnul pg_strchrnul static inline const char * strchrnul(const char *s, int c) @@ -413,19 +419,7 @@ strchrnul(const char *s, int c) return s; } -#else - -/* - * glibc's <string.h> declares strchrnul only if _GNU_SOURCE is defined. - * While we typically use that on glibc platforms, configure will set - * HAVE_STRCHRNUL whether it's used or not. Fill in the missing declaration - * so that this file will compile cleanly with or without _GNU_SOURCE. - */ -#ifndef _GNU_SOURCE -extern char *strchrnul(const char *s, int c); -#endif - -#endif /* HAVE_STRCHRNUL */ +#endif /* !HAVE_DECL_STRCHRNUL */ /* @@ -619,6 +613,28 @@ nextch2: fmtpos = accum; accum = 0; goto nextch2; +#ifdef WIN32 + case 'I': + /* Windows PRI*{32,64,PTR} size */ + if (format[0] == '3' && format[1] == '2') + format += 2; + else if (format[0] == '6' && format[1] == '4') + { + format += 2; + longlongflag = 1; + } + else + { +#if SIZEOF_VOID_P == SIZEOF_LONG + longflag = 1; +#elif SIZEOF_VOID_P == SIZEOF_LONG_LONG + longlongflag = 1; +#else +#error "cannot find integer type of the same size as intptr_t" +#endif + } + goto nextch2; +#endif case 'l': if (longflag) longlongflag = 1; @@ -626,16 +642,12 @@ nextch2: longflag = 1; goto nextch2; case 'z': -#if SIZEOF_SIZE_T == 8 -#ifdef HAVE_LONG_INT_64 +#if SIZEOF_SIZE_T == SIZEOF_LONG longflag = 1; -#elif defined(HAVE_LONG_LONG_INT_64) +#elif SIZEOF_SIZE_T == SIZEOF_LONG_LONG longlongflag = 1; #else -#error "Don't know how to print 64bit integers" -#endif -#else - /* assume size_t is same size as int */ +#error "cannot find integer type of the same size as size_t" #endif goto nextch2; case 'h': @@ -886,6 +898,28 @@ nextch1: fmtpos = accum; accum = 0; goto nextch1; +#ifdef WIN32 + case 'I': + /* Windows PRI*{32,64,PTR} size */ + if (format[0] == '3' && format[1] == '2') + format += 2; + else if (format[0] == '6' && format[1] == '4') + { + format += 2; + longlongflag = 1; + } + else + { +#if SIZEOF_VOID_P == SIZEOF_LONG + longflag = 1; +#elif SIZEOF_VOID_P == SIZEOF_LONG_LONG + longlongflag = 1; +#else +#error "cannot find integer type of the same size as intptr_t" +#endif + } + goto nextch1; +#endif case 'l': if (longflag) longlongflag = 1; @@ -893,16 +927,12 @@ nextch1: longflag = 1; goto nextch1; case 'z': -#if SIZEOF_SIZE_T == 8 -#ifdef HAVE_LONG_INT_64 +#if SIZEOF_SIZE_T == SIZEOF_LONG longflag = 1; -#elif defined(HAVE_LONG_LONG_INT_64) +#elif SIZEOF_SIZE_T == SIZEOF_LONG_LONG longlongflag = 1; #else -#error "Don't know how to print 64bit integers" -#endif -#else - /* assume size_t is same size as int */ +#error "cannot find integer type of the same size as size_t" #endif goto nextch1; case 'h': diff --git a/src/parser/stringinfo.c b/src/parser/stringinfo.c index c35e5bacf..9429dac46 100644 --- a/src/parser/stringinfo.c +++ b/src/parser/stringinfo.c @@ -6,11 +6,11 @@ * It can be used to buffer either ordinary C strings (null-terminated text) * or arbitrary binary data. All storage is allocated with palloc(). * - * Portions Copyright (c) 2003-2024, PgPool Global Development Group - * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group + * Portions Copyright (c) 2003-2025, PgPool Global Development Group + * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * src/backend/lib/stringinfo.c + * src/common/stringinfo.c * *------------------------------------------------------------------------- */ @@ -22,6 +22,40 @@ #include "utils/palloc.h" /* + * initStringInfoInternal + * + * Initialize a StringInfoData struct (with previously undefined contents) + * to describe an empty string. + * The initial memory allocation size is specified by 'initsize'. + * The valid range for 'initsize' is 1 to MaxAllocSize. + */ +static inline void +initStringInfoInternal(StringInfo str, int initsize) +{ + Assert(initsize >= 1 && initsize <= MaxAllocSize); + + str->data = (char *) palloc(initsize); + str->maxlen = initsize; + resetStringInfo(str); +} + +/* + * makeStringInfoInternal(int initsize) + * + * Create an empty 'StringInfoData' & return a pointer to it. + * The initial memory allocation size is specified by 'initsize'. + * The valid range for 'initsize' is 1 to MaxAllocSize. + */ +static inline StringInfo +makeStringInfoInternal(int initsize) +{ + StringInfo res = (StringInfo) palloc(sizeof(StringInfoData)); + + initStringInfoInternal(res, initsize); + return res; +} + +/* * makeStringInfo * * Create an empty 'StringInfoData' & return a pointer to it. @@ -29,13 +63,20 @@ StringInfo makeStringInfo(void) { - StringInfo res; - - res = (StringInfo) palloc(sizeof(StringInfoData)); - - initStringInfo(res); + return makeStringInfoInternal(STRINGINFO_DEFAULT_SIZE); +} - return res; +/* + * makeStringInfoExt(int initsize) + * + * Create an empty 'StringInfoData' & return a pointer to it. + * The initial memory allocation size is specified by 'initsize'. + * The valid range for 'initsize' is 1 to MaxAllocSize. + */ +StringInfo +makeStringInfoExt(int initsize) +{ + return makeStringInfoInternal(initsize); } /* @@ -47,11 +88,21 @@ makeStringInfo(void) void initStringInfo(StringInfo str) { - int size = 1024; /* initial default buffer size */ + initStringInfoInternal(str, STRINGINFO_DEFAULT_SIZE); +} - str->data = (char *) palloc(size); - str->maxlen = size; - resetStringInfo(str); +/* + * initStringInfoExt + * + * Initialize a StringInfoData struct (with previously undefined contents) + * to describe an empty string. + * The initial memory allocation size is specified by 'initsize'. + * The valid range for 'initsize' is 1 to MaxAllocSize. + */ +void +initStringInfoExt(StringInfo str, int initsize) +{ + initStringInfoInternal(str, initsize); } /* @@ -292,7 +343,7 @@ enlargeStringInfo(StringInfo str, int needed) if (((Size) needed) >= (MaxAllocSize - (Size) str->len)) ereport(ERROR, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), - errmsg("out of memory"), + errmsg("string buffer exceeds maximum allowed length (%zu bytes)", MaxAllocSize), errdetail("Cannot enlarge string buffer containing %d bytes by %d more bytes.", str->len, needed))); #endif diff --git a/src/parser/value.c b/src/parser/value.c index 3b7ab09a8..f99883c5b 100644 --- a/src/parser/value.c +++ b/src/parser/value.c @@ -4,8 +4,8 @@ * implementation of value nodes * * - * Copyright (c) 2003-2024, PgPool Global Development Group - * Copyright (c) 2003-2024, PostgreSQL Global Development Group + * Copyright (c) 2003-2025, PgPool Global Development Group + * Copyright (c) 2003-2025, PostgreSQL Global Development Group * * * IDENTIFICATION diff --git a/src/parser/wchar.c b/src/parser/wchar.c index 1e3a1b0ae..27c972fc0 100644 --- a/src/parser/wchar.c +++ b/src/parser/wchar.c @@ -9,6 +9,7 @@ #include "utils/elog.h" #include <stdio.h> #include <string.h> +#include <limits.h> #include "pg_wchar.h" #ifndef WIN32 @@ -115,6 +116,24 @@ const char *pg_enc2gettext_tbl[] = [PG_SHIFT_JIS_2004] = "SHIFT_JISX0213", }; +/* + * In today's multibyte encodings other than UTF8, this two-byte sequence + * ensures pg_encoding_mblen() == 2 && pg_encoding_verifymbstr() == 0. + * + * For historical reasons, several verifychar implementations opt to reject + * this pair specifically. Byte pair range constraints, in encoding + * originator documentation, always excluded this pair. No core conversion + * could translate it. However, longstanding verifychar implementations + * accepted any non-NUL byte. big5_to_euc_tw and big5_to_mic even translate + * pairs not valid per encoding originator documentation. To avoid tightening + * core or non-core conversions in a security patch, we sought this one pair. + * + * PQescapeString() historically used spaces for BYTE1; many other values + * could suffice for BYTE1. + */ +#define NONUTF8_INVALID_BYTE0 (0x8d) +#define NONUTF8_INVALID_BYTE1 (' ') + /* * Operations on multi-byte encodings are driven by a table of helper @@ -706,454 +725,8 @@ mbbisearch(pg_wchar ucs, const struct mbinterval *table, int max) static int ucs_wcwidth(pg_wchar ucs) { - /* sorted list of non-overlapping intervals of non-spacing characters */ - static const struct mbinterval nonspacing[] = { - {0x00AD, 0x00AD}, - {0x0300, 0x036F}, - {0x0483, 0x0489}, - {0x0591, 0x05BD}, - {0x05BF, 0x05BF}, - {0x05C1, 0x05C2}, - {0x05C4, 0x05C5}, - {0x05C7, 0x05C7}, - {0x0600, 0x0605}, - {0x0610, 0x061A}, - {0x061C, 0x061C}, - {0x064B, 0x065F}, - {0x0670, 0x0670}, - {0x06D6, 0x06DD}, - {0x06DF, 0x06E4}, - {0x06E7, 0x06E8}, - {0x06EA, 0x06ED}, - {0x070F, 0x070F}, - {0x0711, 0x0711}, - {0x0730, 0x074A}, - {0x07A6, 0x07B0}, - {0x07EB, 0x07F3}, - {0x07FD, 0x07FD}, - {0x0816, 0x0819}, - {0x081B, 0x0823}, - {0x0825, 0x0827}, - {0x0829, 0x082D}, - {0x0859, 0x085B}, - {0x0890, 0x089F}, - {0x08CA, 0x0902}, - {0x093A, 0x093A}, - {0x093C, 0x093C}, - {0x0941, 0x0948}, - {0x094D, 0x094D}, - {0x0951, 0x0957}, - {0x0962, 0x0963}, - {0x0981, 0x0981}, - {0x09BC, 0x09BC}, - {0x09C1, 0x09C4}, - {0x09CD, 0x09CD}, - {0x09E2, 0x09E3}, - {0x09FE, 0x0A02}, - {0x0A3C, 0x0A3C}, - {0x0A41, 0x0A51}, - {0x0A70, 0x0A71}, - {0x0A75, 0x0A75}, - {0x0A81, 0x0A82}, - {0x0ABC, 0x0ABC}, - {0x0AC1, 0x0AC8}, - {0x0ACD, 0x0ACD}, - {0x0AE2, 0x0AE3}, - {0x0AFA, 0x0B01}, - {0x0B3C, 0x0B3C}, - {0x0B3F, 0x0B3F}, - {0x0B41, 0x0B44}, - {0x0B4D, 0x0B56}, - {0x0B62, 0x0B63}, - {0x0B82, 0x0B82}, - {0x0BC0, 0x0BC0}, - {0x0BCD, 0x0BCD}, - {0x0C00, 0x0C00}, - {0x0C04, 0x0C04}, - {0x0C3C, 0x0C3C}, - {0x0C3E, 0x0C40}, - {0x0C46, 0x0C56}, - {0x0C62, 0x0C63}, - {0x0C81, 0x0C81}, - {0x0CBC, 0x0CBC}, - {0x0CBF, 0x0CBF}, - {0x0CC6, 0x0CC6}, - {0x0CCC, 0x0CCD}, - {0x0CE2, 0x0CE3}, - {0x0D00, 0x0D01}, - {0x0D3B, 0x0D3C}, - {0x0D41, 0x0D44}, - {0x0D4D, 0x0D4D}, - {0x0D62, 0x0D63}, - {0x0D81, 0x0D81}, - {0x0DCA, 0x0DCA}, - {0x0DD2, 0x0DD6}, - {0x0E31, 0x0E31}, - {0x0E34, 0x0E3A}, - {0x0E47, 0x0E4E}, - {0x0EB1, 0x0EB1}, - {0x0EB4, 0x0EBC}, - {0x0EC8, 0x0ECE}, - {0x0F18, 0x0F19}, - {0x0F35, 0x0F35}, - {0x0F37, 0x0F37}, - {0x0F39, 0x0F39}, - {0x0F71, 0x0F7E}, - {0x0F80, 0x0F84}, - {0x0F86, 0x0F87}, - {0x0F8D, 0x0FBC}, - {0x0FC6, 0x0FC6}, - {0x102D, 0x1030}, - {0x1032, 0x1037}, - {0x1039, 0x103A}, - {0x103D, 0x103E}, - {0x1058, 0x1059}, - {0x105E, 0x1060}, - {0x1071, 0x1074}, - {0x1082, 0x1082}, - {0x1085, 0x1086}, - {0x108D, 0x108D}, - {0x109D, 0x109D}, - {0x135D, 0x135F}, - {0x1712, 0x1714}, - {0x1732, 0x1733}, - {0x1752, 0x1753}, - {0x1772, 0x1773}, - {0x17B4, 0x17B5}, - {0x17B7, 0x17BD}, - {0x17C6, 0x17C6}, - {0x17C9, 0x17D3}, - {0x17DD, 0x17DD}, - {0x180B, 0x180F}, - {0x1885, 0x1886}, - {0x18A9, 0x18A9}, - {0x1920, 0x1922}, - {0x1927, 0x1928}, - {0x1932, 0x1932}, - {0x1939, 0x193B}, - {0x1A17, 0x1A18}, - {0x1A1B, 0x1A1B}, - {0x1A56, 0x1A56}, - {0x1A58, 0x1A60}, - {0x1A62, 0x1A62}, - {0x1A65, 0x1A6C}, - {0x1A73, 0x1A7F}, - {0x1AB0, 0x1B03}, - {0x1B34, 0x1B34}, - {0x1B36, 0x1B3A}, - {0x1B3C, 0x1B3C}, - {0x1B42, 0x1B42}, - {0x1B6B, 0x1B73}, - {0x1B80, 0x1B81}, - {0x1BA2, 0x1BA5}, - {0x1BA8, 0x1BA9}, - {0x1BAB, 0x1BAD}, - {0x1BE6, 0x1BE6}, - {0x1BE8, 0x1BE9}, - {0x1BED, 0x1BED}, - {0x1BEF, 0x1BF1}, - {0x1C2C, 0x1C33}, - {0x1C36, 0x1C37}, - {0x1CD0, 0x1CD2}, - {0x1CD4, 0x1CE0}, - {0x1CE2, 0x1CE8}, - {0x1CED, 0x1CED}, - {0x1CF4, 0x1CF4}, - {0x1CF8, 0x1CF9}, - {0x1DC0, 0x1DFF}, - {0x200B, 0x200F}, - {0x202A, 0x202E}, - {0x2060, 0x206F}, - {0x20D0, 0x20F0}, - {0x2CEF, 0x2CF1}, - {0x2D7F, 0x2D7F}, - {0x2DE0, 0x2DFF}, - {0x302A, 0x302D}, - {0x3099, 0x309A}, - {0xA66F, 0xA672}, - {0xA674, 0xA67D}, - {0xA69E, 0xA69F}, - {0xA6F0, 0xA6F1}, - {0xA802, 0xA802}, - {0xA806, 0xA806}, - {0xA80B, 0xA80B}, - {0xA825, 0xA826}, - {0xA82C, 0xA82C}, - {0xA8C4, 0xA8C5}, - {0xA8E0, 0xA8F1}, - {0xA8FF, 0xA8FF}, - {0xA926, 0xA92D}, - {0xA947, 0xA951}, - {0xA980, 0xA982}, - {0xA9B3, 0xA9B3}, - {0xA9B6, 0xA9B9}, - {0xA9BC, 0xA9BD}, - {0xA9E5, 0xA9E5}, - {0xAA29, 0xAA2E}, - {0xAA31, 0xAA32}, - {0xAA35, 0xAA36}, - {0xAA43, 0xAA43}, - {0xAA4C, 0xAA4C}, - {0xAA7C, 0xAA7C}, - {0xAAB0, 0xAAB0}, - {0xAAB2, 0xAAB4}, - {0xAAB7, 0xAAB8}, - {0xAABE, 0xAABF}, - {0xAAC1, 0xAAC1}, - {0xAAEC, 0xAAED}, - {0xAAF6, 0xAAF6}, - {0xABE5, 0xABE5}, - {0xABE8, 0xABE8}, - {0xABED, 0xABED}, - {0xFB1E, 0xFB1E}, - {0xFE00, 0xFE0F}, - {0xFE20, 0xFE2F}, - {0xFEFF, 0xFEFF}, - {0xFFF9, 0xFFFB}, - {0x101FD, 0x101FD}, - {0x102E0, 0x102E0}, - {0x10376, 0x1037A}, - {0x10A01, 0x10A0F}, - {0x10A38, 0x10A3F}, - {0x10AE5, 0x10AE6}, - {0x10D24, 0x10D27}, - {0x10EAB, 0x10EAC}, - {0x10EFD, 0x10EFF}, - {0x10F46, 0x10F50}, - {0x10F82, 0x10F85}, - {0x11001, 0x11001}, - {0x11038, 0x11046}, - {0x11070, 0x11070}, - {0x11073, 0x11074}, - {0x1107F, 0x11081}, - {0x110B3, 0x110B6}, - {0x110B9, 0x110BA}, - {0x110BD, 0x110BD}, - {0x110C2, 0x110CD}, - {0x11100, 0x11102}, - {0x11127, 0x1112B}, - {0x1112D, 0x11134}, - {0x11173, 0x11173}, - {0x11180, 0x11181}, - {0x111B6, 0x111BE}, - {0x111C9, 0x111CC}, - {0x111CF, 0x111CF}, - {0x1122F, 0x11231}, - {0x11234, 0x11234}, - {0x11236, 0x11237}, - {0x1123E, 0x1123E}, - {0x11241, 0x11241}, - {0x112DF, 0x112DF}, - {0x112E3, 0x112EA}, - {0x11300, 0x11301}, - {0x1133B, 0x1133C}, - {0x11340, 0x11340}, - {0x11366, 0x11374}, - {0x11438, 0x1143F}, - {0x11442, 0x11444}, - {0x11446, 0x11446}, - {0x1145E, 0x1145E}, - {0x114B3, 0x114B8}, - {0x114BA, 0x114BA}, - {0x114BF, 0x114C0}, - {0x114C2, 0x114C3}, - {0x115B2, 0x115B5}, - {0x115BC, 0x115BD}, - {0x115BF, 0x115C0}, - {0x115DC, 0x115DD}, - {0x11633, 0x1163A}, - {0x1163D, 0x1163D}, - {0x1163F, 0x11640}, - {0x116AB, 0x116AB}, - {0x116AD, 0x116AD}, - {0x116B0, 0x116B5}, - {0x116B7, 0x116B7}, - {0x1171D, 0x1171F}, - {0x11722, 0x11725}, - {0x11727, 0x1172B}, - {0x1182F, 0x11837}, - {0x11839, 0x1183A}, - {0x1193B, 0x1193C}, - {0x1193E, 0x1193E}, - {0x11943, 0x11943}, - {0x119D4, 0x119DB}, - {0x119E0, 0x119E0}, - {0x11A01, 0x11A0A}, - {0x11A33, 0x11A38}, - {0x11A3B, 0x11A3E}, - {0x11A47, 0x11A47}, - {0x11A51, 0x11A56}, - {0x11A59, 0x11A5B}, - {0x11A8A, 0x11A96}, - {0x11A98, 0x11A99}, - {0x11C30, 0x11C3D}, - {0x11C3F, 0x11C3F}, - {0x11C92, 0x11CA7}, - {0x11CAA, 0x11CB0}, - {0x11CB2, 0x11CB3}, - {0x11CB5, 0x11CB6}, - {0x11D31, 0x11D45}, - {0x11D47, 0x11D47}, - {0x11D90, 0x11D91}, - {0x11D95, 0x11D95}, - {0x11D97, 0x11D97}, - {0x11EF3, 0x11EF4}, - {0x11F00, 0x11F01}, - {0x11F36, 0x11F3A}, - {0x11F40, 0x11F40}, - {0x11F42, 0x11F42}, - {0x13430, 0x13440}, - {0x13447, 0x13455}, - {0x16AF0, 0x16AF4}, - {0x16B30, 0x16B36}, - {0x16F4F, 0x16F4F}, - {0x16F8F, 0x16F92}, - {0x16FE4, 0x16FE4}, - {0x1BC9D, 0x1BC9E}, - {0x1BCA0, 0x1CF46}, - {0x1D167, 0x1D169}, - {0x1D173, 0x1D182}, - {0x1D185, 0x1D18B}, - {0x1D1AA, 0x1D1AD}, - {0x1D242, 0x1D244}, - {0x1DA00, 0x1DA36}, - {0x1DA3B, 0x1DA6C}, - {0x1DA75, 0x1DA75}, - {0x1DA84, 0x1DA84}, - {0x1DA9B, 0x1DAAF}, - {0x1E000, 0x1E02A}, - {0x1E08F, 0x1E08F}, - {0x1E130, 0x1E136}, - {0x1E2AE, 0x1E2AE}, - {0x1E2EC, 0x1E2EF}, - {0x1E4EC, 0x1E4EF}, - {0x1E8D0, 0x1E8D6}, - {0x1E944, 0x1E94A}, - {0xE0001, 0xE01EF}, - }; - - static const struct mbinterval east_asian_fw[] = { - {0x1100, 0x115F}, - {0x231A, 0x231B}, - {0x2329, 0x232A}, - {0x23E9, 0x23EC}, - {0x23F0, 0x23F0}, - {0x23F3, 0x23F3}, - {0x25FD, 0x25FE}, - {0x2614, 0x2615}, - {0x2648, 0x2653}, - {0x267F, 0x267F}, - {0x2693, 0x2693}, - {0x26A1, 0x26A1}, - {0x26AA, 0x26AB}, - {0x26BD, 0x26BE}, - {0x26C4, 0x26C5}, - {0x26CE, 0x26CE}, - {0x26D4, 0x26D4}, - {0x26EA, 0x26EA}, - {0x26F2, 0x26F3}, - {0x26F5, 0x26F5}, - {0x26FA, 0x26FA}, - {0x26FD, 0x26FD}, - {0x2705, 0x2705}, - {0x270A, 0x270B}, - {0x2728, 0x2728}, - {0x274C, 0x274C}, - {0x274E, 0x274E}, - {0x2753, 0x2755}, - {0x2757, 0x2757}, - {0x2795, 0x2797}, - {0x27B0, 0x27B0}, - {0x27BF, 0x27BF}, - {0x2B1B, 0x2B1C}, - {0x2B50, 0x2B50}, - {0x2B55, 0x2B55}, - {0x2E80, 0x2E99}, - {0x2E9B, 0x2EF3}, - {0x2F00, 0x2FD5}, - {0x2FF0, 0x303E}, - {0x3041, 0x3096}, - {0x3099, 0x30FF}, - {0x3105, 0x312F}, - {0x3131, 0x318E}, - {0x3190, 0x31E3}, - {0x31EF, 0x321E}, - {0x3220, 0x3247}, - {0x3250, 0x4DBF}, - {0x4E00, 0xA48C}, - {0xA490, 0xA4C6}, - {0xA960, 0xA97C}, - {0xAC00, 0xD7A3}, - {0xF900, 0xFAFF}, - {0xFE10, 0xFE19}, - {0xFE30, 0xFE52}, - {0xFE54, 0xFE66}, - {0xFE68, 0xFE6B}, - {0xFF01, 0xFF60}, - {0xFFE0, 0xFFE6}, - {0x16FE0, 0x16FE4}, - {0x16FF0, 0x16FF1}, - {0x17000, 0x187F7}, - {0x18800, 0x18CD5}, - {0x18D00, 0x18D08}, - {0x1AFF0, 0x1AFF3}, - {0x1AFF5, 0x1AFFB}, - {0x1AFFD, 0x1AFFE}, - {0x1B000, 0x1B122}, - {0x1B150, 0x1B152}, - {0x1B164, 0x1B167}, - {0x1B170, 0x1B2FB}, - {0x1F004, 0x1F004}, - {0x1F0CF, 0x1F0CF}, - {0x1F18E, 0x1F18E}, - {0x1F191, 0x1F19A}, - {0x1F200, 0x1F202}, - {0x1F210, 0x1F23B}, - {0x1F240, 0x1F248}, - {0x1F250, 0x1F251}, - {0x1F260, 0x1F265}, - {0x1F300, 0x1F320}, - {0x1F32D, 0x1F335}, - {0x1F337, 0x1F37C}, - {0x1F37E, 0x1F393}, - {0x1F3A0, 0x1F3CA}, - {0x1F3CF, 0x1F3D3}, - {0x1F3E0, 0x1F3F0}, - {0x1F3F4, 0x1F3F4}, - {0x1F3F8, 0x1F43E}, - {0x1F440, 0x1F440}, - {0x1F442, 0x1F4FC}, - {0x1F4FF, 0x1F53D}, - {0x1F54B, 0x1F54E}, - {0x1F550, 0x1F567}, - {0x1F57A, 0x1F57A}, - {0x1F595, 0x1F596}, - {0x1F5A4, 0x1F5A4}, - {0x1F5FB, 0x1F64F}, - {0x1F680, 0x1F6C5}, - {0x1F6CC, 0x1F6CC}, - {0x1F6D0, 0x1F6D2}, - {0x1F6D5, 0x1F6D7}, - {0x1F6DD, 0x1F6DF}, - {0x1F6EB, 0x1F6EC}, - {0x1F6F4, 0x1F6FC}, - {0x1F7E0, 0x1F7EB}, - {0x1F7F0, 0x1F7F0}, - {0x1F90C, 0x1F93A}, - {0x1F93C, 0x1F945}, - {0x1F947, 0x1F9FF}, - {0x1FA70, 0x1FA74}, - {0x1FA78, 0x1FA7C}, - {0x1FA80, 0x1FA86}, - {0x1FA90, 0x1FAAC}, - {0x1FAB0, 0x1FABA}, - {0x1FAC0, 0x1FAC5}, - {0x1FAD0, 0x1FAD9}, - {0x1FAE0, 0x1FAE7}, - {0x1FAF0, 0x1FAF6}, - {0x20000, 0x2FFFD}, - {0x30000, 0x3FFFD}, - }; +#include "unicode_nonspacing_table.h" +#include "unicode_east_asian_fw_table.h" /* test for 8-bit control characters */ if (ucs == 0) @@ -2010,6 +1583,11 @@ pg_big5_verifychar(const unsigned char *s, int len) if (len < l) return -1; + if (l == 2 && + s[0] == NONUTF8_INVALID_BYTE0 && + s[1] == NONUTF8_INVALID_BYTE1) + return -1; + while (--l > 0) { if (*++s == '\0') @@ -2059,6 +1637,11 @@ pg_gbk_verifychar(const unsigned char *s, int len) if (len < l) return -1; + if (l == 2 && + s[0] == NONUTF8_INVALID_BYTE0 && + s[1] == NONUTF8_INVALID_BYTE1) + return -1; + while (--l > 0) { if (*++s == '\0') @@ -2108,6 +1691,11 @@ pg_uhc_verifychar(const unsigned char *s, int len) if (len < l) return -1; + if (l == 2 && + s[0] == NONUTF8_INVALID_BYTE0 && + s[1] == NONUTF8_INVALID_BYTE1) + return -1; + while (--l > 0) { if (*++s == '\0') @@ -2631,6 +2219,19 @@ pg_eucjp_increment(unsigned char *charptr, int length) /* + * Fills the provided buffer with two bytes such that: + * pg_encoding_mblen(dst) == 2 && pg_encoding_verifymbstr(dst) == 0 + */ +void +pg_encoding_set_invalid(int encoding, char *dst) +{ + Assert(pg_encoding_max_length(encoding) > 1); + + dst[0] = (encoding == PG_UTF8 ? 0xc0 : NONUTF8_INVALID_BYTE0); + dst[1] = NONUTF8_INVALID_BYTE1; +} + +/* *------------------------------------------------------------------- * encoding info table *------------------------------------------------------------------- @@ -2683,10 +2284,27 @@ const pg_wchar_tbl pg_wchar_table[] = { /* * Returns the byte length of a multibyte character. * - * Caution: when dealing with text that is not certainly valid in the - * specified encoding, the result may exceed the actual remaining - * string length. Callers that are not prepared to deal with that - * should use pg_encoding_mblen_bounded() instead. + * Choose "mblen" functions based on the input string characteristics. + * pg_encoding_mblen() can be used when ANY of these conditions are met: + * + * - The input string is zero-terminated + * + * - The input string is known to be valid in the encoding (e.g., string + * converted from database encoding) + * + * - The encoding is not GB18030 (e.g., when only database encodings are + * passed to 'encoding' parameter) + * + * encoding==GB18030 requires examining up to two bytes to determine character + * length. Therefore, callers satisfying none of those conditions must use + * pg_encoding_mblen_or_incomplete() instead, as access to mbstr[1] cannot be + * guaranteed to be within allocation bounds. + * + * When dealing with text that is not certainly valid in the specified + * encoding, the result may exceed the actual remaining string length. + * Callers that are not prepared to deal with that should use Min(remaining, + * pg_encoding_mblen_or_incomplete()). For zero-terminated strings, that and + * pg_encoding_mblen_bounded() are interchangeable. */ int pg_encoding_mblen(int encoding, const char *mbstr) @@ -2697,8 +2315,28 @@ pg_encoding_mblen(int encoding, const char *mbstr) } /* - * Returns the byte length of a multibyte character; but not more than - * the distance to end of string. + * Returns the byte length of a multibyte character (possibly not + * zero-terminated), or INT_MAX if too few bytes remain to determine a length. + */ +int +pg_encoding_mblen_or_incomplete(int encoding, const char *mbstr, + size_t remaining) +{ + /* + * Define zero remaining as too few, even for single-byte encodings. + * pg_gb18030_mblen() reads one or two bytes; single-byte encodings read + * zero; others read one. + */ + if (remaining < 1 || + (encoding == PG_GB18030 && IS_HIGHBIT_SET(*mbstr) && remaining < 2)) + return INT_MAX; + return pg_encoding_mblen(encoding, mbstr); +} + +/* + * Returns the byte length of a multibyte character; but not more than the + * distance to the terminating zero byte. For input that might lack a + * terminating zero, use Min(remaining, pg_encoding_mblen_or_incomplete()). */ int pg_encoding_mblen_bounded(int encoding, const char *mbstr) @@ -2751,7 +2389,13 @@ pg_encoding_max_length(int encoding) { Assert(PG_VALID_ENCODING(encoding)); - return pg_wchar_table[encoding].maxmblen; + /* + * Check for the encoding despite the assert, due to some mingw versions + * otherwise issuing bogus warnings. + */ + return PG_VALID_ENCODING(encoding) ? + pg_wchar_table[encoding].maxmblen : + pg_wchar_table[PG_SQL_ASCII].maxmblen; } #ifndef FRONTEND diff --git a/src/pcp_con/pcp_worker.c b/src/pcp_con/pcp_worker.c index a9d02e011..72bf68d84 100644 --- a/src/pcp_con/pcp_worker.c +++ b/src/pcp_con/pcp_worker.c @@ -933,9 +933,9 @@ inform_node_info(PCP_CONNECTION *frontend, char *buf) snprintf(standby_delay_by_time_str, sizeof(standby_delay_by_time_str), "%d", bi->standby_delay_by_time); - snprintf(standby_delay_str, sizeof(standby_delay_str), UINT64_FORMAT, bi->standby_delay); + snprintf(standby_delay_str, sizeof(standby_delay_str), "%lld", (long long) bi->standby_delay); - snprintf(status_changed_time_str, sizeof(status_changed_time_str), UINT64_FORMAT, bi->status_changed_time); + snprintf(status_changed_time_str, sizeof(status_changed_time_str), "%lld", (long long) bi->status_changed_time); pcp_write(frontend, "i", 1); wsize = htonl(sizeof(code) + diff --git a/src/pcp_con/recovery.c b/src/pcp_con/recovery.c index 8ad4a2fd5..84e4ddc17 100644 --- a/src/pcp_con/recovery.c +++ b/src/pcp_con/recovery.c @@ -482,7 +482,7 @@ connect_backend_libpq(BackendInfo *backend) port_str, NULL, NULL, - pool_config->recovery_database, + dbname, pool_config->recovery_user, password ? password : ""); diff --git a/src/pgpool.spec b/src/pgpool.spec index 6795c7f5f..c93eb37a3 100644 --- a/src/pgpool.spec +++ b/src/pgpool.spec @@ -21,7 +21,8 @@ %endif %global _varrundir %{_localstatedir}/run/pgpool -%global _varlogdir %{_localstatedir}/log/pgpool_log +%global _varlogdir %{_localstatedir}/log/pgpool +%global _varlibdir %{_localstatedir}/lib/pgpool Summary: Pgpool is a connection pooling/replication server for PostgreSQL Name: pgpool-II-pg%{pg_version} @@ -45,6 +46,7 @@ Patch1: pgpool_socket_dir.patch Patch2: pcp_unix_domain_path.patch %endif Patch3: pgpool_log.patch +Patch4: pgpool.conf.sample.patch BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) BuildRequires: postgresql%{pg_version}-devel pam-devel openssl-devel jade libxslt docbook-dtds docbook-style-xsl docbook-style-dsssl openldap-devel %if %{rhel} >= 9 @@ -71,7 +73,7 @@ Requires(preun): chkconfig Requires(preun): initscripts Requires(postun): initscripts %endif -Obsoletes: postgresql-pgpool +Obsoletes: postgresql-pgpool < %{version} # original pgpool archive name %define archive_name pgpool-II-%{version} @@ -107,6 +109,7 @@ PostgreSQL extensions libraries and sql files for pgpool-II. %patch2 -p0 %endif %patch3 -p0 +%patch4 -p0 %build %configure --with-pgsql=%{pghome} \ @@ -177,6 +180,7 @@ install -m 755 %{SOURCE1} %{buildroot}%{_initrddir}/pgpool %endif mkdir -p %{buildroot}%{_varlogdir} +mkdir -p %{buildroot}%{_varlibdir} install -d %{buildroot}%{_sysconfdir}/sysconfig %if 0%{rhel} && 0%{rhel} <= 6 @@ -290,6 +294,7 @@ fi %{_initrddir}/pgpool %endif %attr(0755,postgres,postgres) %dir %{_varlogdir} +%attr(0755,postgres,postgres) %dir %{_varlibdir} %defattr(600,postgres,postgres,-) %{_sysconfdir}/%{short_name}/pgpool.conf.sample %{_sysconfdir}/%{short_name}/pcp.conf.sample @@ -340,6 +345,8 @@ fi %{pghome}/share/extension/pgpool_adm--1.3--1.4.sql %{pghome}/share/extension/pgpool_adm--1.5.sql %{pghome}/share/extension/pgpool_adm--1.4--1.5.sql +%{pghome}/share/extension/pgpool_adm--1.6.sql +%{pghome}/share/extension/pgpool_adm--1.5--1.6.sql %{pghome}/share/extension/pgpool_adm.control %{pghome}/lib/pgpool_adm.so # From PostgreSQL 9.4 pgpool-regclass.so is not needed anymore @@ -360,6 +367,10 @@ fi %endif %changelog +* Tue Oct 14 2025 Taiki Koshino <koshino@sraoss.co.jp> 4.7.0 +- Change the value of log_directory parameter to '/var/log/pgpool'. +- Create '/var/lib/pgpool' and set it to work_dir. + * Wed Nov 2 2022 Bo Peng <pengbo@sraoss.co.jp> 4.4.0 - Change /lib/tmpfiles.d/ file from /var/run to /run - Install /etc/sudoers.d/pgpool diff --git a/src/protocol/CommandComplete.c b/src/protocol/CommandComplete.c index ef144ca31..a3b8f0ea1 100644 --- a/src/protocol/CommandComplete.c +++ b/src/protocol/CommandComplete.c @@ -5,7 +5,7 @@ * pgpool: a language independent connection pool server for PostgreSQL * written by Tatsuo Ishii * - * Copyright (c) 2003-2024 PgPool Global Development Group + * Copyright (c) 2003-2025 PgPool Global Development Group * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby @@ -111,8 +111,8 @@ CommandComplete(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend, bool c if (session_context->query_context && session_context->query_context->parse_tree && is_start_transaction_query(session_context->query_context->parse_tree)) - TSTATE(backend, i) = 'T'; /* we are inside a transaction */ { + TSTATE(backend, i) = 'T'; /* we are inside a transaction */ ereport(DEBUG1, (errmsg("processing command complete"), errdetail("set transaction state to T"))); diff --git a/src/protocol/child.c b/src/protocol/child.c index cf2161806..c34f05728 100644 --- a/src/protocol/child.c +++ b/src/protocol/child.c @@ -772,8 +772,11 @@ read_startup_packet(POOL_CONNECTION *cp) } /* The database defaults to their user name. */ - if (sp->database == NULL || sp->database[0] == '\0') + if (sp->database == NULL) + sp->database = pstrdup(sp->user); + else if (sp->database[0] == '\0') { + pfree(sp->database); sp->database = pstrdup(sp->user); } @@ -838,50 +841,7 @@ connect_using_existing_connection(POOL_CONNECTION *frontend, if (MAJOR(backend) == 3) { - char command_buf[1024]; - - /* - * If we have received application_name in the start up packet, we - * send SET command to backend. Also we add or replace existing - * application_name data. - */ - if (sp->application_name) - { - snprintf(command_buf, sizeof(command_buf), "SET application_name TO '%s'", sp->application_name); - - for (i = 0; i < NUM_BACKENDS; i++) - { - if (VALID_BACKEND(i)) - { - /* - * We want to catch and ignore errors in do_command if a - * backend is just going down right now. Otherwise - * do_command raises an error and disconnects the - * connection to frontend. We can safely ignore error from - * "SET application_name" command if the backend goes - * down. - */ - PG_TRY(); - { - do_command(frontend, CONNECTION(backend, i), - command_buf, MAJOR(backend), - MAIN_CONNECTION(backend)->pid, - MAIN_CONNECTION(backend)->key, - MAIN_CONNECTION(backend)->keylen, 0); - } - PG_CATCH(); - { - /* ignore the error message */ - MemoryContextSwitchTo(oldContext); - FlushErrorState(); - } - PG_END_TRY(); - } - } - pool_add_param(&MAIN(backend)->params, "application_name", sp->application_name); - set_application_name_with_string(sp->application_name); - } - + /* Send parameter status message to frontend. */ send_params(frontend, backend); } @@ -1337,6 +1297,8 @@ send_params(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend) pool_write(frontend, &sendlen, sizeof(sendlen)); pool_write(frontend, name, strlen(name) + 1); pool_write(frontend, value, strlen(value) + 1); + elog(DEBUG1, "send parameter status message to frontend: \"%s\" = \"%s\"", + name, value); } if (pool_flush(frontend)) diff --git a/src/protocol/pool_connection_pool.c b/src/protocol/pool_connection_pool.c index c3b369dc2..b16ccc39e 100644 --- a/src/protocol/pool_connection_pool.c +++ b/src/protocol/pool_connection_pool.c @@ -302,10 +302,10 @@ pool_create_cp(void) ereport(DEBUG1, (errmsg("creating connection pool"), - errdetail("user: %s database: %s closetime: %ld", + errdetail("user: %s database: %s closetime: %lld", CONNECTION_SLOT(p, main_node_id)->sp->user, CONNECTION_SLOT(p, main_node_id)->sp->database, - CONNECTION_SLOT(p, main_node_id)->closetime))); + (long long) CONNECTION_SLOT(p, main_node_id)->closetime))); if (CONNECTION_SLOT(p, main_node_id)->closetime < closetime) { @@ -366,7 +366,7 @@ pool_connection_pool_timer(POOL_CONNECTION_POOL *backend) ereport(DEBUG1, (errmsg("setting backend connection close timer"), - errdetail("close time %ld", time(NULL)))); + errdetail("close time %lld", (long long) time(NULL)))); /* Set connection close time */ for (i = 0; i < NUM_BACKENDS; i++) @@ -424,7 +424,7 @@ pool_backend_timer(void) now = time(NULL); ereport(DEBUG1, - (errmsg("backend timer handler called at %ld", now))); + (errmsg("backend timer handler called at %lld", (long long) now))); for (i = 0; i < pool_config->max_pool; i++, p++) { @@ -442,8 +442,8 @@ pool_backend_timer(void) ereport(DEBUG1, (errmsg("backend timer handler called"), - errdetail("expire time: %ld", - MAIN_CONNECTION(p)->closetime + pool_config->connection_life_time))); + errdetail("expire time: %lld", + (long long) (MAIN_CONNECTION(p)->closetime + pool_config->connection_life_time)))); if (now >= (MAIN_CONNECTION(p)->closetime + pool_config->connection_life_time)) { diff --git a/src/protocol/pool_process_query.c b/src/protocol/pool_process_query.c index 467e50baa..96334f8e0 100644 --- a/src/protocol/pool_process_query.c +++ b/src/protocol/pool_process_query.c @@ -3847,9 +3847,10 @@ read_kind_from_backend(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend, /* * If we are in in streaming replication mode and we doing an extended * query, check the kind we just read. If it's one of 'D' (data row), 'E' - * (error), or 'N' (notice), and the head of the pending message queue was - * 'execute', the message must not be pulled out so that next Command - * Complete message from backend matches the execute message. + * (error), 'N' (notice), 'H' (CopyOutResponse), 'd' (CopyData) or 'c' + * (CopyDone) and the head of the pending message queue was 'execute', the + * message must not be pulled out so that next Command Complete message + * from backend matches the execute message. * * Also if it's 't' (parameter description) and the pulled message was * 'describe', the message must not be pulled out so that the row @@ -3858,7 +3859,9 @@ read_kind_from_backend(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend, if (SL_MODE && pool_is_doing_extended_query_message() && msg) { if ((msg->type == POOL_EXECUTE && - (*decided_kind == 'D' || *decided_kind == 'E' || *decided_kind == 'N')) || + (*decided_kind == 'D' || *decided_kind == 'E' || + *decided_kind == 'N' || *decided_kind == 'H' || + *decided_kind == 'd' || *decided_kind == 'c')) || (msg->type == POOL_DESCRIBE && *decided_kind == 't')) { ereport(DEBUG5, @@ -5296,6 +5299,7 @@ pool_push_pending_data(POOL_CONNECTION *backend) { pool_push(backend, buf, len); pfree(buf); + buf = NULL; } data_pushed = true; if (kind == 'E') diff --git a/src/protocol/pool_proto_modules.c b/src/protocol/pool_proto_modules.c index 6fad3353c..9f31442b7 100644 --- a/src/protocol/pool_proto_modules.c +++ b/src/protocol/pool_proto_modules.c @@ -1609,7 +1609,7 @@ Parse(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend, } } - if (REPLICATION || SLONY) + if (REPLICATION) { /* * We must synchronize because Parse message acquires table locks. @@ -1721,9 +1721,26 @@ Bind(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend, parse_msg = pool_get_sent_message('P', pstmt_name, POOL_SENT_MESSAGE_CREATED); if (!parse_msg) { - ereport(FATAL, - (errmsg("unable to bind"), - errdetail("cannot get parse message \"%s\"", pstmt_name))); + char *errmessage; + + /* send error message to frontend */ + errmessage = psprintf("prepared statement \"%s\" does not exist", + pstmt_name); + pool_send_error_message(frontend, MAJOR(cp), "XX000", errmessage, + "", "", __FILE__, __LINE__); + pfree(errmessage); + + /* + * Since we do not receive an error response from backend, we need + * similar treatement in case of error response. + */ + pool_set_ignore_till_sync(); + pool_unset_query_in_progress(); + pool_unset_suspend_reading_from_frontend(); + if (SL_MODE) + pool_discard_except_sync_and_ready_for_query(frontend, backend); + + return POOL_CONTINUE; } bind_msg = pool_create_sent_message('B', len, contents, @@ -3829,9 +3846,9 @@ pi_set(int node_id) ProcessInfo *pi = pool_get_my_process_info(); if (node_id < BITS_PER_TYPE(uint64)) - pi->node_ids[0] |= (1 << node_id); + pi->node_ids[0] |= ((uint64) 1 << node_id); else - pi->node_ids[1] |= (1 << (node_id - BITS_PER_TYPE(uint64))); + pi->node_ids[1] |= ((uint64) 1 << (node_id - BITS_PER_TYPE(uint64))); } /* @@ -3843,9 +3860,9 @@ is_pi_set(uint64 *node_ids, int node_id) int set; if (node_id < BITS_PER_TYPE(uint64)) - set = node_ids[0] & (1 << node_id); + set = node_ids[0] & ((uint64) 1 << node_id); else - set = node_ids[1] & (1 << (node_id - BITS_PER_TYPE(uint64))); + set = node_ids[1] & ((uint64) 1 << (node_id - BITS_PER_TYPE(uint64))); return set != 0; } diff --git a/src/query_cache/pool_memqcache.c b/src/query_cache/pool_memqcache.c index 40ad93e1a..f38f71146 100644 --- a/src/query_cache/pool_memqcache.c +++ b/src/query_cache/pool_memqcache.c @@ -280,7 +280,7 @@ pool_commit_cache(POOL_CONNECTION_POOL *backend, char *query, char *data, size_t memqcache_expire = pool_config->memqcache_expire; ereport(DEBUG1, (errmsg("committing SELECT results to cache storage"), - errdetail("memqcache_expire = %ld", memqcache_expire))); + errdetail("memqcache_expire = %lld", (long long) memqcache_expire))); if (pool_is_shmem_cache()) { @@ -390,7 +390,7 @@ pool_catalog_commit_cache(POOL_CONNECTION_POOL *backend, char *query, char *data memqcache_expire = pool_config->relcache_expire; ereport(DEBUG1, (errmsg("committing relation cache to cache storage"), - errdetail("memqcache_expire = %ld", memqcache_expire))); + errdetail("memqcache_expire = %lld", (long long) memqcache_expire))); if (pool_is_shmem_cache()) { @@ -537,10 +537,12 @@ pool_fetch_cache(POOL_CONNECTION_POOL *backend, const char *query, char **buf, s memcpy(p, ptr, *len); +#ifdef USE_MEMCACHED if (!pool_is_shmem_cache()) { free(ptr); } +#endif ereport(DEBUG1, (errmsg("fetching from cache storage"), @@ -2900,8 +2902,8 @@ pool_find_item_on_shmem_cache(POOL_QUERY_HASH *query_hash) { ereport(DEBUG1, (errmsg("memcache finding item"), - errdetail("cache expired: now: %ld timestamp: %ld", - now, cih->timestamp + cih->expire))); + errdetail("cache expired: now: %lld timestamp: %lld", + (long long) now, (long long) (cih->timestamp + cih->expire)))); pool_delete_item_shmem_cache(c); return NULL; } @@ -3135,7 +3137,7 @@ pool_shmem_lock(POOL_MEMQ_LOCK_TYPE type) { char *path; - path = psprintf("%s/%s", pool_config->logdir, QUERY_CACHE_LOCK_FILE); + path = psprintf("%s/%s", pool_config->work_dir, QUERY_CACHE_LOCK_FILE); memq_lock_fd = open(path, O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR | S_IWUSR); if (memq_lock_fd == -1) { @@ -4872,8 +4874,8 @@ query_cache_delete_by_stmt(char *query, POOL_CONNECTION_POOL *backend) else pool_delete_item_shmem_cache(cacheid); } -#ifdef USE_MEMCACHED else +#ifdef USE_MEMCACHED { if (delete_cache_on_memcached(key) == 0) rtn = false; diff --git a/src/redhat/pcp_unix_domain_path.patch b/src/redhat/pcp_unix_domain_path.patch index 5b2b10685..0576b369c 100644 --- a/src/redhat/pcp_unix_domain_path.patch +++ b/src/redhat/pcp_unix_domain_path.patch @@ -1,16 +1,16 @@ -*** src/include/pcp/pcp_stream.h 2020-07-31 09:24:10.835496879 +0900 ---- pcp_stream.h 2020-07-31 09:24:02.598396128 +0900 +*** src/include/pcp/pcp_stream.h 2025-08-15 16:47:16.214748366 +0900 +--- pcp_stream.h 2025-08-15 16:47:07.339772297 +0900 *************** *** 49,54 **** - extern int pcp_write(PCP_CONNECTION * pc, void *buf, int len); - extern int pcp_flush(PCP_CONNECTION * pc); + extern int pcp_write(PCP_CONNECTION *pc, void *buf, int len); + extern int pcp_flush(PCP_CONNECTION *pc); ! #define UNIX_DOMAIN_PATH "/tmp" #endif /* PCP_STREAM_H */ --- 49,54 ---- - extern int pcp_write(PCP_CONNECTION * pc, void *buf, int len); - extern int pcp_flush(PCP_CONNECTION * pc); + extern int pcp_write(PCP_CONNECTION *pc, void *buf, int len); + extern int pcp_flush(PCP_CONNECTION *pc); ! #define UNIX_DOMAIN_PATH "/var/run/postgresql" diff --git a/src/redhat/pgpool.conf.sample.patch b/src/redhat/pgpool.conf.sample.patch index 515f26fc3..ada1bef3f 100644 --- a/src/redhat/pgpool.conf.sample.patch +++ b/src/redhat/pgpool.conf.sample.patch @@ -1,10 +1,10 @@ -*** src/sample/pgpool.conf.sample 2014-10-21 16:03:55.605775451 +0900 ---- pgpool.conf.sample.new 2014-10-21 16:04:15.557776162 +0900 +*** src/sample/pgpool.conf.sample 2025-09-30 17:44:36.223222257 +0900 +--- pgpool.conf.sample 2025-09-30 17:46:22.952860803 +0900 *************** -*** 58,72 **** - +*** 82,96 **** + # - Backend Connection Settings - - + ! #backend_hostname0 = 'host1' # Host name or IP address to connect to for backend 0 ! #backend_port0 = 5432 @@ -15,12 +15,12 @@ # Data directory for backend 0 ! #backend_flag0 = 'ALLOW_TO_FAILOVER' # Controls various backend behavior - # ALLOW_TO_FAILOVER or DISALLOW_TO_FAILOVER - #backend_hostname1 = 'host2' ---- 58,72 ---- - + # ALLOW_TO_FAILOVER, DISALLOW_TO_FAILOVER + # or ALWAYS_PRIMARY +--- 82,96 ---- + # - Backend Connection Settings - - + ! backend_hostname0 = 'localhost' # Host name or IP address to connect to for backend 0 ! backend_port0 = 5432 @@ -31,28 +31,22 @@ # Data directory for backend 0 ! backend_flag0 = 'ALLOW_TO_FAILOVER' # Controls various backend behavior - # ALLOW_TO_FAILOVER or DISALLOW_TO_FAILOVER - #backend_hostname1 = 'host2' + # ALLOW_TO_FAILOVER, DISALLOW_TO_FAILOVER + # or ALWAYS_PRIMARY *************** -*** 214,220 **** - pid_file_name = '/var/run/pgpool/pgpool.pid' - # PID file name - # Can be specified as relative to the" +*** 351,357 **** # location of pgpool.conf file or # as an absolute path # (change requires restart) -! logdir = '/tmp' - # Directory of pgPool status file +! #work_dir = '/tmp' + # Directory for pgpool_status and lock files. # (change requires restart) - ---- 214,220 ---- - pid_file_name = '/var/run/pgpool/pgpool.pid' - # PID file name - # Can be specified as relative to the" + +--- 351,357 ---- # location of pgpool.conf file or - # or as absolute path + # as an absolute path # (change requires restart) -! logdir = '/var/log/pgpool' - # Directory of pgPool status file +! work_dir = '/var/lib/pgpool' + # Directory for pgpool_status and lock files. # (change requires restart) diff --git a/src/redhat/pgpool_log.patch b/src/redhat/pgpool_log.patch index aaab1e8d7..198aa8fdd 100644 --- a/src/redhat/pgpool_log.patch +++ b/src/redhat/pgpool_log.patch @@ -1,7 +1,7 @@ -*** src/sample/pgpool.conf.sample 2022-02-10 12:49:15.079700949 +0900 ---- pgpool.conf.sample 2022-02-22 11:05:17.073517397 +0900 +*** src/sample/pgpool.conf.sample 2025-08-15 17:12:42.964631588 +0900 +--- pgpool.conf.sample 2025-08-15 17:17:21.762879829 +0900 *************** -*** 186,192 **** +*** 231,237 **** # - Where to log - @@ -9,7 +9,7 @@ # Where to log # Valid values are combinations of stderr, # and syslog. Default to stderr. ---- 186,192 ---- +--- 231,237 ---- # - Where to log - @@ -18,7 +18,7 @@ # Valid values are combinations of stderr, # and syslog. Default to stderr. *************** -*** 252,268 **** +*** 305,321 **** # panic # This is used when logging to stderr: @@ -36,7 +36,7 @@ # log file name pattern, # can include strftime() escapes ---- 252,268 ---- +--- 305,321 ---- # panic # This is used when logging to stderr: @@ -47,7 +47,7 @@ # -- Only used if logging_collector is on --- -! log_directory = '/var/log/pgpool_log' +! log_directory = '/var/log/pgpool' # directory where log files are written, # can be absolute ! log_filename = 'pgpool-%a.log' @@ -55,7 +55,7 @@ # can include strftime() escapes *************** -*** 270,276 **** +*** 323,329 **** # creation mode for log files, # begin with 0 to use octal notation @@ -63,7 +63,7 @@ # If on, an existing log file with the # same name as the new log file will be # truncated rather than appended to. ---- 270,276 ---- +--- 323,329 ---- # creation mode for log files, # begin with 0 to use octal notation @@ -72,7 +72,7 @@ # same name as the new log file will be # truncated rather than appended to. *************** -*** 280,290 **** +*** 333,343 **** # off, meaning append to existing files # in all cases. @@ -84,7 +84,7 @@ # Automatic rotation of logfiles will # happen after that much (KB) log output. # 0 disables size based rotation. ---- 280,290 ---- +--- 333,343 ---- # off, meaning append to existing files # in all cases. @@ -92,7 +92,7 @@ # Automatic rotation of logfiles will # happen after that (minutes)time. # 0 disables time based rotation. -! log_rotation_size = 0 +! log_rotation_size = 0 # Automatic rotation of logfiles will # happen after that much (KB) log output. # 0 disables size based rotation. diff --git a/src/redhat/pgpool_socket_dir.patch b/src/redhat/pgpool_socket_dir.patch index 40554ddda..de1101331 100644 --- a/src/redhat/pgpool_socket_dir.patch +++ b/src/redhat/pgpool_socket_dir.patch @@ -1,5 +1,5 @@ -*** src/sample/pgpool.conf.sample 2023-11-07 20:38:38.890984731 +0900 ---- pgpool.conf.sample 2023-11-09 13:22:19.179462724 +0900 +*** src/sample/pgpool.conf.sample 2025-08-15 11:18:51.825595514 +0900 +--- pgpool.conf.sample 2025-08-15 17:04:49.381908570 +0900 *************** *** 40,46 **** #port = 9999 @@ -35,7 +35,7 @@ # The Debian package defaults to # /var/run/postgresql *************** -*** 736,742 **** +*** 744,750 **** # Authentication key for watchdog communication # (change requires restart) @@ -43,7 +43,7 @@ # Unix domain socket path for watchdog IPC socket # The Debian package defaults to # /var/run/postgresql ---- 736,742 ---- +--- 744,750 ---- # Authentication key for watchdog communication # (change requires restart) diff --git a/src/rewrite/pool_timestamp.c b/src/rewrite/pool_timestamp.c index 01402bfa6..32de3f309 100644 --- a/src/rewrite/pool_timestamp.c +++ b/src/rewrite/pool_timestamp.c @@ -5,7 +5,7 @@ * pgpool: a language independent connection pool server for PostgreSQL * written by Tatsuo Ishii * - * Copyright (c) 2003-2023 PgPool Global Development Group + * Copyright (c) 2003-2025 PgPool Global Development Group * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby @@ -74,7 +74,8 @@ static char *get_current_timestamp(POOL_CONNECTION_POOL *backend); static Node *makeTsExpr(TSRewriteContext *ctx); static TypeCast *makeTypeCastFromSvfOp(SQLValueFunctionOp op); static A_Const *makeStringConstFromQuery(POOL_CONNECTION_POOL *backend, char *expression); -bool raw_expression_tree_walker(Node *node, bool (*walker) (), void *context); + +/* bool raw_expression_tree_walker(Node *node, walker, void *context); */ POOL_RELCACHE *ts_relcache; @@ -522,7 +523,7 @@ rewrite_timestamp_insert(InsertStmt *i_stmt, TSRewriteContext *ctx) rewrite_timestamp_walker, (void *) ctx); raw_expression_tree_walker( - (Node *) i_stmt->returningList, + (Node *) i_stmt->returningClause, rewrite_timestamp_walker, (void *) ctx); rewrite = ctx->rewrite; @@ -742,7 +743,7 @@ rewrite_timestamp_update(UpdateStmt *u_stmt, TSRewriteContext *ctx) rewrite_timestamp_walker, (void *) ctx); raw_expression_tree_walker( - (Node *) u_stmt->returningList, + (Node *) u_stmt->returningClause, rewrite_timestamp_walker, (void *) ctx); rewrite = ctx->rewrite; @@ -880,7 +881,7 @@ rewrite_timestamp(POOL_CONNECTION_POOL *backend, Node *node, rewrite_timestamp_walker, (void *) &ctx); raw_expression_tree_walker( - (Node *) d_stmt->returningList, + (Node *) d_stmt->returningClause, rewrite_timestamp_walker, (void *) &ctx); raw_expression_tree_walker( @@ -1370,9 +1371,10 @@ makeTypeCastFromSvfOp(SQLValueFunctionOp op) */ bool raw_expression_tree_walker(Node *node, - bool (*walker) (), + tree_walker_callback walker, void *context) { +#define WALK(n,c) walker((Node *) (n), c) ListCell *temp; /* @@ -1406,17 +1408,17 @@ raw_expression_tree_walker(Node *node, /* we assume the colnames list isn't interesting */ break; case T_RangeVar: - return walker(((RangeVar *) node)->alias, context); + return WALK(((RangeVar *) node)->alias, context); case T_GroupingFunc: - return walker(((GroupingFunc *) node)->args, context); + return WALK(((GroupingFunc *) node)->args, context); case T_SubLink: { SubLink *sublink = (SubLink *) node; - if (walker(sublink->testexpr, context)) + if (WALK(sublink->testexpr, context)) return true; /* we assume the operName is not interesting */ - if (walker(sublink->subselect, context)) + if (WALK(sublink->subselect, context)) return true; } break; @@ -1424,7 +1426,7 @@ raw_expression_tree_walker(Node *node, { CaseExpr *caseexpr = (CaseExpr *) node; - if (walker(caseexpr->arg, context)) + if (WALK(caseexpr->arg, context)) return true; /* we assume walker doesn't care about CaseWhens, either */ foreach(temp, caseexpr->args) @@ -1432,48 +1434,48 @@ raw_expression_tree_walker(Node *node, CaseWhen *when = (CaseWhen *) lfirst(temp); Assert(IsA(when, CaseWhen)); - if (walker(when->expr, context)) + if (WALK(when->expr, context)) return true; - if (walker(when->result, context)) + if (WALK(when->result, context)) return true; } - if (walker(caseexpr->defresult, context)) + if (WALK(caseexpr->defresult, context)) return true; } break; case T_RowExpr: /* Assume colnames isn't interesting */ - return walker(((RowExpr *) node)->args, context); + return WALK(((RowExpr *) node)->args, context); case T_CoalesceExpr: - return walker(((CoalesceExpr *) node)->args, context); + return WALK(((CoalesceExpr *) node)->args, context); case T_MinMaxExpr: - return walker(((MinMaxExpr *) node)->args, context); + return WALK(((MinMaxExpr *) node)->args, context); case T_XmlExpr: { XmlExpr *xexpr = (XmlExpr *) node; - if (walker(xexpr->named_args, context)) + if (WALK(xexpr->named_args, context)) return true; /* we assume walker doesn't care about arg_names */ - if (walker(xexpr->args, context)) + if (WALK(xexpr->args, context)) return true; } break; case T_NullTest: - return walker(((NullTest *) node)->arg, context); + return WALK(((NullTest *) node)->arg, context); case T_BooleanTest: - return walker(((BooleanTest *) node)->arg, context); + return WALK(((BooleanTest *) node)->arg, context); case T_JoinExpr: { JoinExpr *join = (JoinExpr *) node; - if (walker(join->larg, context)) + if (WALK(join->larg, context)) return true; - if (walker(join->rarg, context)) + if (WALK(join->rarg, context)) return true; - if (walker(join->quals, context)) + if (WALK(join->quals, context)) return true; - if (walker(join->alias, context)) + if (WALK(join->alias, context)) return true; /* using list is deemed uninteresting */ } @@ -1482,18 +1484,18 @@ raw_expression_tree_walker(Node *node, { IntoClause *into = (IntoClause *) node; - if (walker(into->rel, context)) + if (WALK(into->rel, context)) return true; /* colNames, options are deemed uninteresting */ /* viewQuery should be null in raw parsetree, but check it */ - if (walker(into->viewQuery, context)) + if (WALK(into->viewQuery, context)) return true; } break; case T_List: foreach(temp, (List *) node) { - if (walker((Node *) lfirst(temp), context)) + if (WALK((Node *) lfirst(temp), context)) return true; } break; @@ -1501,11 +1503,11 @@ raw_expression_tree_walker(Node *node, { MergeWhenClause *mergeWhenClause = (MergeWhenClause *) node; - if (walker(mergeWhenClause->condition, context)) + if (WALK(mergeWhenClause->condition, context)) return true; - if (walker(mergeWhenClause->targetList, context)) + if (WALK(mergeWhenClause->targetList, context)) return true; - if (walker(mergeWhenClause->values, context)) + if (WALK(mergeWhenClause->values, context)) return true; } break; @@ -1513,9 +1515,9 @@ raw_expression_tree_walker(Node *node, { MergeAction *action = (MergeAction *) node; - if (walker(action->targetList, context)) + if (WALK(action->targetList, context)) return true; - if (walker(action->qual, context)) + if (WALK(action->qual, context)) return true; } break; @@ -1523,17 +1525,17 @@ raw_expression_tree_walker(Node *node, { InsertStmt *stmt = (InsertStmt *) node; - if (walker(stmt->relation, context)) + if (WALK(stmt->relation, context)) return true; - if (walker(stmt->cols, context)) + if (WALK(stmt->cols, context)) return true; - if (walker(stmt->selectStmt, context)) + if (WALK(stmt->selectStmt, context)) return true; - if (walker(stmt->onConflictClause, context)) + if (WALK(stmt->onConflictClause, context)) return true; - if (walker(stmt->returningList, context)) + if (WALK(stmt->returningClause, context)) return true; - if (walker(stmt->withClause, context)) + if (WALK(stmt->withClause, context)) return true; } break; @@ -1541,15 +1543,15 @@ raw_expression_tree_walker(Node *node, { DeleteStmt *stmt = (DeleteStmt *) node; - if (walker(stmt->relation, context)) + if (WALK(stmt->relation, context)) return true; - if (walker(stmt->usingClause, context)) + if (WALK(stmt->usingClause, context)) return true; - if (walker(stmt->whereClause, context)) + if (WALK(stmt->whereClause, context)) return true; - if (walker(stmt->returningList, context)) + if (WALK(stmt->returningClause, context)) return true; - if (walker(stmt->withClause, context)) + if (WALK(stmt->withClause, context)) return true; } break; @@ -1557,17 +1559,17 @@ raw_expression_tree_walker(Node *node, { UpdateStmt *stmt = (UpdateStmt *) node; - if (walker(stmt->relation, context)) + if (WALK(stmt->relation, context)) return true; - if (walker(stmt->targetList, context)) + if (WALK(stmt->targetList, context)) return true; - if (walker(stmt->whereClause, context)) + if (WALK(stmt->whereClause, context)) return true; - if (walker(stmt->fromClause, context)) + if (WALK(stmt->fromClause, context)) return true; - if (walker(stmt->returningList, context)) + if (WALK(stmt->returningClause, context)) return true; - if (walker(stmt->withClause, context)) + if (WALK(stmt->withClause, context)) return true; } break; @@ -1575,37 +1577,37 @@ raw_expression_tree_walker(Node *node, { SelectStmt *stmt = (SelectStmt *) node; - if (walker(stmt->distinctClause, context)) + if (WALK(stmt->distinctClause, context)) return true; - if (walker(stmt->intoClause, context)) + if (WALK(stmt->intoClause, context)) return true; - if (walker(stmt->targetList, context)) + if (WALK(stmt->targetList, context)) return true; - if (walker(stmt->fromClause, context)) + if (WALK(stmt->fromClause, context)) return true; - if (walker(stmt->whereClause, context)) + if (WALK(stmt->whereClause, context)) return true; - if (walker(stmt->groupClause, context)) + if (WALK(stmt->groupClause, context)) return true; - if (walker(stmt->havingClause, context)) + if (WALK(stmt->havingClause, context)) return true; - if (walker(stmt->windowClause, context)) + if (WALK(stmt->windowClause, context)) return true; - if (walker(stmt->valuesLists, context)) + if (WALK(stmt->valuesLists, context)) return true; - if (walker(stmt->sortClause, context)) + if (WALK(stmt->sortClause, context)) return true; - if (walker(stmt->limitOffset, context)) + if (WALK(stmt->limitOffset, context)) return true; - if (walker(stmt->limitCount, context)) + if (WALK(stmt->limitCount, context)) return true; - if (walker(stmt->lockingClause, context)) + if (WALK(stmt->lockingClause, context)) return true; - if (walker(stmt->withClause, context)) + if (WALK(stmt->withClause, context)) return true; - if (walker(stmt->larg, context)) + if (WALK(stmt->larg, context)) return true; - if (walker(stmt->rarg, context)) + if (WALK(stmt->rarg, context)) return true; } break; @@ -1613,9 +1615,9 @@ raw_expression_tree_walker(Node *node, { A_Expr *expr = (A_Expr *) node; - if (walker(expr->lexpr, context)) + if (WALK(expr->lexpr, context)) return true; - if (walker(expr->rexpr, context)) + if (WALK(expr->rexpr, context)) return true; /* operator name is deemed uninteresting */ } @@ -1624,7 +1626,7 @@ raw_expression_tree_walker(Node *node, { BoolExpr *expr = (BoolExpr *) node; - if (walker(expr->args, context)) + if (WALK(expr->args, context)) return true; } break; @@ -1635,26 +1637,26 @@ raw_expression_tree_walker(Node *node, { FuncCall *fcall = (FuncCall *) node; - if (walker(fcall->args, context)) + if (WALK(fcall->args, context)) return true; - if (walker(fcall->agg_order, context)) + if (WALK(fcall->agg_order, context)) return true; - if (walker(fcall->agg_filter, context)) + if (WALK(fcall->agg_filter, context)) return true; - if (walker(fcall->over, context)) + if (WALK(fcall->over, context)) return true; /* function name is deemed uninteresting */ } break; case T_NamedArgExpr: - return walker(((NamedArgExpr *) node)->arg, context); + return WALK(((NamedArgExpr *) node)->arg, context); case T_A_Indices: { A_Indices *indices = (A_Indices *) node; - if (walker(indices->lidx, context)) + if (WALK(indices->lidx, context)) return true; - if (walker(indices->uidx, context)) + if (WALK(indices->uidx, context)) return true; } break; @@ -1662,51 +1664,51 @@ raw_expression_tree_walker(Node *node, { A_Indirection *indir = (A_Indirection *) node; - if (walker(indir->arg, context)) + if (WALK(indir->arg, context)) return true; - if (walker(indir->indirection, context)) + if (WALK(indir->indirection, context)) return true; } break; case T_A_ArrayExpr: - return walker(((A_ArrayExpr *) node)->elements, context); + return WALK(((A_ArrayExpr *) node)->elements, context); case T_ResTarget: { ResTarget *rt = (ResTarget *) node; - if (walker(rt->indirection, context)) + if (WALK(rt->indirection, context)) return true; - if (walker(rt->val, context)) + if (WALK(rt->val, context)) return true; } break; case T_MultiAssignRef: - return walker(((MultiAssignRef *) node)->source, context); + return WALK(((MultiAssignRef *) node)->source, context); case T_TypeCast: { TypeCast *tc = (TypeCast *) node; - if (walker(tc->arg, context)) + if (WALK(tc->arg, context)) return true; - if (walker(tc->typeName, context)) + if (WALK(tc->typeName, context)) return true; } break; case T_CollateClause: - return walker(((CollateClause *) node)->arg, context); + return WALK(((CollateClause *) node)->arg, context); case T_SortBy: - return walker(((SortBy *) node)->node, context); + return WALK(((SortBy *) node)->node, context); case T_WindowDef: { WindowDef *wd = (WindowDef *) node; - if (walker(wd->partitionClause, context)) + if (WALK(wd->partitionClause, context)) return true; - if (walker(wd->orderClause, context)) + if (WALK(wd->orderClause, context)) return true; - if (walker(wd->startOffset, context)) + if (WALK(wd->startOffset, context)) return true; - if (walker(wd->endOffset, context)) + if (WALK(wd->endOffset, context)) return true; } break; @@ -1714,9 +1716,9 @@ raw_expression_tree_walker(Node *node, { RangeSubselect *rs = (RangeSubselect *) node; - if (walker(rs->subquery, context)) + if (WALK(rs->subquery, context)) return true; - if (walker(rs->alias, context)) + if (WALK(rs->alias, context)) return true; } break; @@ -1724,11 +1726,11 @@ raw_expression_tree_walker(Node *node, { RangeFunction *rf = (RangeFunction *) node; - if (walker(rf->functions, context)) + if (WALK(rf->functions, context)) return true; - if (walker(rf->alias, context)) + if (WALK(rf->alias, context)) return true; - if (walker(rf->coldeflist, context)) + if (WALK(rf->coldeflist, context)) return true; } break; @@ -1736,12 +1738,12 @@ raw_expression_tree_walker(Node *node, { RangeTableSample *rts = (RangeTableSample *) node; - if (walker(rts->relation, context)) + if (WALK(rts->relation, context)) return true; /* method name is deemed uninteresting */ - if (walker(rts->args, context)) + if (WALK(rts->args, context)) return true; - if (walker(rts->repeatable, context)) + if (WALK(rts->repeatable, context)) return true; } break; @@ -1749,9 +1751,9 @@ raw_expression_tree_walker(Node *node, { TypeName *tn = (TypeName *) node; - if (walker(tn->typmods, context)) + if (WALK(tn->typmods, context)) return true; - if (walker(tn->arrayBounds, context)) + if (WALK(tn->arrayBounds, context)) return true; /* type name itself is deemed uninteresting */ } @@ -1760,38 +1762,38 @@ raw_expression_tree_walker(Node *node, { ColumnDef *coldef = (ColumnDef *) node; - if (walker(coldef->typeName, context)) + if (WALK(coldef->typeName, context)) return true; - if (walker(coldef->raw_default, context)) + if (WALK(coldef->raw_default, context)) return true; - if (walker(coldef->collClause, context)) + if (WALK(coldef->collClause, context)) return true; /* for now, constraints are ignored */ } break; case T_GroupingSet: - return walker(((GroupingSet *) node)->content, context); + return WALK(((GroupingSet *) node)->content, context); case T_LockingClause: - return walker(((LockingClause *) node)->lockedRels, context); + return WALK(((LockingClause *) node)->lockedRels, context); case T_XmlSerialize: { XmlSerialize *xs = (XmlSerialize *) node; - if (walker(xs->expr, context)) + if (WALK(xs->expr, context)) return true; - if (walker(xs->typeName, context)) + if (WALK(xs->typeName, context)) return true; } break; case T_WithClause: - return walker(((WithClause *) node)->ctes, context); + return WALK(((WithClause *) node)->ctes, context); case T_InferClause: { InferClause *stmt = (InferClause *) node; - if (walker(stmt->indexElems, context)) + if (WALK(stmt->indexElems, context)) return true; - if (walker(stmt->whereClause, context)) + if (WALK(stmt->whereClause, context)) return true; } break; @@ -1799,16 +1801,16 @@ raw_expression_tree_walker(Node *node, { OnConflictClause *stmt = (OnConflictClause *) node; - if (walker(stmt->infer, context)) + if (WALK(stmt->infer, context)) return true; - if (walker(stmt->targetList, context)) + if (WALK(stmt->targetList, context)) return true; - if (walker(stmt->whereClause, context)) + if (WALK(stmt->whereClause, context)) return true; } break; case T_CommonTableExpr: - return walker(((CommonTableExpr *) node)->ctequery, context); + return WALK(((CommonTableExpr *) node)->ctequery, context); default: /* diff --git a/src/sample/pgpool.conf.sample-stream b/src/sample/pgpool.conf.sample-stream index bec929dcd..797906491 100644 --- a/src/sample/pgpool.conf.sample-stream +++ b/src/sample/pgpool.conf.sample-stream @@ -1,5 +1,5 @@ # -------------------------------- -# Pgpool-II 4.7 configuration file +# Pgpool-II 4.8 configuration file # -------------------------------- # # This file consists of lines of the form: @@ -20,7 +20,7 @@ #------------------------------------------------------------------------------ # BACKEND CLUSTERING MODE # Choose one of: streaming_replication, native_replication, -# logical_replication, slony, raw or snapshot_isolation +# logical_replication, raw or snapshot_isolation # (change requires restart) #------------------------------------------------------------------------------ @@ -244,7 +244,7 @@ backend_clustering_mode = streaming_replication # Log connections #log_disconnections = off # Log disconnections -#log_pcp_processes = on +#log_pcp_processes = off # Log PCP Processes #log_hostname = off # Hostname will be shown in ps status @@ -351,8 +351,8 @@ backend_clustering_mode = streaming_replication # location of pgpool.conf file or # as an absolute path # (change requires restart) -#logdir = '/tmp' - # Directory of pgPool status file +#work_dir = '/tmp' + # Directory for pgpool_status and lock files. # (change requires restart) diff --git a/src/sample/scripts/recovery_1st_stage.sample b/src/sample/scripts/recovery_1st_stage.sample index f62500f47..9cbe33c8a 100755 --- a/src/sample/scripts/recovery_1st_stage.sample +++ b/src/sample/scripts/recovery_1st_stage.sample @@ -49,7 +49,7 @@ ssh -T ${SSH_OPTIONS} ${POSTGRESQL_STARTUP_USER}@$DEST_NODE_HOST " set -o errexit - [ -d \"${DEST_NODE_PGDATA}\" ] && rm -rf ${DEST_NODE_PGDATA} + [ -d \"${DEST_NODE_PGDATA}\" ] && rm -rf \"${DEST_NODE_PGDATA}\" ${PGHOME}/bin/pg_basebackup -h $PRIMARY_NODE_HOST -U $REPLUSER -p $PRIMARY_NODE_PORT -D $DEST_NODE_PGDATA -X stream diff --git a/src/sql/pgpool_adm/Makefile b/src/sql/pgpool_adm/Makefile index 6dde6ccf6..ce996da8d 100644 --- a/src/sql/pgpool_adm/Makefile +++ b/src/sql/pgpool_adm/Makefile @@ -10,7 +10,7 @@ pgpool_adm--1.0--1.1.sql pgpool_adm--1.1--1.2.sql pgpool_adm--1.2--1.3.sql \ pgpool_adm--1.4.sql pgpool_adm--1.3--1.4.sql \ pgpool_adm--1.5.sql pgpool_adm--1.4--1.5.sql \ pgpool_adm--1.6.sql pgpool_adm--1.5--1.6.sql -SHLIB_LINK = -L../../libs/pcp/.libs -lpcp -Wl,--as-needed -Wl,-rpath,'${prefix}/lib',--enable-new-dtags +SHLIB_LINK = -L../../libs/pcp/.libs -lpcp # if you are using PostgreSQL 8.0 or later, # using pg_config is recommended. # if you are not, comment out following line and... diff --git a/src/streaming_replication/pool_worker_child.c b/src/streaming_replication/pool_worker_child.c index 4f8f823a3..5bf19c37d 100644 --- a/src/streaming_replication/pool_worker_child.c +++ b/src/streaming_replication/pool_worker_child.c @@ -106,7 +106,7 @@ static volatile bool follow_primary_lock_acquired; * worker child main loop */ void -do_worker_child(void) +do_worker_child(void *params) { sigjmp_buf local_sigjmp_buf; MemoryContext WorkerMemoryContext; diff --git a/src/test/pgpool_setup.in b/src/test/pgpool_setup.in index 926b8f8ac..51054ee87 100644 --- a/src/test/pgpool_setup.in +++ b/src/test/pgpool_setup.in @@ -23,7 +23,6 @@ # -m r: create an installation as native replication mode. # -m n: create an installation as raw mode. # -m l: create an installation as logical replication mode. -# -m y: create an installation as slony mode. # -m i: create an installation as snapshot isolation mode. # -n num_clusters: create num_clusters PostgreSQL database cluster nodes # -p base_port: specify base port. pgpool port is base_port. @@ -126,7 +125,7 @@ vstr=`$INITDB -V|awk '{print $3}'|sed 's/\./ /g'` #vstr="11.1" # check if alpha or beta -echo $vstr|egrep "[a-z]" > /dev/null +echo $vstr|grep -E "[a-z]" > /dev/null if [ $? = 0 ];then vstr=`echo $vstr|sed 's/\([0-9]*\).*/\1/'` major1=`echo $vstr|awk '{print $1}'` @@ -1171,7 +1170,7 @@ EOF ################################################################################ function usage() { - echo "usage: $0 [-m r|s|n|l|y|i] [-n num_clusters] [-p base_port] [-pg pg_base_port][--no-stop] [-d] [-s] [-r] [-e] [-t] [-c]";exit 1 + echo "usage: $0 [-m r|s|n|l|i] [-n num_clusters] [-p base_port] [-pg pg_base_port][--no-stop] [-d] [-s] [-r] [-e] [-t] [-c]";exit 1 } #------------------------------------------- @@ -1195,7 +1194,6 @@ do s ) MODE="s";; n ) MODE="n";; l ) MODE="l";; - y ) MODE="y";; i ) MODE="i";; * ) usage;; esac @@ -1247,9 +1245,6 @@ case $MODE in l ) MODENAME="logical replication mode" CLUSTERING_MODE_STR="logical_replication" ;; - y ) MODENAME="slony mode" - CLUSTERING_MODE_STR="slony" - ;; i ) MODENAME="snapshot isolation mode" CLUSTERING_MODE_STR="snapshot_isolation" ;; @@ -1380,7 +1375,7 @@ chmod 0600 $PCP_PASS_FILE test ! -d run && mkdir run echo "pid_file_name = '$BASEDIR/run/pgpool.pid'" >> $CONF test ! -d log && mkdir log -echo "logdir = '$BASEDIR/log'" >> $CONF +echo "work_dir = '$BASEDIR/log'" >> $CONF if [ "$PGPOOLDEBUG" = "true" ];then echo '$PGPOOL_INSTALL_DIR/bin/pgpool -d -D -n -f $dir/etc/pgpool.conf -F $dir/etc/pcp.conf -a $dir/etc/pool_hba.conf 2>&1 | cat > $dir/log/pgpool.log &' >> $STARTALL diff --git a/src/test/regression/regress.sh b/src/test/regression/regress.sh index c192a385e..a0a98b1a1 100755 --- a/src/test/regression/regress.sh +++ b/src/test/regression/regress.sh @@ -204,6 +204,10 @@ fi for i in $dirs do + # skip if it's not a directory + if [ ! -d $i ];then + continue; + fi cd $i # skip the test if there's no test.sh diff --git a/src/test/regression/tests/010.rewrite_timestamp/timestamp/main.c b/src/test/regression/tests/010.rewrite_timestamp/timestamp/main.c index 917ca8803..da5b9b70c 100644 --- a/src/test/regression/tests/010.rewrite_timestamp/timestamp/main.c +++ b/src/test/regression/tests/010.rewrite_timestamp/timestamp/main.c @@ -90,7 +90,9 @@ Pgversion(POOL_CONNECTION_POOL *backend) } POOL_RELCACHE * -pool_create_relcache(int cachesize, char *sql, func_ptr register_func, func_ptr unregister_func, bool issessionlocal) +pool_create_relcache(int cachesize, char *sql, + void *(*register_func) (), void *(*unregister_func) (), + bool issessionlocal) { return (POOL_RELCACHE *) 1; } diff --git a/src/test/regression/tests/010.rewrite_timestamp/timestamp/run-test b/src/test/regression/tests/010.rewrite_timestamp/timestamp/run-test index 9b1a6e293..d81102f3b 100755 --- a/src/test/regression/tests/010.rewrite_timestamp/timestamp/run-test +++ b/src/test/regression/tests/010.rewrite_timestamp/timestamp/run-test @@ -23,12 +23,12 @@ if ARGV.size != 1 end file = ARGV.shift -if !(File.exists? file) +if !(File.exist? file) STDERR.puts "run-test: file does not exist: #{file}" exit 1 end -if !(File.exists? RESULT_DIRECTORY) +if !(File.exist? RESULT_DIRECTORY) Dir.mkdir RESULT_DIRECTORY else Dir["#{RESULT_DIRECTORY}/*.out"].each do |f| @@ -36,7 +36,7 @@ else end end -File.unlink DIFF_FILE if File.exists? DIFF_FILE +File.unlink DIFF_FILE if File.exist? DIFF_FILE begin IO.foreach(file) do |testcase| diff --git a/src/test/regression/tests/011.watchdog_quorum_failover/test.sh b/src/test/regression/tests/011.watchdog_quorum_failover/test.sh index 9a5830617..2958d5e17 100755 --- a/src/test/regression/tests/011.watchdog_quorum_failover/test.sh +++ b/src/test/regression/tests/011.watchdog_quorum_failover/test.sh @@ -57,7 +57,7 @@ echo -n "creating standby pgpool..." cat standby.conf >> $STANDBY_DIR/etc/pgpool.conf # since we are using the same pgpool-II conf as of leader. so change the pid file path in standby pgpool conf echo "pid_file_name = '$PWD/pgpool2.pid'" >> $STANDBY_DIR/etc/pgpool.conf -echo "logdir = $STANDBY_DIR/log" >> $STANDBY_DIR/etc/pgpool.conf +echo "work_dir = $STANDBY_DIR/log" >> $STANDBY_DIR/etc/pgpool.conf echo 1 > $STANDBY_DIR/etc/pgpool_node_id # start the standby pgpool-II by hand $PGPOOL_INSTALL_DIR/bin/pgpool -D -n -f $STANDBY_DIR/etc/pgpool.conf -F $STANDBY_DIR/etc/pcp.conf -a $STANDBY_DIR/etc/pool_hba.conf > $STANDBY_DIR/log/pgpool.log 2>&1 & @@ -69,7 +69,7 @@ echo -n "creating standby2 pgpool..." cat standby2.conf >> $STANDBY2_DIR/etc/pgpool.conf # since we are using the same pgpool-II conf as of leader. so change the pid file path in standby pgpool conf echo "pid_file_name = '$PWD/pgpool3.pid'" >> $STANDBY2_DIR/etc/pgpool.conf -echo "logdir = $STANDBY2_DIR/log" >> $STANDBY2_DIR/etc/pgpool.conf +echo "work_dir = $STANDBY2_DIR/log" >> $STANDBY2_DIR/etc/pgpool.conf echo 2 > $STANDBY2_DIR/etc/pgpool_node_id # start the standby pgpool-II by hand $PGPOOL_INSTALL_DIR/bin/pgpool -D -n -f $STANDBY2_DIR/etc/pgpool.conf -F $STANDBY2_DIR/etc/pcp.conf -a $STANDBY2_DIR/etc/pool_hba.conf > $STANDBY2_DIR/log/pgpool.log 2>&1 & diff --git a/src/test/regression/tests/012.watchdog_failover_when_quorum_exists/test.sh b/src/test/regression/tests/012.watchdog_failover_when_quorum_exists/test.sh index ccccb86c6..e14e18134 100755 --- a/src/test/regression/tests/012.watchdog_failover_when_quorum_exists/test.sh +++ b/src/test/regression/tests/012.watchdog_failover_when_quorum_exists/test.sh @@ -59,7 +59,7 @@ echo -n "creating standby pgpool..." cat standby.conf >> $STANDBY_DIR/etc/pgpool.conf # since we are using the same pgpool-II conf as of leader. so change the pid file path in standby pgpool conf echo "pid_file_name = '$PWD/pgpool2.pid'" >> $STANDBY_DIR/etc/pgpool.conf -echo "logdir = $STANDBY_DIR/log" >> $STANDBY_DIR/etc/pgpool.conf +echo "work_dir = $STANDBY_DIR/log" >> $STANDBY_DIR/etc/pgpool.conf echo 1 > $STANDBY_DIR/etc/pgpool_node_id # start the standby pgpool-II by hand #$PGPOOL_INSTALL_DIR/bin/pgpool -D -n -f $STANDBY_DIR/etc/pgpool.conf -F $STANDBY_DIR/etc/pcp.conf -a $STANDBY_DIR/etc/pool_hba.conf > $STANDBY_DIR/log/pgpool.log 2>&1 & @@ -71,7 +71,7 @@ echo -n "creating standby2 pgpool..." cat standby2.conf >> $STANDBY2_DIR/etc/pgpool.conf # since we are using the same pgpool-II conf as of leader. so change the pid file path in standby pgpool conf echo "pid_file_name = '$PWD/pgpool3.pid'" >> $STANDBY2_DIR/etc/pgpool.conf -echo "logdir = $STANDBY2_DIR/log" >> $STANDBY2_DIR/etc/pgpool.conf +echo "work_dir = $STANDBY2_DIR/log" >> $STANDBY2_DIR/etc/pgpool.conf echo 2 > $STANDBY2_DIR/etc/pgpool_node_id # start the standby pgpool-II by hand #$PGPOOL_INSTALL_DIR/bin/pgpool -D -n -f $STANDBY2_DIR/etc/pgpool.conf -F $STANDBY2_DIR/etc/pcp.conf -a $STANDBY2_DIR/etc/pool_hba.conf > $STANDBY2_DIR/log/pgpool.log 2>&1 & diff --git a/src/test/regression/tests/013.watchdog_failover_require_consensus/test.sh b/src/test/regression/tests/013.watchdog_failover_require_consensus/test.sh index d74a827e9..b51af66a3 100755 --- a/src/test/regression/tests/013.watchdog_failover_require_consensus/test.sh +++ b/src/test/regression/tests/013.watchdog_failover_require_consensus/test.sh @@ -59,7 +59,7 @@ echo -n "creating standby pgpool..." cat standby.conf >> $STANDBY_DIR/etc/pgpool.conf # since we are using the same pgpool-II conf as of leader. so change the pid file path in standby pgpool conf echo "pid_file_name = '$PWD/pgpool2.pid'" >> $STANDBY_DIR/etc/pgpool.conf -echo "logdir = $STANDBY_DIR/log" >> $STANDBY_DIR/etc/pgpool.conf +echo "work_dir = $STANDBY_DIR/log" >> $STANDBY_DIR/etc/pgpool.conf echo 1 > $STANDBY_DIR/etc/pgpool_node_id # start the standby pgpool-II by hand $PGPOOL_INSTALL_DIR/bin/pgpool -D -n -f $STANDBY_DIR/etc/pgpool.conf -F $STANDBY_DIR/etc/pcp.conf -a $STANDBY_DIR/etc/pool_hba.conf > $STANDBY_DIR/log/pgpool.log 2>&1 & @@ -70,7 +70,7 @@ echo -n "creating standby2 pgpool..." cat standby2.conf >> $STANDBY2_DIR/etc/pgpool.conf # since we are using the same pgpool-II conf as of leader. so change the pid file path in standby pgpool conf echo "pid_file_name = '$PWD/pgpool3.pid'" >> $STANDBY2_DIR/etc/pgpool.conf -echo "logdir = $STANDBY2_DIR/log" >> $STANDBY2_DIR/etc/pgpool.conf +echo "work_dir = $STANDBY2_DIR/log" >> $STANDBY2_DIR/etc/pgpool.conf echo 2 > $STANDBY2_DIR/etc/pgpool_node_id # start the standby pgpool-II by hand $PGPOOL_INSTALL_DIR/bin/pgpool -D -n -f $STANDBY2_DIR/etc/pgpool.conf -F $STANDBY2_DIR/etc/pcp.conf -a $STANDBY2_DIR/etc/pool_hba.conf > $STANDBY2_DIR/log/pgpool.log 2>&1 & diff --git a/src/test/regression/tests/015.watchdog_master_and_backend_fail/test.sh b/src/test/regression/tests/015.watchdog_master_and_backend_fail/test.sh index 3b517a98d..f0dad0766 100755 --- a/src/test/regression/tests/015.watchdog_master_and_backend_fail/test.sh +++ b/src/test/regression/tests/015.watchdog_master_and_backend_fail/test.sh @@ -59,7 +59,7 @@ echo -n "creating standby pgpool..." cat standby.conf >> $STANDBY_DIR/etc/pgpool.conf # since we are using the same pgpool-II conf as of leader. so change the pid file path in standby pgpool conf echo "pid_file_name = '$PWD/pgpool2.pid'" >> $STANDBY_DIR/etc/pgpool.conf -echo "logdir = $STANDBY_DIR/log" >> $STANDBY_DIR/etc/pgpool.conf +echo "work_dir = $STANDBY_DIR/log" >> $STANDBY_DIR/etc/pgpool.conf echo 1 > $STANDBY_DIR/etc/pgpool_node_id # start the standby pgpool-II by hand $PGPOOL_INSTALL_DIR/bin/pgpool -D -n -f $STANDBY_DIR/etc/pgpool.conf -F $STANDBY_DIR/etc/pcp.conf -a $STANDBY_DIR/etc/pool_hba.conf > $STANDBY_DIR/log/pgpool.log 2>&1 & @@ -70,7 +70,7 @@ echo -n "creating standby2 pgpool..." cat standby2.conf >> $STANDBY2_DIR/etc/pgpool.conf # since we are using the same pgpool-II conf as of leader. so change the pid file path in standby pgpool conf echo "pid_file_name = '$PWD/pgpool3.pid'" >> $STANDBY2_DIR/etc/pgpool.conf -echo "logdir = $STANDBY2_DIR/log" >> $STANDBY2_DIR/etc/pgpool.conf +echo "work_dir = $STANDBY2_DIR/log" >> $STANDBY2_DIR/etc/pgpool.conf echo 2 > $STANDBY2_DIR/etc/pgpool_node_id # start the standby pgpool-II by hand $PGPOOL_INSTALL_DIR/bin/pgpool -D -n -f $STANDBY2_DIR/etc/pgpool.conf -F $STANDBY2_DIR/etc/pcp.conf -a $STANDBY2_DIR/etc/pool_hba.conf > $STANDBY2_DIR/log/pgpool.log 2>&1 & diff --git a/src/test/regression/tests/023.ssl_connection/test.sh b/src/test/regression/tests/023.ssl_connection/test.sh index 17e375339..2b5f3b693 100755 --- a/src/test/regression/tests/023.ssl_connection/test.sh +++ b/src/test/regression/tests/023.ssl_connection/test.sh @@ -65,7 +65,13 @@ $PSQL -h localhost test <<EOF > result \q EOF -grep SSL result +# PostgreSQL 18 or later prints tablular output for \conninfo. +# For SSL, "SSL Connection | true (or false)" +if [ $PGVERSION -ge 18 ];then + grep "SSL Connection" result|grep true +else + grep SSL result +fi if [ $? != 0 ];then echo "Checking SSL connection between frontend and Pgpool-II failed." @@ -75,7 +81,11 @@ fi echo "Checking SSL connection between frontend and Pgpool-II was ok." -grep SSL result |grep TLSv1.2 +if [ $PGVERSION -ge 18 ];then + grep "SSL Protocol" result|grep TLSv1.2 +else + grep SSL result |grep TLSv1.2 +fi # if SSl protocol version TLSv1.2 if [ $? = 0 ];then @@ -99,4 +109,53 @@ fi echo "Checking SSL connection between Pgpool-II and backend was ok." ./shutdownall + +# Checking ssl_ecdh_curve. Set bad value to see if SSL connection fails. +echo "ssl_ecdh_curve = 'badcurve'" >> etc/pgpool.conf + +./startall +wait_for_pgpool_startup + +$PSQL -h localhost test <<EOF > result +\conninfo +\q +EOF + +if [ $PGVERSION -ge 18 ];then + grep "SSL Connection" result|grep true +else + grep SSL result +fi + +if [ $? = 0 ];then + echo "Checking SSL connection between frontend and Pgpool-II succeeded despite bad ssl_ecdh_curve." + ./shutdownall + exit 1 +fi + +echo "Checking SSL connection between frontend and Pgpool-II failed due to bad ssl_ecdh_curve as expected." +./shutdownall + +# Make sure that SSL connection succeeds with good ssl_ecdh_curve +echo "ssl_ecdh_curve = 'prime256v1'" >> etc/pgpool.conf + +./startall +wait_for_pgpool_startup + +$PSQL -h localhost test <<EOF > result +\conninfo +\q +EOF + +grep SSL result + +if [ $? = 0 ];then + echo "Checking SSL connection between frontend and Pgpool-II succeeded with good ssl_ecdh_curve." + ./shutdownall +else + echo "Checking SSL connection between frontend and Pgpool-II failed with good ssl_ecdh_curve." + ./shutdownall + exit 1 +fi + exit 0 diff --git a/src/test/regression/tests/034.promote_node/test.sh b/src/test/regression/tests/034.promote_node/test.sh index 547e97821..07f35e46b 100755 --- a/src/test/regression/tests/034.promote_node/test.sh +++ b/src/test/regression/tests/034.promote_node/test.sh @@ -38,7 +38,7 @@ wait_for_pgpool_startup # check to see if alll nodes are up echo -n "starting to check follow primary results: " date -cnt=60 +cnt=120 while [ $cnt -gt 0 ] do # check to see if primary is now node 3 diff --git a/src/test/regression/tests/037.failover_session/test.sh b/src/test/regression/tests/037.failover_session/test.sh index b75377140..7fc9845d8 100755 --- a/src/test/regression/tests/037.failover_session/test.sh +++ b/src/test/regression/tests/037.failover_session/test.sh @@ -60,6 +60,8 @@ else echo "pgbench suceeded. test1 ok." r1=ok fi +# give pgpool chance to complete the failover +sleep 5 ./shutdownall echo "=== test2: backend_weight2 = 0 and pgbench with -C option" diff --git a/src/test/regression/tests/039.log_backend_messages/test.sh b/src/test/regression/tests/039.log_backend_messages/test.sh index d89ba5494..6fe672e46 100755 --- a/src/test/regression/tests/039.log_backend_messages/test.sh +++ b/src/test/regression/tests/039.log_backend_messages/test.sh @@ -23,17 +23,25 @@ do echo > result - # We set backend_weight0 to 0 to send ready queries to backend 1. + # We set backend_weight0 to send read queries to backend 1. # We set client_min_messages to log so that log messages appear on # the client screen. # We set connection_cache to off so that each time client connects # to pgpool, it receives ready for query from backend. + # We set synchronous_commit = remote_apply, and synchronous_standby_names = 'server1' + # in streaming replication mode so that updation to primary is replicated to standby with no lag. cat >> etc/pgpool.conf <<EOF backend_weight0 = 0 client_min_messages = log log_per_node_statement = off connection_cache = off EOF + if [ $mode = "s" ];then + cat >> data0/postgresql.conf <<EOF +synchronous_commit = remote_apply +synchronous_standby_names = 'server1' +EOF + fi for option in none terse verbose do echo "==== mode: $mode option: $option ===" >> result diff --git a/src/test/regression/tests/040.client_auth/test.sh b/src/test/regression/tests/040.client_auth/test.sh index 964e9293e..c0b2c3331 100755 --- a/src/test/regression/tests/040.client_auth/test.sh +++ b/src/test/regression/tests/040.client_auth/test.sh @@ -278,9 +278,9 @@ function do_auth add_user $username $pg_hba $PGPORT - # for logical replication and slony, we need to manually + # for logical replication, we need to manually # add PostgreSQL user to node 1. - if [ $mode = 'l' -o $mode = 'y' ];then + if [ $mode = 'l' ];then add_user $username $pg_hba "11003" fi add_pool_hba $username $pool_hba $PGPOOL_VERSION_DIGIT diff --git a/src/test/regression/tests/050.bug58/.gitignore b/src/test/regression/tests/100.bug58/.gitignore index f937fcb17..f937fcb17 100644 --- a/src/test/regression/tests/050.bug58/.gitignore +++ b/src/test/regression/tests/100.bug58/.gitignore diff --git a/src/test/regression/tests/050.bug58/test.sh b/src/test/regression/tests/100.bug58/test.sh index 15afb7c69..15afb7c69 100755 --- a/src/test/regression/tests/050.bug58/test.sh +++ b/src/test/regression/tests/100.bug58/test.sh diff --git a/src/test/regression/tests/051.bug60/.gitignore b/src/test/regression/tests/101.bug60/.gitignore index f937fcb17..f937fcb17 100644 --- a/src/test/regression/tests/051.bug60/.gitignore +++ b/src/test/regression/tests/101.bug60/.gitignore diff --git a/src/test/regression/tests/051.bug60/bug.sql b/src/test/regression/tests/101.bug60/bug.sql index 134199bd7..134199bd7 100644 --- a/src/test/regression/tests/051.bug60/bug.sql +++ b/src/test/regression/tests/101.bug60/bug.sql diff --git a/src/test/regression/tests/051.bug60/database-clean.sql b/src/test/regression/tests/101.bug60/database-clean.sql index a32da02a4..a32da02a4 100644 --- a/src/test/regression/tests/051.bug60/database-clean.sql +++ b/src/test/regression/tests/101.bug60/database-clean.sql diff --git a/src/test/regression/tests/051.bug60/database-setup.sql b/src/test/regression/tests/101.bug60/database-setup.sql index 1fccbaab5..1fccbaab5 100644 --- a/src/test/regression/tests/051.bug60/database-setup.sql +++ b/src/test/regression/tests/101.bug60/database-setup.sql diff --git a/src/test/regression/tests/051.bug60/test.sh b/src/test/regression/tests/101.bug60/test.sh index 4032153b9..4032153b9 100755 --- a/src/test/regression/tests/051.bug60/test.sh +++ b/src/test/regression/tests/101.bug60/test.sh diff --git a/src/test/regression/tests/052.do_query/.gitignore b/src/test/regression/tests/102.do_query/.gitignore index f937fcb17..f937fcb17 100644 --- a/src/test/regression/tests/052.do_query/.gitignore +++ b/src/test/regression/tests/102.do_query/.gitignore diff --git a/src/test/regression/tests/052.do_query/test.sh b/src/test/regression/tests/102.do_query/test.sh index 9370b7b3b..9370b7b3b 100755 --- a/src/test/regression/tests/052.do_query/test.sh +++ b/src/test/regression/tests/102.do_query/test.sh diff --git a/src/test/regression/tests/053.insert_lock_hangs/.gitignore b/src/test/regression/tests/103.insert_lock_hangs/.gitignore index f937fcb17..f937fcb17 100644 --- a/src/test/regression/tests/053.insert_lock_hangs/.gitignore +++ b/src/test/regression/tests/103.insert_lock_hangs/.gitignore diff --git a/src/test/regression/tests/053.insert_lock_hangs/test.sh b/src/test/regression/tests/103.insert_lock_hangs/test.sh index daa811762..daa811762 100755 --- a/src/test/regression/tests/053.insert_lock_hangs/test.sh +++ b/src/test/regression/tests/103.insert_lock_hangs/test.sh diff --git a/src/test/regression/tests/054.postgres_fdw/.gitignore b/src/test/regression/tests/104.postgres_fdw/.gitignore index f937fcb17..f937fcb17 100644 --- a/src/test/regression/tests/054.postgres_fdw/.gitignore +++ b/src/test/regression/tests/104.postgres_fdw/.gitignore diff --git a/src/test/regression/tests/054.postgres_fdw/test.sh b/src/test/regression/tests/104.postgres_fdw/test.sh index b3b6f556f..b3b6f556f 100755 --- a/src/test/regression/tests/054.postgres_fdw/test.sh +++ b/src/test/regression/tests/104.postgres_fdw/test.sh diff --git a/src/test/regression/tests/055.backend_all_down/.gitignore b/src/test/regression/tests/105.backend_all_down/.gitignore index f937fcb17..f937fcb17 100644 --- a/src/test/regression/tests/055.backend_all_down/.gitignore +++ b/src/test/regression/tests/105.backend_all_down/.gitignore diff --git a/src/test/regression/tests/055.backend_all_down/test.sh b/src/test/regression/tests/105.backend_all_down/test.sh index ba7dadd32..ba7dadd32 100755 --- a/src/test/regression/tests/055.backend_all_down/test.sh +++ b/src/test/regression/tests/105.backend_all_down/test.sh diff --git a/src/test/regression/tests/056.bug63/.gitignore b/src/test/regression/tests/106.bug63/.gitignore index f937fcb17..f937fcb17 100644 --- a/src/test/regression/tests/056.bug63/.gitignore +++ b/src/test/regression/tests/106.bug63/.gitignore diff --git a/src/test/regression/tests/056.bug63/jdbctest2.java b/src/test/regression/tests/106.bug63/jdbctest2.java index 8f8b6efa8..8f8b6efa8 100644 --- a/src/test/regression/tests/056.bug63/jdbctest2.java +++ b/src/test/regression/tests/106.bug63/jdbctest2.java diff --git a/src/test/regression/tests/056.bug63/test.sh b/src/test/regression/tests/106.bug63/test.sh index 483826895..483826895 100755 --- a/src/test/regression/tests/056.bug63/test.sh +++ b/src/test/regression/tests/106.bug63/test.sh diff --git a/src/test/regression/tests/057.bug61/.gitignore b/src/test/regression/tests/107.bug61/.gitignore index f937fcb17..f937fcb17 100644 --- a/src/test/regression/tests/057.bug61/.gitignore +++ b/src/test/regression/tests/107.bug61/.gitignore diff --git a/src/test/regression/tests/057.bug61/test.sh b/src/test/regression/tests/107.bug61/test.sh index 1b6515153..1b6515153 100755 --- a/src/test/regression/tests/057.bug61/test.sh +++ b/src/test/regression/tests/107.bug61/test.sh diff --git a/src/test/regression/tests/058.bug68/.gitignore b/src/test/regression/tests/108.bug68/.gitignore index f937fcb17..f937fcb17 100644 --- a/src/test/regression/tests/058.bug68/.gitignore +++ b/src/test/regression/tests/108.bug68/.gitignore diff --git a/src/test/regression/tests/058.bug68/jdbctest3.java b/src/test/regression/tests/108.bug68/jdbctest3.java index 20cfb1aae..20cfb1aae 100644 --- a/src/test/regression/tests/058.bug68/jdbctest3.java +++ b/src/test/regression/tests/108.bug68/jdbctest3.java diff --git a/src/test/regression/tests/058.bug68/test.sh b/src/test/regression/tests/108.bug68/test.sh index 54b7d4968..54b7d4968 100755 --- a/src/test/regression/tests/058.bug68/test.sh +++ b/src/test/regression/tests/108.bug68/test.sh diff --git a/src/test/regression/tests/059.bug92/.gitignore b/src/test/regression/tests/109.bug92/.gitignore index f937fcb17..f937fcb17 100644 --- a/src/test/regression/tests/059.bug92/.gitignore +++ b/src/test/regression/tests/109.bug92/.gitignore diff --git a/src/test/regression/tests/059.bug92/jdbctest.java b/src/test/regression/tests/109.bug92/jdbctest.java index dd3720b8b..dd3720b8b 100644 --- a/src/test/regression/tests/059.bug92/jdbctest.java +++ b/src/test/regression/tests/109.bug92/jdbctest.java diff --git a/src/test/regression/tests/059.bug92/test.sh b/src/test/regression/tests/109.bug92/test.sh index e430f6a77..e430f6a77 100755 --- a/src/test/regression/tests/059.bug92/test.sh +++ b/src/test/regression/tests/109.bug92/test.sh diff --git a/src/test/regression/tests/060.memory_leak/.gitignore b/src/test/regression/tests/110.memory_leak/.gitignore index f937fcb17..f937fcb17 100644 --- a/src/test/regression/tests/060.memory_leak/.gitignore +++ b/src/test/regression/tests/110.memory_leak/.gitignore diff --git a/src/test/regression/tests/060.memory_leak/test.sh b/src/test/regression/tests/110.memory_leak/test.sh index 05f80de92..05f80de92 100755 --- a/src/test/regression/tests/060.memory_leak/test.sh +++ b/src/test/regression/tests/110.memory_leak/test.sh diff --git a/src/test/regression/tests/061.cancel_query/.gitignore b/src/test/regression/tests/111.cancel_query/.gitignore index f937fcb17..f937fcb17 100644 --- a/src/test/regression/tests/061.cancel_query/.gitignore +++ b/src/test/regression/tests/111.cancel_query/.gitignore diff --git a/src/test/regression/tests/061.cancel_query/test.sh b/src/test/regression/tests/111.cancel_query/test.sh index 969deaea2..969deaea2 100755 --- a/src/test/regression/tests/061.cancel_query/test.sh +++ b/src/test/regression/tests/111.cancel_query/test.sh diff --git a/src/test/regression/tests/062.select_error_hangs/.gitignore b/src/test/regression/tests/112.select_error_hangs/.gitignore index f937fcb17..f937fcb17 100644 --- a/src/test/regression/tests/062.select_error_hangs/.gitignore +++ b/src/test/regression/tests/112.select_error_hangs/.gitignore diff --git a/src/test/regression/tests/062.select_error_hangs/test.sh b/src/test/regression/tests/112.select_error_hangs/test.sh index 522a3599f..522a3599f 100755 --- a/src/test/regression/tests/062.select_error_hangs/test.sh +++ b/src/test/regression/tests/112.select_error_hangs/test.sh diff --git a/src/test/regression/tests/063.tables_with_space/.gitignore b/src/test/regression/tests/113.tables_with_space/.gitignore index f937fcb17..f937fcb17 100644 --- a/src/test/regression/tests/063.tables_with_space/.gitignore +++ b/src/test/regression/tests/113.tables_with_space/.gitignore diff --git a/src/test/regression/tests/063.tables_with_space/test.sh b/src/test/regression/tests/113.tables_with_space/test.sh index a40708307..a40708307 100755 --- a/src/test/regression/tests/063.tables_with_space/test.sh +++ b/src/test/regression/tests/113.tables_with_space/test.sh diff --git a/src/test/regression/tests/064.bug153/.gitignore b/src/test/regression/tests/114.bug153/.gitignore index f937fcb17..f937fcb17 100644 --- a/src/test/regression/tests/064.bug153/.gitignore +++ b/src/test/regression/tests/114.bug153/.gitignore diff --git a/src/test/regression/tests/064.bug153/test.sh b/src/test/regression/tests/114.bug153/test.sh index bc9eb1687..bc9eb1687 100755 --- a/src/test/regression/tests/064.bug153/test.sh +++ b/src/test/regression/tests/114.bug153/test.sh diff --git a/src/test/regression/tests/065.bug152/.gitignore b/src/test/regression/tests/115.bug152/.gitignore index f937fcb17..f937fcb17 100644 --- a/src/test/regression/tests/065.bug152/.gitignore +++ b/src/test/regression/tests/115.bug152/.gitignore diff --git a/src/test/regression/tests/065.bug152/Main.java b/src/test/regression/tests/115.bug152/Main.java index 5d9736071..5d9736071 100644 --- a/src/test/regression/tests/065.bug152/Main.java +++ b/src/test/regression/tests/115.bug152/Main.java diff --git a/src/test/regression/tests/065.bug152/run.sh b/src/test/regression/tests/115.bug152/run.sh index e6e1eead7..e6e1eead7 100644 --- a/src/test/regression/tests/065.bug152/run.sh +++ b/src/test/regression/tests/115.bug152/run.sh diff --git a/src/test/regression/tests/065.bug152/test.sh b/src/test/regression/tests/115.bug152/test.sh index 9dcbddcde..9dcbddcde 100755 --- a/src/test/regression/tests/065.bug152/test.sh +++ b/src/test/regression/tests/115.bug152/test.sh diff --git a/src/test/regression/tests/066.bug230/.gitignore b/src/test/regression/tests/116.bug230/.gitignore index f937fcb17..f937fcb17 100644 --- a/src/test/regression/tests/066.bug230/.gitignore +++ b/src/test/regression/tests/116.bug230/.gitignore diff --git a/src/test/regression/tests/066.bug230/Sample.java b/src/test/regression/tests/116.bug230/Sample.java index 47b7f98cf..47b7f98cf 100644 --- a/src/test/regression/tests/066.bug230/Sample.java +++ b/src/test/regression/tests/116.bug230/Sample.java diff --git a/src/test/regression/tests/066.bug230/test.sh b/src/test/regression/tests/116.bug230/test.sh index 1a1d123ea..1a1d123ea 100755 --- a/src/test/regression/tests/066.bug230/test.sh +++ b/src/test/regression/tests/116.bug230/test.sh diff --git a/src/test/regression/tests/067.bug231/.gitignore b/src/test/regression/tests/117.bug231/.gitignore index f937fcb17..f937fcb17 100644 --- a/src/test/regression/tests/067.bug231/.gitignore +++ b/src/test/regression/tests/117.bug231/.gitignore diff --git a/src/test/regression/tests/067.bug231/TestReplGap.java b/src/test/regression/tests/117.bug231/TestReplGap.java index 2aaa17dbf..2aaa17dbf 100644 --- a/src/test/regression/tests/067.bug231/TestReplGap.java +++ b/src/test/regression/tests/117.bug231/TestReplGap.java diff --git a/src/test/regression/tests/067.bug231/test.sh b/src/test/regression/tests/117.bug231/test.sh index 02b6a86de..02b6a86de 100755 --- a/src/test/regression/tests/067.bug231/test.sh +++ b/src/test/regression/tests/117.bug231/test.sh diff --git a/src/test/regression/tests/068.memqcache_bug/.gitignore b/src/test/regression/tests/118.memqcache_bug/.gitignore index f937fcb17..f937fcb17 100644 --- a/src/test/regression/tests/068.memqcache_bug/.gitignore +++ b/src/test/regression/tests/118.memqcache_bug/.gitignore diff --git a/src/test/regression/tests/068.memqcache_bug/Sample.java b/src/test/regression/tests/118.memqcache_bug/Sample.java index bacf9a9c8..bacf9a9c8 100644 --- a/src/test/regression/tests/068.memqcache_bug/Sample.java +++ b/src/test/regression/tests/118.memqcache_bug/Sample.java diff --git a/src/test/regression/tests/068.memqcache_bug/test.sh b/src/test/regression/tests/118.memqcache_bug/test.sh index 05746cf7a..05746cf7a 100755 --- a/src/test/regression/tests/068.memqcache_bug/test.sh +++ b/src/test/regression/tests/118.memqcache_bug/test.sh diff --git a/src/test/regression/tests/069.memory_leak_extended/.gitignore b/src/test/regression/tests/119.memory_leak_extended/.gitignore index f937fcb17..f937fcb17 100644 --- a/src/test/regression/tests/069.memory_leak_extended/.gitignore +++ b/src/test/regression/tests/119.memory_leak_extended/.gitignore diff --git a/src/test/regression/tests/069.memory_leak_extended/test.sh b/src/test/regression/tests/119.memory_leak_extended/test.sh index 87802608f..87802608f 100755 --- a/src/test/regression/tests/069.memory_leak_extended/test.sh +++ b/src/test/regression/tests/119.memory_leak_extended/test.sh diff --git a/src/test/regression/tests/070.memory_leak_extended_memqcache/.gitignore b/src/test/regression/tests/120.memory_leak_extended_memqcache/.gitignore index f937fcb17..f937fcb17 100644 --- a/src/test/regression/tests/070.memory_leak_extended_memqcache/.gitignore +++ b/src/test/regression/tests/120.memory_leak_extended_memqcache/.gitignore diff --git a/src/test/regression/tests/070.memory_leak_extended_memqcache/test.sh b/src/test/regression/tests/120.memory_leak_extended_memqcache/test.sh index 4a2badb51..4a2badb51 100755 --- a/src/test/regression/tests/070.memory_leak_extended_memqcache/test.sh +++ b/src/test/regression/tests/120.memory_leak_extended_memqcache/test.sh diff --git a/src/test/regression/tests/071.execute_and_deallocate/.gitignore b/src/test/regression/tests/121.execute_and_deallocate/.gitignore index f937fcb17..f937fcb17 100644 --- a/src/test/regression/tests/071.execute_and_deallocate/.gitignore +++ b/src/test/regression/tests/121.execute_and_deallocate/.gitignore diff --git a/src/test/regression/tests/071.execute_and_deallocate/test.sh b/src/test/regression/tests/121.execute_and_deallocate/test.sh index 08b3cb7b9..08b3cb7b9 100755 --- a/src/test/regression/tests/071.execute_and_deallocate/test.sh +++ b/src/test/regression/tests/121.execute_and_deallocate/test.sh diff --git a/src/test/regression/tests/072.meqcache_bug2/extended_query_test.data b/src/test/regression/tests/122.meqcache_bug2/extended_query_test.data index 07874b0d3..07874b0d3 100644 --- a/src/test/regression/tests/072.meqcache_bug2/extended_query_test.data +++ b/src/test/regression/tests/122.meqcache_bug2/extended_query_test.data diff --git a/src/test/regression/tests/072.meqcache_bug2/test.sh b/src/test/regression/tests/122.meqcache_bug2/test.sh index 32f969115..32f969115 100755 --- a/src/test/regression/tests/072.meqcache_bug2/test.sh +++ b/src/test/regression/tests/122.meqcache_bug2/test.sh diff --git a/src/test/regression/tests/073.pg_terminate_backend/test.sh b/src/test/regression/tests/123.pg_terminate_backend/test.sh index 4e2b9ab25..4e2b9ab25 100755 --- a/src/test/regression/tests/073.pg_terminate_backend/test.sh +++ b/src/test/regression/tests/123.pg_terminate_backend/test.sh diff --git a/src/test/regression/tests/074.bug700_memqcache_segfault/expected.txt b/src/test/regression/tests/124.bug700_memqcache_segfault/expected.txt index 3964fd9fa..3964fd9fa 100644 --- a/src/test/regression/tests/074.bug700_memqcache_segfault/expected.txt +++ b/src/test/regression/tests/124.bug700_memqcache_segfault/expected.txt diff --git a/src/test/regression/tests/074.bug700_memqcache_segfault/pgproto.data b/src/test/regression/tests/124.bug700_memqcache_segfault/pgproto.data index 510bada8a..510bada8a 100644 --- a/src/test/regression/tests/074.bug700_memqcache_segfault/pgproto.data +++ b/src/test/regression/tests/124.bug700_memqcache_segfault/pgproto.data diff --git a/src/test/regression/tests/074.bug700_memqcache_segfault/test.sh b/src/test/regression/tests/124.bug700_memqcache_segfault/test.sh index a26475bae..116d5c16c 100755 --- a/src/test/regression/tests/074.bug700_memqcache_segfault/test.sh +++ b/src/test/regression/tests/124.bug700_memqcache_segfault/test.sh @@ -27,6 +27,8 @@ do echo "memory_cache_enabled = on" >> etc/pgpool.conf echo "log_min_messages = debug1" >> etc/pgpool.conf + echo "log_backend_messages = terse" >> etc/pgpool.conf + echo "log_client_messages = on" >> etc/pgpool.conf ./startall wait_for_pgpool_startup diff --git a/src/test/regression/tests/075.detach_primary_left_down_node/test.sh b/src/test/regression/tests/125.detach_primary_left_down_node/test.sh index 05fdc5317..30acec9cb 100755 --- a/src/test/regression/tests/075.detach_primary_left_down_node/test.sh +++ b/src/test/regression/tests/125.detach_primary_left_down_node/test.sh @@ -30,7 +30,7 @@ wait_for_pgpool_startup # check to see if alll nodes are up echo -n "starting to check follow primary results: " date -cnt=60 +cnt=120 while [ $cnt -gt 0 ] do $PGBIN/psql -c "show pool_nodes" test 2>&1|grep -E 'down|error' diff --git a/src/test/regression/tests/126.copy_hang/copy-out-expected b/src/test/regression/tests/126.copy_hang/copy-out-expected new file mode 100644 index 000000000..270ee35e1 --- /dev/null +++ b/src/test/regression/tests/126.copy_hang/copy-out-expected @@ -0,0 +1,37 @@ +FE=> Query (query="CREATE TEMP TABLE copy_in_test AS SELECT I FROM generate_series(1,10) AS i") +<= BE CommandComplete(SELECT 10) +<= BE ReadyForQuery(I) +FE=> Query (query="SELECT * FROM copy_in_test") +<= BE RowDescription +<= BE DataRow +<= BE DataRow +<= BE DataRow +<= BE DataRow +<= BE DataRow +<= BE DataRow +<= BE DataRow +<= BE DataRow +<= BE DataRow +<= BE DataRow +<= BE CommandComplete(SELECT 10) +<= BE ReadyForQuery(I) +FE=> Parse(stmt="", query="COPY copy_in_test TO STDOUT") +FE=> Bind(stmt="", portal="") +FE=> Execute(portal="") +FE=> Sync +<= BE ParseComplete +<= BE BindComplete +<= BE CopyOutResponse +<= BE CopyData +<= BE CopyData +<= BE CopyData +<= BE CopyData +<= BE CopyData +<= BE CopyData +<= BE CopyData +<= BE CopyData +<= BE CopyData +<= BE CopyData +<= BE CopyDone +<= BE CommandComplete(COPY 10) +<= BE ReadyForQuery(I) diff --git a/src/test/regression/tests/126.copy_hang/pgproto-copy-out.data b/src/test/regression/tests/126.copy_hang/pgproto-copy-out.data new file mode 100644 index 000000000..627076530 --- /dev/null +++ b/src/test/regression/tests/126.copy_hang/pgproto-copy-out.data @@ -0,0 +1,9 @@ +'Q' "CREATE TEMP TABLE copy_in_test AS SELECT I FROM generate_series(1,10) AS i" +'Y' +'Q' "SELECT * FROM copy_in_test" +'Y' +'P' "" "COPY copy_in_test TO STDOUT" 0 +'B' "" "" 0 0 0 +'E' "" 0 +'S' +'Y' diff --git a/src/test/regression/tests/076.copy_hang/pgproto.data b/src/test/regression/tests/126.copy_hang/pgproto.data index ce6eeebc1..ce6eeebc1 100644 --- a/src/test/regression/tests/076.copy_hang/pgproto.data +++ b/src/test/regression/tests/126.copy_hang/pgproto.data diff --git a/src/test/regression/tests/076.copy_hang/test.sh b/src/test/regression/tests/126.copy_hang/test.sh index 9e0f4c0ce..6ed70a72e 100755 --- a/src/test/regression/tests/076.copy_hang/test.sh +++ b/src/test/regression/tests/126.copy_hang/test.sh @@ -64,4 +64,20 @@ if [ ! $? -eq 0 ];then ./shutdownall exit 1 fi + +# +# Test case for COPY OUT in extended query protocol mode segfaults. +# since this creates temp table, prevent load balance +echo "backend_weight1 = 0" >> etc/pgpool.conf +echo "backend_weight2 = 0" >> etc/pgpool.conf +# reload pgpool.conf and wait until the effect is apparent +./pgpool_reload +sleep 1 +# run test script +$PGPROTO -d test -f ../pgproto-copy-out.data > copy-out-result 2>&1 +cmp ../copy-out-expected copy-out-result +if [ ! $? -eq 0 ];then + ./shutdownall + exit 1 +fi ./shutdownall diff --git a/src/test/regression/tests/077.invalid_failover_node/test.sh b/src/test/regression/tests/127.invalid_failover_node/test.sh index bfea574e2..bfea574e2 100755 --- a/src/test/regression/tests/077.invalid_failover_node/test.sh +++ b/src/test/regression/tests/127.invalid_failover_node/test.sh diff --git a/src/test/regression/tests/078.aborted_transaction/expected.txt b/src/test/regression/tests/128.aborted_transaction/expected.txt index f70e6716e..f70e6716e 100644 --- a/src/test/regression/tests/078.aborted_transaction/expected.txt +++ b/src/test/regression/tests/128.aborted_transaction/expected.txt diff --git a/src/test/regression/tests/078.aborted_transaction/test.sh b/src/test/regression/tests/128.aborted_transaction/test.sh index 7c8eca387..7c8eca387 100755 --- a/src/test/regression/tests/078.aborted_transaction/test.sh +++ b/src/test/regression/tests/128.aborted_transaction/test.sh diff --git a/src/test/regression/tests/079.multi_prepare/expected.txt b/src/test/regression/tests/129.multi_prepare/expected.txt index 58ac94ffd..58ac94ffd 100644 --- a/src/test/regression/tests/079.multi_prepare/expected.txt +++ b/src/test/regression/tests/129.multi_prepare/expected.txt diff --git a/src/test/regression/tests/079.multi_prepare/pgproto.data b/src/test/regression/tests/129.multi_prepare/pgproto.data index aeef45bf7..aeef45bf7 100644 --- a/src/test/regression/tests/079.multi_prepare/pgproto.data +++ b/src/test/regression/tests/129.multi_prepare/pgproto.data diff --git a/src/test/regression/tests/079.multi_prepare/test.sh b/src/test/regression/tests/129.multi_prepare/test.sh index 970fca630..970fca630 100755 --- a/src/test/regression/tests/079.multi_prepare/test.sh +++ b/src/test/regression/tests/129.multi_prepare/test.sh diff --git a/src/test/regression/tests/080.declare/expected.txt b/src/test/regression/tests/130.declare/expected.txt index 414f4e406..414f4e406 100644 --- a/src/test/regression/tests/080.declare/expected.txt +++ b/src/test/regression/tests/130.declare/expected.txt diff --git a/src/test/regression/tests/080.declare/pgproto.data b/src/test/regression/tests/130.declare/pgproto.data index 5cfadf410..5cfadf410 100644 --- a/src/test/regression/tests/080.declare/pgproto.data +++ b/src/test/regression/tests/130.declare/pgproto.data diff --git a/src/test/regression/tests/080.declare/test.sh b/src/test/regression/tests/130.declare/test.sh index 65e00d571..65e00d571 100755 --- a/src/test/regression/tests/080.declare/test.sh +++ b/src/test/regression/tests/130.declare/test.sh diff --git a/src/test/regression/tests/081.detach_primary_all_down/test.sh b/src/test/regression/tests/131.detach_primary_all_down/test.sh index e97dcf923..e97dcf923 100755 --- a/src/test/regression/tests/081.detach_primary_all_down/test.sh +++ b/src/test/regression/tests/131.detach_primary_all_down/test.sh diff --git a/src/test/regression/tests/082.guard_against_bad_protocol/pgproto.data b/src/test/regression/tests/132.guard_against_bad_protocol/pgproto.data index 4b5bae6d0..4b5bae6d0 100644 --- a/src/test/regression/tests/082.guard_against_bad_protocol/pgproto.data +++ b/src/test/regression/tests/132.guard_against_bad_protocol/pgproto.data diff --git a/src/test/regression/tests/082.guard_against_bad_protocol/pgproto2.data b/src/test/regression/tests/132.guard_against_bad_protocol/pgproto2.data index f4edbb4b5..f4edbb4b5 100644 --- a/src/test/regression/tests/082.guard_against_bad_protocol/pgproto2.data +++ b/src/test/regression/tests/132.guard_against_bad_protocol/pgproto2.data diff --git a/src/test/regression/tests/082.guard_against_bad_protocol/test.sh b/src/test/regression/tests/132.guard_against_bad_protocol/test.sh index f1d16e6f3..f1d16e6f3 100755 --- a/src/test/regression/tests/082.guard_against_bad_protocol/test.sh +++ b/src/test/regression/tests/132.guard_against_bad_protocol/test.sh diff --git a/src/test/regression/tests/README b/src/test/regression/tests/README new file mode 100644 index 000000000..b1e074fe9 --- /dev/null +++ b/src/test/regression/tests/README @@ -0,0 +1,6 @@ +All test directory names should have following format: + +3-digit-numbers '.' (dot) test-names + +For the 3-digit-number, range 000-099 are reserved for tests of +features. Range 100- are reserved for tests for bugs. diff --git a/src/test/watchdog_setup.in b/src/test/watchdog_setup.in index d84a5b619..c64152451 100644 --- a/src/test/watchdog_setup.in +++ b/src/test/watchdog_setup.in @@ -1,6 +1,6 @@ #!/usr/bin/env bash # -# Copyright (c) 2013-2021 PgPool Global Development Group +# Copyright (c) 2013-2025 PgPool Global Development Group # # Permission to use, copy, modify, and distribute this software and # its documentation for any purpose and without fee is hereby @@ -18,10 +18,11 @@ # this tool for production environment! # Note that this script uses pgpool_setup as a work horse. # -# usage: watchdog_setup [-wn num_pgpool][-wp watchdog_base_port][-m r|s|n|i][-n num_clusters][-p base_port][--no-stop][-d] +# usage: watchdog_setup [-wn num_pgpool][-wp watchdog_base_port][-m r|s|n|i][-n num_clusters][-p base_port][--no-stop][-vip [ip]][-d] # -wn num_pgpool: create num_pgpool pgpool nodes. The default is 3. Must be greater than 1. # -wp watchdog_base_port: starting port number. The default is # 50000. +# -vip [ip]: allow to assign "ip" being set to delegate_ip. If "ip" is omitted, "127.0.0.1" is assumed. #------------------------------------------- # Configuration section #------------------------------------------- @@ -40,6 +41,9 @@ export PGBASEPORT=`expr $W_BASE_PORT + 1000` # number of ports used in a single pgpool-II installation. # (port, pcp_port, wd_port, wd_heartbeat_port) num_ports_per_node=4 + +# default vip +DEFAULT_VIP="127.0.0.1" #------------------------------------------- # End of configuration section #------------------------------------------- @@ -198,6 +202,13 @@ EOF n=`expr $n + 1` done + if [ "$VIP" != "" ];then + echo "delegate_ip = '$VIP'" >> $conf + echo "if_up_cmd = '/usr/bin/echo \"if_up_cmd executed\"'" >> $conf + echo "if_down_cmd = 'usr/bin/echo \"if_down_cmd executed\"'" >> $conf + echo "arping_cmd = '/usr/bin/true'" >> $conf + fi + echo "$id" >> $node_id_file } @@ -208,17 +219,18 @@ EOF ################################################################################ function usage() { - echo "usage: $0 [-wn num_pgpool][-wp watchdog_base_port][-m r|s|n|i] [-n num_clusters] [-p base_port] [-pg pg_base_port][--no-stop] [-d]";exit 1 + echo "usage: $0 [-wn num_pgpool][-wp watchdog_base_port][-m r|s|n|i] [-n num_clusters] [-p base_port] [-pg pg_base_port][--no-stop] -vip [ip]] [-d]";exit 1 } #------------------------------------------- # Argument check -# usage: $0 [-wn num_pgpool][-wp watchdog_base_port][-m r|s|n][-n num_clusters][-p base_port][-pg pg_base_port][--no-stop][-d] +# usage: $0 [-wn num_pgpool][-wp watchdog_base_port][-m r|s|n][-n num_clusters][-p base_port][-pg pg_base_port][--no-stop][-vip [ip]][-d] #------------------------------------------- # # default mode is streaming replication mode MODE="s" NO_STOP="false" +VIP="" while [ $# -gt 0 ] do @@ -257,9 +269,23 @@ do elif [ $1 = "--no-stop" ];then shift NO_STOP="true" + + elif [ $1 = "-vip" ];then + if [ $# = 1 ];then + # there's no more argument. set the default vip + VIP=$DEFAULT_VIP + else + if [[ $2 =~ -.* ]];then + # next argument given. set the default vip + VIP=$DEFAULT_VIP + else + # VIP is specified + shift + VIP=$1 + fi + fi elif [ $1 = "-d" ];then export PGPOOLDEBUG="true" - shift; elif [ $1 = "--help" -o $1 = "-o" ];then usage exit diff --git a/src/tools/pgenc/pg_enc.c b/src/tools/pgenc/pg_enc.c index 83c6d3b4f..7e5143843 100644 --- a/src/tools/pgenc/pg_enc.c +++ b/src/tools/pgenc/pg_enc.c @@ -5,7 +5,7 @@ * pgpool: a language independent connection pool server for PostgreSQL * written by Tatsuo Ishii * - * Copyright (c) 2003-2022 PgPool Global Development Group + * Copyright (c) 2003-2025 PgPool Global Development Group * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby @@ -98,7 +98,7 @@ main(int argc, char *argv[]) { switch (opt) { - case 'p': /* prompt for postgres password */ + case 'p': /* prompt for password to be encrypted */ prompt = true; break; @@ -246,6 +246,7 @@ main(int argc, char *argv[]) exit(EXIT_FAILURE); } stpncpy(enc_key, buf, sizeof(enc_key)); + pool_key = enc_key; } else { diff --git a/src/tools/pgindent/README.pgpool b/src/tools/pgindent/README.pgpool index a47c237e4..152e51653 100644 --- a/src/tools/pgindent/README.pgpool +++ b/src/tools/pgindent/README.pgpool @@ -9,8 +9,18 @@ The steps to run pgindent are as follows: 2. Or, if you want to generate typedefs.list from scratch, run find_typedes: cd pgpool2 + autoreconf -fi + make clean + # find_typedef needs to refer to the latest object files + make src/tools/find_typedef src > src/tools/pgindent/typedefs.list 3. Run pgindent by using run_pgindent. cd pgpool2/src tools/pgindent/run_pgindent + +4. Commit the change. + +5. Add an entry to .git-blame-ignore-revs. + (How to add an entry is described in the file). +
\ No newline at end of file diff --git a/src/tools/pgindent/enums.list b/src/tools/pgindent/enums.list index 5668af69f..5aa369e01 100644 --- a/src/tools/pgindent/enums.list +++ b/src/tools/pgindent/enums.list @@ -60,4 +60,4 @@ WDCommandStatus fe_scram_state_enum scram_state_enum ExplainFormat -RowCompareType +CompareType diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list index d7309565d..939200965 100644 --- a/src/tools/pgindent/typedefs.list +++ b/src/tools/pgindent/typedefs.list @@ -1,4 +1,4 @@ -ASN1_ITEM +ATAlterConstraint A_ArrayExpr A_Const A_Expr @@ -100,6 +100,7 @@ ColumnRef CommandDest CommentStmt CommonTableExpr +CompareType CompositeTypeStmt ConfigBoolAssignFunc ConfigContext @@ -182,9 +183,14 @@ DropTableSpaceStmt DropUserMappingStmt DropdbStmt EC_KEY +ENGINE +EVP_CIPHER EVP_CIPHER_CTX +EVP_MD ErrorContextCallback ErrorData +ErrorSaveContext +ExecStatusType ExecuteStmt ExplainStmt Expr @@ -274,6 +280,7 @@ JsonWrapper KeyAction KeyActions LDAP +LDAPControl LDAPMessage LDAPURLDesc LOAD_BALANCE_STATUS @@ -316,6 +323,7 @@ NotifyStmt NullIfExpr NullTest NullTestType +OPENSSL_INIT_SETTINGS ObjectType ObjectWithArgs Oid @@ -449,11 +457,14 @@ RenameStmt ReplicaIdentityStmt ResTarget ReturnStmt +ReturningClause +ReturningExpr +ReturningOption +ReturningOptionKind RoleSpec RoleSpecType RoleStmtType RowCompareExpr -RowCompareType RowDesc RowExpr RowMarkClause @@ -465,6 +476,8 @@ SQLValueFunction SQLValueFunctionOp SSL SSL_CTX +SSL_METHOD +SSL_verify_cb ScalarArrayOpExpr ScanKeywordHashFunc ScanKeywordList @@ -477,12 +490,8 @@ SetOperation SetOperationStmt SetQuantifier SetToDefault -SinglePartitionSpec Size SockAddr -Sockbuf -Sockbuf_IO -Sockbuf_IO_Desc SocketConnection SortBy SortByDir @@ -528,6 +537,7 @@ VacuumParams VacuumRelation VacuumStmt Var +VarReturningType VarShowHook VariableSetKind VariableSetStmt @@ -576,6 +586,7 @@ WindowFuncRunCondition WithCheckOption WithClause X509 +X509_NAME X509_STORE X509_STORE_CTX XmlExpr @@ -586,6 +597,7 @@ YYSTYPE YY_BUFFER_STATE YY_CHAR _IO_lock_t +__CONST_SOCKADDR_ARG __SOCKADDR_ARG __blkcnt_t __blksize_t @@ -627,13 +639,12 @@ __uint16_t __uint32_t __uint64_t __uint8_t +__useconds_t base_yy_extra_type ber_int_t ber_len_t -ber_slen_t bitmapword bits32 -bool check_network_data config_group config_type @@ -646,7 +657,6 @@ fe_scram_state fe_scram_state_enum flex_int16_t flex_uint8_t -func_ptr gid_t hashkit_hash_fn hashkit_st @@ -660,13 +670,13 @@ int64 int64_t int8 intptr_t -jmp_buf json_object_entry json_settings json_state json_type json_uchar json_value +key_t list_sort_comparator mb2wchar_with_len_converter mbchar_verifier @@ -688,6 +698,7 @@ memcached_result_st memcached_return memcached_return_t memcached_server_distribution_t +memcached_server_list_st memcached_server_st memcached_st memcached_string_st @@ -696,6 +707,7 @@ memcached_trigger_key_fn mode_t packet_types pam_handle_t +pem_password_cb pg_enc pg_enc2name pg_on_exit_callback @@ -732,6 +744,7 @@ size_t socklen_t ssize_t time_t +tree_walker_callback uid_t uint16 uint16_t @@ -751,5 +764,6 @@ yy_state_fast_t yy_state_t yy_state_type yyscan_t +yysymbol_kind_t yytype_int16 yytype_int8 diff --git a/src/utils/json.c b/src/utils/json.c index 8d156439c..ffe7a2c96 100644 --- a/src/utils/json.c +++ b/src/utils/json.c @@ -1191,7 +1191,7 @@ json_get_int_value_for_key(json_value *source, const char *key, int *value) } int -json_get_long_value_for_key(json_value *source, const char *key, long *value) +json_get_llong_value_for_key(json_value *source, const char *key, long long *value) { json_value *jNode; diff --git a/src/utils/pool_process_reporting.c b/src/utils/pool_process_reporting.c index 8e41ccafd..39087bc47 100644 --- a/src/utils/pool_process_reporting.c +++ b/src/utils/pool_process_reporting.c @@ -507,9 +507,9 @@ get_config(int *nrows) StrNCpy(status[i].desc, "path to pid file", POOLCONFIG_MAXDESCLEN); i++; - StrNCpy(status[i].name, "logdir", POOLCONFIG_MAXNAMELEN); - snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", pool_config->logdir); - StrNCpy(status[i].desc, "PgPool status file logging directory", POOLCONFIG_MAXDESCLEN); + StrNCpy(status[i].name, "work_dir", POOLCONFIG_MAXNAMELEN); + snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", pool_config->work_dir); + StrNCpy(status[i].desc, "directory to create pgpool_status and lock files ", POOLCONFIG_MAXDESCLEN); i++; /* CONNECTION POOLING */ @@ -1117,6 +1117,8 @@ get_config(int *nrows) StrNCpy(status[i].name, "memqcache_stats_start_time", POOLCONFIG_MAXNAMELEN); snprintf(status[i].value, POOLCONFIG_MAXVALLEN, "%s", ctime(&pool_get_memqcache_stats()->start_time)); + /* remove a newline added by ctime() */ + *(strchrnul(status[i].value, '\n')) = '\0'; StrNCpy(status[i].desc, "Start time of query cache stats", POOLCONFIG_MAXDESCLEN); i++; @@ -2071,7 +2073,7 @@ get_health_check_stats(int *nrows) /* status last changed */ t = bi->status_changed_time; - ereport(LOG, (errmsg("status_changed_time %ld", t))); + ereport(LOG, (errmsg("status_changed_time %lld", (long long) t))); strftime(stats[i].last_status_change, POOLCONFIG_MAXDATELEN, "%F %T", localtime(&t)); snprintf(stats[i].total_count, POOLCONFIG_MAXLONGCOUNTLEN, UINT64_FORMAT, health_check_stats[i].total_count); diff --git a/src/utils/pool_relcache.c b/src/utils/pool_relcache.c index bea2ac396..d4ebab25e 100644 --- a/src/utils/pool_relcache.c +++ b/src/utils/pool_relcache.c @@ -5,7 +5,7 @@ * pgpool: a language independent connection pool server for PostgreSQL * written by Tatsuo Ishii * - * Copyright (c) 2003-2023 PgPool Global Development Group + * Copyright (c) 2003-2025 PgPool Global Development Group * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby @@ -48,7 +48,7 @@ static char *relation_cache_to_query_cache(POOL_SELECT_RESULT *res, size_t *size */ POOL_RELCACHE * pool_create_relcache(int cachesize, char *sql, - func_ptr register_func, func_ptr unregister_func, + void *(*register_func) (POOL_SELECT_RESULT *), void *(*unregister_func) (void *), bool issessionlocal) { POOL_RELCACHE *p; @@ -187,7 +187,7 @@ pool_search_relcache(POOL_RELCACHE *relcache, POOL_CONNECTION_POOL *backend, cha { ereport(DEBUG1, (errmsg("searching relcache"), - errdetail("relcache for database:%s table:%s expired. now:%ld expiration time:%ld", dbname, table, now, relcache->cache[i].expire))); + errdetail("relcache for database:%s table:%s expired. now:%lld expiration time:%lld", dbname, table, (long long) now, (long long) relcache->cache[i].expire))); relcache->cache[i].refcnt = 0; break; diff --git a/src/watchdog/watchdog.c b/src/watchdog/watchdog.c index d57d83526..aa6fe7e41 100644 --- a/src/watchdog/watchdog.c +++ b/src/watchdog/watchdog.c @@ -590,7 +590,7 @@ static bool get_authhash_for_node(WatchdogNode *wdNode, char *authhash); static bool verify_authhash_for_node(WatchdogNode *wdNode, char *authhash); static void print_watchdog_node_info(WatchdogNode *wdNode); -static List *wd_create_recv_socket(int port); +static List *wd_create_recv_socket(char *hostname, int port); static void wd_check_config(void); static pid_t watchdog_main(void); static pid_t fork_watchdog_child(void); @@ -658,7 +658,7 @@ wd_check_config(void) MAX_PASSWORD_SIZE))); if (pool_config->wd_lifecheck_method == LIFECHECK_BY_HB) { - if (pool_config->num_hb_dest_if <= 0) + if (pool_config->num_hb_local_if <= 0 || pool_config->num_hb_dest_if <= 0) ereport(ERROR, (errmsg("invalid life-check configuration. no heartbeat interfaces defined"))); } @@ -865,7 +865,7 @@ clear_command_node_result(WDCommandNodeResult *nodeResult) } static List * -wd_create_recv_socket(int port) +wd_create_recv_socket(char *hostname, int port) { int one = 1; int sock = -1; @@ -886,7 +886,7 @@ wd_create_recv_socket(int port) hints.ai_protocol = 0; hints.ai_flags = AI_NUMERICSERV | AI_PASSIVE; - if ((gai_ret = getaddrinfo(NULL, portstr, &hints, &res)) != 0) + if ((gai_ret = getaddrinfo(!hostname ? NULL : hostname, portstr, &hints, &res)) != 0) { ereport(ERROR, (errmsg("getaddrinfo failed with error \"%s\"", gai_strerror(gai_ret)))); @@ -1299,7 +1299,7 @@ watchdog_main(void) /* initialize all the local structures for watchdog */ wd_cluster_initialize(); /* create a server socket for incoming watchdog connections */ - g_wd_recv_socks = wd_create_recv_socket(g_cluster.localNode->wd_port); + g_wd_recv_socks = wd_create_recv_socket(g_cluster.localNode->hostname, g_cluster.localNode->wd_port); /* open the command server */ g_cluster.command_server_sock = wd_create_command_server_socket(); @@ -1983,6 +1983,10 @@ read_sockets(fd_set *rmask, int pending_fds_count) return count; } +/* + * write watchdog IP command along with result data + * returns true on success + */ static bool write_ipc_command_with_result_data(WDCommandData *ipcCommand, char type, char *data, int len) { @@ -2133,7 +2137,7 @@ read_ipc_socket_and_process(int sock, bool *remove_socket) data_len = strlen(data) + 1; } - if (write_ipc_command_with_result_data(ipcCommand, res_type, data, data_len)) + if (!write_ipc_command_with_result_data(ipcCommand, res_type, data, data_len)) { ereport(NOTICE, (errmsg("error writing to IPC socket"))); @@ -3691,6 +3695,10 @@ update_successful_outgoing_cons(fd_set *wmask, int pending_fds_count) return count; } +/* + * write packet to watchdog communication socket + * returns true on success. + */ static bool write_packet_to_socket(int sock, WDPacketData *pkt, bool ipcPacket) { @@ -6755,8 +6763,8 @@ watchdog_state_machine_nw_isolation(WD_EVENTS event, WatchdogNode *wdNode, WDPac static bool beacon_message_received_from_node(WatchdogNode *wdNode, WDPacketData *pkt) { - long seconds_since_node_startup; - long seconds_since_current_state; + long long seconds_since_node_startup; + long long seconds_since_current_state; int quorum_status; int standby_nodes_count; bool escalated; @@ -7292,11 +7300,42 @@ watchdog_state_machine_standby(WD_EVENTS event, WatchdogNode *wdNode, WDPacketDa if (last_rcv_sec >= (3 * BEACON_MESSAGE_INTERVAL_SECONDS)) { - /* we have missed atleast two beacons from leader node */ + /* we have missed at least three beacons from leader node */ ereport(WARNING, (errmsg("we have not received a beacon message from leader node \"%s\" and it has not replied to our info request", WD_LEADER_NODE->nodeName), errdetail("re-initializing the cluster"))); + + /* + * Starting to set LOST status to the leader node. This needs to + * be done because there could be two leader nodes. + */ + WD_LEADER_NODE->state = WD_LOST; + ereport(LOG, + (errmsg("remote node \"%s\" is lost due to missed beacons", WD_LEADER_NODE->nodeName))); + + /* Inform the node, that it is lost for us */ + send_cluster_service_message(WD_LEADER_NODE, pkt, CLUSTER_NODE_APPEARING_LOST); + ereport(LOG, + (errmsg("watchdog cluster has lost the coordinator node"))); + + /* close all socket connections to the node */ + close_socket_connection(&WD_LEADER_NODE->client_socket); + close_socket_connection(&WD_LEADER_NODE->server_socket); + + /* clear the wait timer on the node */ + WD_LEADER_NODE->last_sent_time.tv_sec = 0; + WD_LEADER_NODE->last_sent_time.tv_usec = 0; + WD_LEADER_NODE->sending_failures_count = 0; + + node_lost_while_ipc_command(WD_LEADER_NODE); + set_cluster_leader_node(NULL); + + /* + * Finish setting LOST status to the leader node. + */ + + /* re-initialize the cluster */ set_state(WD_JOINING); } else if (last_rcv_sec >= (2 * BEACON_MESSAGE_INTERVAL_SECONDS)) @@ -8540,7 +8579,7 @@ load_watchdog_debug_test_option(void) if (wd_debug_request_file[0] == '\0') { snprintf(wd_debug_request_file, sizeof(wd_debug_request_file), - "%s/%s", pool_config->logdir, WATCHDOG_DEBUG_FILE); + "%s/%s", pool_config->work_dir, WATCHDOG_DEBUG_FILE); } fd = fopen(wd_debug_request_file, "r"); diff --git a/src/watchdog/wd_commands.c b/src/watchdog/wd_commands.c index 1539ef675..4b313e6c7 100644 --- a/src/watchdog/wd_commands.c +++ b/src/watchdog/wd_commands.c @@ -193,9 +193,9 @@ get_wd_runtime_variable_value(char *wd_authkey, char *varName) case VALUE_DATA_TYPE_LONG: { - long longVal; + long long longVal; - if (json_get_long_value_for_key(root, WD_JSON_KEY_VALUE_DATA, &longVal)) + if (json_get_llong_value_for_key(root, WD_JSON_KEY_VALUE_DATA, &longVal)) { ereport(WARNING, (errmsg("get runtime variable value from watchdog failed"), diff --git a/src/watchdog/wd_heartbeat.c b/src/watchdog/wd_heartbeat.c index a9e99dec9..33c378b4f 100644 --- a/src/watchdog/wd_heartbeat.c +++ b/src/watchdog/wd_heartbeat.c @@ -262,7 +262,7 @@ wd_create_hb_recv_socket(WdHbIf *hb_if) *walk, *res = NULL; - portstr = psprintf("%d", pool_config->wd_heartbeat_port); + portstr = psprintf("%d", hb_if->dest_port); memset(&hints, 0x00, sizeof(hints)); hints.ai_family = AF_UNSPEC; @@ -270,7 +270,7 @@ wd_create_hb_recv_socket(WdHbIf *hb_if) hints.ai_protocol = 0; hints.ai_flags = AI_NUMERICSERV | AI_PASSIVE; - if ((gai_ret = getaddrinfo(NULL, portstr, &hints, &res)) != 0) + if ((gai_ret = getaddrinfo(hb_if->addr[0] == '\0' ? NULL : hb_if->addr, portstr, &hints, &res)) != 0) { ereport(WARNING, (errmsg("getaddrinfo() failed with error \"%s\"", gai_strerror(gai_ret)))); @@ -285,7 +285,7 @@ wd_create_hb_recv_socket(WdHbIf *hb_if) if (n == 0) { ereport(ERROR, (errmsg("failed to create watchdog heartbeat receive socket"), - errdetail("getaddrinfo() result is empty: no sockets can be created because no available local address with port:%d", pool_config->wd_heartbeat_port))); + errdetail("getaddrinfo() result is empty: no sockets can be created because no available local address with port:%d", hb_if->dest_port))); return NULL; } else @@ -380,7 +380,7 @@ wd_create_hb_recv_socket(WdHbIf *hb_if) } ereport(LOG, (errmsg("creating watchdog heartbeat receive socket."), - errdetail("creating socket on %s:%d", buf, pool_config->wd_heartbeat_port))); + errdetail("creating socket on %s:%d", buf, hb_if->dest_port))); bind_is_done = 0; for (bind_tries = 0; !bind_is_done && bind_tries < MAX_BIND_TRIES; bind_tries++) @@ -850,8 +850,8 @@ packet_to_string_hb(WdHbPacket *pkt, char *str, int maxlen) { int len; - len = snprintf(str, maxlen, "tv_sec=%ld tv_usec=%ld from=%s", - pkt->send_time.tv_sec, pkt->send_time.tv_usec, pkt->from); + len = snprintf(str, maxlen, "tv_sec=%lld tv_usec=%lld from=%s", + (long long) pkt->send_time.tv_sec, (long long) pkt->send_time.tv_usec, pkt->from); return len; } diff --git a/src/watchdog/wd_json_data.c b/src/watchdog/wd_json_data.c index d5741b3e7..91dd26a86 100644 --- a/src/watchdog/wd_json_data.c +++ b/src/watchdog/wd_json_data.c @@ -533,6 +533,7 @@ get_watchdog_node_from_json(char *json_data, int data_len, char **authkey) { json_value *root = NULL; char *ptr; + long long longVal; WatchdogNode *wdNode = palloc0(sizeof(WatchdogNode)); root = json_parse(json_data, data_len); @@ -540,19 +541,20 @@ get_watchdog_node_from_json(char *json_data, int data_len, char **authkey) if (root == NULL || root->type != json_object) goto ERROR_EXIT; - if (json_get_long_value_for_key(root, "StartupTimeSecs", &wdNode->startup_time.tv_sec)) + if (json_get_llong_value_for_key(root, "StartupTimeSecs", &longVal)) { bool escalated; - long seconds_since_node_startup; - long seconds_since_current_state; + long long seconds_since_node_startup; + long long seconds_since_current_state; struct timeval current_time; + wdNode->startup_time.tv_sec = longVal; gettimeofday(¤t_time, NULL); /* The new version does not have StartupTimeSecs Key */ - if (json_get_long_value_for_key(root, "SecondsSinceStartup", &seconds_since_node_startup)) + if (json_get_llong_value_for_key(root, "SecondsSinceStartup", &seconds_since_node_startup)) goto ERROR_EXIT; - if (json_get_long_value_for_key(root, "SecondsSinceCurrentState", &seconds_since_current_state)) + if (json_get_llong_value_for_key(root, "SecondsSinceCurrentState", &seconds_since_current_state)) goto ERROR_EXIT; if (json_get_bool_value_for_key(root, "Escalated", &escalated)) goto ERROR_EXIT; @@ -643,8 +645,8 @@ ERROR_EXIT: bool parse_beacon_message_json(char *json_data, int data_len, int *state, - long *seconds_since_node_startup, - long *seconds_since_current_state, + long long *seconds_since_node_startup, + long long *seconds_since_current_state, int *quorumStatus, int *standbyNodesCount, bool *escalated) @@ -658,9 +660,9 @@ parse_beacon_message_json(char *json_data, int data_len, if (json_get_int_value_for_key(root, "State", state)) goto ERROR_EXIT; - if (json_get_long_value_for_key(root, "SecondsSinceStartup", seconds_since_node_startup)) + if (json_get_llong_value_for_key(root, "SecondsSinceStartup", seconds_since_node_startup)) goto ERROR_EXIT; - if (json_get_long_value_for_key(root, "SecondsSinceCurrentState", seconds_since_current_state)) + if (json_get_llong_value_for_key(root, "SecondsSinceCurrentState", seconds_since_current_state)) goto ERROR_EXIT; if (json_get_bool_value_for_key(root, "Escalated", escalated)) goto ERROR_EXIT; diff --git a/src/watchdog/wd_lifecheck.c b/src/watchdog/wd_lifecheck.c index b62a9b493..86caf9b4b 100644 --- a/src/watchdog/wd_lifecheck.c +++ b/src/watchdog/wd_lifecheck.c @@ -133,11 +133,14 @@ lifecheck_child_name(pid_t pid) { int i; - for (i = 0; i < pool_config->num_hb_dest_if; i++) + for (i = 0; i < pool_config->num_hb_local_if; i++) { if (g_hb_receiver_pid && pid == g_hb_receiver_pid[i]) return "heartBeat receiver"; - else if (g_hb_sender_pid && pid == g_hb_sender_pid[i]) + } + for (i = 0; i < pool_config->num_hb_dest_if; i++) + { + if (g_hb_sender_pid && pid == g_hb_sender_pid[i]) return "heartBeat sender"; } /* Check if it was a ping to trusted server process */ @@ -211,13 +214,13 @@ wd_reaper_lifecheck(pid_t pid, int status) if (g_hb_receiver_pid == NULL && g_hb_sender_pid == NULL) return -1; - for (i = 0; i < pool_config->num_hb_dest_if; i++) + for (i = 0; i < pool_config->num_hb_local_if; i++) { if (g_hb_receiver_pid && pid == g_hb_receiver_pid[i]) { if (restart_child) { - g_hb_receiver_pid[i] = wd_hb_receiver(1, &(pool_config->hb_dest_if[i])); + g_hb_receiver_pid[i] = wd_hb_receiver(1, &(pool_config->hb_local_if[i])); ereport(LOG, (errmsg("fork a new %s process with pid: %d", proc_name, g_hb_receiver_pid[i]))); } @@ -226,8 +229,11 @@ wd_reaper_lifecheck(pid_t pid, int status) return g_hb_receiver_pid[i]; } + } - else if (g_hb_sender_pid && pid == g_hb_sender_pid[i]) + for (i = 0; i < pool_config->num_hb_dest_if; i++) + { + if (g_hb_sender_pid && pid == g_hb_sender_pid[i]) { if (restart_child) { @@ -253,17 +259,21 @@ lifecheck_kill_all_children(int sig) && g_hb_receiver_pid && g_hb_sender_pid) { int i; + pid_t pid_child; - for (i = 0; i < pool_config->num_hb_dest_if; i++) + for (i = 0; i < pool_config->num_hb_local_if; i++) { - pid_t pid_child = g_hb_receiver_pid[i]; + pid_child = g_hb_receiver_pid[i]; if (pid_child > 0) { kill(pid_child, sig); ret = true; } + } + for (i = 0; i < pool_config->num_hb_dest_if; i++) + { pid_child = g_hb_sender_pid[i]; if (pid_child > 0) @@ -378,6 +388,7 @@ lifecheck_main(void) { sigjmp_buf local_sigjmp_buf; int i; + bool need_life_check_warning = false; ereport(DEBUG1, (errmsg("I am watchdog lifecheck child with pid:%d", getpid()))); @@ -424,6 +435,14 @@ lifecheck_main(void) /* wait until ready to go */ while (WD_OK != is_wd_lifecheck_ready()) { + /* + * For the first time we do not emit warning since it is likely the + * life check is not ready. + */ + if (need_life_check_warning) + ereport(WARNING, + (errmsg("watchdog: lifecheck has not started yet"))); + need_life_check_warning = true; sleep(pool_config->wd_interval * 10); } @@ -468,14 +487,17 @@ spawn_lifecheck_children(void) { int i; - g_hb_receiver_pid = palloc0(sizeof(pid_t) * pool_config->num_hb_dest_if); + g_hb_receiver_pid = palloc0(sizeof(pid_t) * pool_config->num_hb_local_if); g_hb_sender_pid = palloc0(sizeof(pid_t) * pool_config->num_hb_dest_if); - for (i = 0; i < pool_config->num_hb_dest_if; i++) + for (i = 0; i < pool_config->num_hb_local_if; i++) { /* heartbeat receiver process */ - g_hb_receiver_pid[i] = wd_hb_receiver(1, &(pool_config->hb_dest_if[i])); + g_hb_receiver_pid[i] = wd_hb_receiver(1, &(pool_config->hb_local_if[i])); + } + for (i = 0; i < pool_config->num_hb_dest_if; i++) + { /* heartbeat sender process */ g_hb_sender_pid[i] = wd_hb_sender(1, &(pool_config->hb_dest_if[i])); } @@ -642,7 +664,14 @@ load_watchdog_nodes_from_json(char *json_data, int len) json_value_free(root); } - +/*---------- + * is_wd_lifecheck_ready + * + * Check all registered watchdog nodes and returns WD_OK if: + * query mode: wd_ping_pgpool returns WD_OK + * hearbeat mode: has received from and + * sent to all node the heartbeat message + */ static int is_wd_lifecheck_ready(void) { @@ -680,7 +709,7 @@ is_wd_lifecheck_ready(void) { ereport(DEBUG1, (errmsg("watchdog checking life check is ready"), - errdetail("pgpool:%d at \"%s:%d\" has not send the heartbeat signal yet", + errdetail("pgpool:%d at \"%s:%d\" has not received from or sent to the heartbeat signal yet", i, node->hostName, node->pgpoolPort))); rtn = WD_NG; } diff --git a/src/watchdog/wd_ping.c b/src/watchdog/wd_ping.c index 2386950f4..ef4bf8724 100644 --- a/src/watchdog/wd_ping.c +++ b/src/watchdog/wd_ping.c @@ -6,7 +6,7 @@ * pgpool: a language independent connection pool server for PostgreSQL * written by Tatsuo Ishii * - * Copyright (c) 2003-2022 PgPool Global Development Group + * Copyright (c) 2003-2025 PgPool Global Development Group * * Permission to use, copy, modify, and distribute this software and * its documentation for any purpose and without fee is hereby @@ -41,6 +41,8 @@ #define WD_MAX_PING_RESULT 256 static double get_result(char *ping_data); +static bool wd_get_ping_result(char *hostname, int exit_status, int outfd); +static pid_t wd_issue_ping_command(char *hostname, int *outfd); /** * check if IP address can be pinged. @@ -95,7 +97,7 @@ wd_is_ip_exists(char *ip) * function issues the ping command using the execv system call * and return the pid of the process. */ -pid_t +static pid_t wd_issue_ping_command(char *hostname, int *outfd) { int status; @@ -254,7 +256,7 @@ wd_trusted_server_command(char *hostname) * The function is helper function and can be used with the * wd_issue_ping_command() function to identify if the ping command * was successful */ -bool +static bool wd_get_ping_result(char *hostname, int exit_status, int outfd) { /* First check the exit status of ping process */ |
