Compare commits

..

111 Commits

Author SHA1 Message Date
Erkfapx9w 34654e81d2 Update kwlookup.cpp 2022-10-30 15:44:09 +08:00
Erkfapx9w fa5d12e556 Update scansup.cpp 2022-10-30 15:40:27 +08:00
xiangxinyong 4cd25670b5 Merge pull request 'sql慢查询注释' (#3) from Eukanj827/openGauss-server:master into master 2022-08-03 09:29:40 +08:00
xiangxinyong f70898ecf5 Merge pull request '对BBOX_DetermineMsb函数的更详细描述' (#2) from Eao3piq4e/openGauss-server:master into master 2022-08-03 09:29:29 +08:00
Eao3piq4e 95466298fa Update bbox_print.cpp 2022-08-02 23:34:06 +08:00
Eao3piq4e 119d5d39da Update bbox_print.cpp 2022-08-02 22:23:59 +08:00
Eao3piq4e 537cba6247 Update bbox_lib.cpp 2022-08-02 21:18:32 +08:00
Eao3piq4e 14c4068daa Update bbox_lib.cpp 2022-08-02 20:50:21 +08:00
Eao3piq4e cf8e1541b1 Update bbox_lib.cpp 2022-08-02 18:05:36 +08:00
Eao3piq4e 58d5c900c9 Update bbox_lib.cpp 2022-08-02 17:15:14 +08:00
Eao3piq4e 25332da4aa Update bbox_lib.cpp 2022-08-02 17:01:46 +08:00
Eukanj827 fd0098411a Update __init__.py 2022-08-02 14:54:35 +08:00
Eukanj827 b4f33b07cf Update average_base.py 2022-08-02 14:44:04 +08:00
Eukanj827 caccfc026d Update feature_model.py 2022-08-02 14:01:17 +08:00
Eao3piq4e 30621924cf Update bbox_lib.cpp 2022-08-02 12:55:12 +08:00
Eukanj827 abb0cee0fc Update __init__.py 2022-08-02 12:37:44 +08:00
Eao3piq4e 0c2af1d742 Update bbox_lib.cpp 2022-08-02 11:50:12 +08:00
Eao3piq4e 09e299ac8a Update bbox_lib.cpp 2022-08-02 10:14:02 +08:00
Eao3piq4e 7dc9903be8 Update bbox_elf_dump_base.cpp 2022-08-02 09:19:40 +08:00
xiangxinyong bc0dc304c8 合并来自罗格的代码注释
合并来自罗格的代码注释
2022-07-28 14:55:50 +08:00
Eao3piq4e 5f334a5656 Update encrypt.cpp 2022-07-28 12:05:27 +08:00
Eao3piq4e 4ec1513e05 Update crypt.cpp 2022-07-28 10:58:29 +08:00
Eao3piq4e fb0026b93b Update crypt.cpp 2022-07-28 10:49:45 +08:00
Eao3piq4e ce56fb62b6 Update asan_report.pl 2022-05-29 10:13:24 +08:00
Eao3piq4e 2b198387ab Update asan_report.pl 2022-05-29 10:07:32 +08:00
opengauss-bot 72f4d68de6
!1772 修复在部分场景下,非sysadmin用户执行gs_dump失败的问题
Merge pull request !1772 from pengjiong/drop_ext
2022-05-28 11:52:08 +00:00
TotaJ 62e3bed09b Fix gs_dump 2022-05-28 17:58:05 +08:00
opengauss-bot 7d4d95a5ad
!1764 函数使用internal类型的限制添加wm_concat
Merge pull request !1764 from 吕辉/wm_concat
2022-05-28 07:00:10 +00:00
opengauss-bot 240f61c595
!1740 compressByteConvert\compressDiffConvert内存判断当且仅当用户输入为true而不是判断用户是否使用该参数
Merge pull request !1740 from 吴岳川/I54KW0
2022-05-28 02:02:39 +00:00
opengauss-bot a0d1a547f8
!1741 【压缩特性】在回放过程中,假设表文件已经被创建而表_pca等文件未被创建,flags会被修改,丢失O_CREATE标记,导致备机回放失败
Merge pull request !1741 from 吴岳川/I56GGM
2022-05-28 01:43:32 +00:00
opengauss-bot df804a8a91
!1763 在support_extended_features场景下,支持删除插件
Merge pull request !1763 from pengjiong/drop_ext
2022-05-26 11:10:25 +00:00
TotaJ 91917dcfaf Fix drop extension. 2022-05-26 16:22:52 +08:00
lvhui e2163187ca add wm_concat in InternalAggIsSupported 2022-05-26 15:34:47 +08:00
opengauss-bot 1d7eadd778
!1762 [bugfix] 修复host_standby=off/wal_level=archive场景下failover/switchover出现tuple concurrently updated的问题
Merge pull request !1762 from 周斌/gsc_hoststandby
2022-05-26 01:31:22 +00:00
opengauss-bot b335ef9af7
!1761 [feature] 修复GSC函数接口内存重复统计问题
Merge pull request !1761 from 周斌/gsc_cache_duplicate
2022-05-26 01:30:00 +00:00
justbk 572d99d03c repair wal_level=archive in switchover/failover get tuple concurrently updated issue 2022-05-25 20:17:01 +08:00
opengauss-bot 0b0959fc69
!1760 DFX: add exit log in PercentileMain
Merge pull request !1760 from 吴岳川/I5696K
2022-05-25 11:25:07 +00:00
justbk 238ee19a59 repair gs_gsc_memory_detail memory info inaccurate issue 2022-05-25 15:43:39 +08:00
opengauss-bot d199d90a71
!1747 修复复合datum产生的record报错
Merge pull request !1747 from 仲夏十三/helper
2022-05-25 03:17:57 +00:00
opengauss-bot 2a77a3cebc
!1751 增加alter procedure帮助说明
Merge pull request !1751 from 仲夏十三/helper2
2022-05-25 03:15:27 +00:00
opengauss-bot 214d01ddb6
!1759 [bugfix] 修复备机GSC不缓存数据问题
Merge pull request !1759 from 周斌/no_gsc_cache
2022-05-25 02:40:49 +00:00
opengauss-bot 4f024161f0
!1758 [bugfix] 修复openGauss数据库关闭时pagewriter主线程退出失败的问题
Merge pull request !1758 from 周斌/master
2022-05-25 02:38:02 +00:00
wuyuechuan 82d5ac65b0 DFX: add exit log in PercentileMain 2022-05-25 10:13:36 +08:00
justbk 7edda5e2a4 repair GSC no cache issue 2022-05-24 21:47:43 +08:00
justbk e10c482649 repair opengauss close failed issue 2022-05-24 20:29:11 +08:00
opengauss-bot 0a29277070
!1739 修复wal2json插件编译时报logical.h文件中的DefElem类型未声明的错误
Merge pull request !1739 from 薛蒙恩/com_wal2json
2022-05-23 12:20:33 +00:00
xue_meng_en 96dad83a1d 修复wal2json插件编译时报logical.h文件中的DefElem类型未声明的错误 2022-05-23 17:27:49 +08:00
opengauss-bot d433ee097a
!1746 Masstree OOM feature
Merge pull request !1746 from Vinoth Veeraraghavan/master
2022-05-23 03:32:46 +00:00
ganyang a590e0b47f add alter procedure helper note 2022-05-23 11:00:17 +08:00
仲夏十三 7f8b900e69 Merge branch 'master' of gitee.com:opengauss/openGauss-server into helper 2022-05-20 07:40:19 +00:00
ganyang f14255f040 fix record type issue caused by composite datum 2022-05-20 15:38:19 +08:00
wuyuechuan 5af581f12a use `RetryDataFileIdOpenFile` to prevent the flags from being modified 2022-05-20 11:57:25 +08:00
Vinoth Veeraraghavan 26793e3bf2 Masstree out of memory feature:
1. Fix RCU bug in masstree (GC layer removal flow)
    2. Support pool allocation failure in masstree
    3. Add new masstree API changes
2022-05-20 10:46:52 +08:00
wuyuechuan dbcf479205 set compressByteConvert/compressDiffConvert to true when defElem is set to true 2022-05-18 14:41:15 +08:00
opengauss-bot ae11cad2c3
!1738 修复\h drop table 查看语法帮助显示语法错误
Merge pull request !1738 from 仲夏十三/helper
2022-05-17 09:50:24 +00:00
ganyang 57bc5c4a37 fix helper note 2022-05-17 10:22:29 +08:00
opengauss-bot fb449157d0
!1710 修复join结果不正确的bug
Merge pull request !1710 from Cross-罗/join_alias
2022-05-16 07:21:34 +00:00
opengauss-bot 6c5898646e
!1726 修复视图中包含自定义操作符时,获取视图定义失败的问题
Merge pull request !1726 from pengjiong/logical_core
2022-05-13 09:11:34 +00:00
TotaJ c1335bebc9 Fix deserialize func and view. 2022-05-13 14:55:39 +08:00
opengauss-bot b2c6e04eab
!1725 重命名b_sql_plugin
Merge pull request !1725 from 仲夏十三/dolphin
2022-05-12 08:34:58 +00:00
ganyang 16d32d3978 rename b_sql_plugin 2022-05-12 14:30:24 +08:00
opengauss-bot 3e14e85fdf
!1698 添加对asianux平台支持
Merge pull request !1698 from zhangminjie/master
2022-05-10 07:35:19 +00:00
opengauss-bot 438bba32ff
!1705 修复 master 分支 和 3.0.0 分支创建 postgis_raster 扩展失败问题
Merge pull request !1705 from sungwu/master
2022-05-10 06:07:23 +00:00
opengauss-bot d82eba4790
!1721 【bugfix】修复interval分区exchange失败的问题
Merge pull request !1721 from cchen676/master1
2022-05-10 02:19:45 +00:00
arcoalien@qq.com 4b7080c8ef [回合主线]fix bug interval分区exchange失败 2022-05-09 20:55:12 +08:00
zhangminjie1997 5e1d9b79f6 添加对asianux平台支持 2022-05-09 11:40:22 +08:00
opengauss-bot 51c355c7b6
!1699 fix core of function pg_create_physical_replication_slot_extern
Merge pull request !1699 from 胡正超/repslot
2022-05-09 02:48:37 +00:00
luozihao 4c0a495a18 fixed the bug of join 2022-05-05 09:45:50 +08:00
wusong cbb8fd609b fix #I51OZS 修复在扩展中无法调用已创建函数问题,sort_candidate_func_list 函数实现 bug 2022-04-27 20:15:23 +08:00
opengauss-bot 475170ca0c
!1703 修复plpgsql在使用b_sql_plugin插件的情况下没有正确使用插件语法解析器的bug
Merge pull request !1703 from Cross-罗/plpgsql
2022-04-27 11:01:46 +00:00
l00584793 7f9a1f5428 Fix the bug that the pgplsql invokes the syntax parser error. 2022-04-27 16:35:38 +08:00
opengauss-bot c04e377cdc
!1701 修复升级后subbinary为空导致发布订阅报错问题
Merge pull request !1701 from 薛蒙恩/pubsub_bnrupg
2022-04-27 02:08:51 +00:00
opengauss-bot 6380ca0f4d
!1702 修复分区表issue
Merge pull request !1702 from 仲夏十三/333
2022-04-26 12:43:21 +00:00
kidhasdream 4898f04a3c change fastcheck 2022-04-26 20:06:11 +08:00
ganyang 11a1a5c9ad fix partition error 2022-04-26 19:15:23 +08:00
opengauss-bot a30ae9d5ad
!1700 修复ustore二级分区以及生成列场景下,发布订阅数据同步失败的问题
Merge pull request !1700 from pengjiong/logical_core
2022-04-26 07:24:18 +00:00
xue_meng_en 0b70c7ab70 修复升级后subbinary为空导致发布订阅报错问题 2022-04-26 11:29:41 +08:00
TotaJ f719422916 Fix ustore bug in publication. 2022-04-26 09:35:24 +08:00
opengauss-bot 88dcc7f99e
!1697 修复由于CurrentResourceOwner为NULL导致的逻辑解码core问题
Merge pull request !1697 from pengjiong/logical_core
2022-04-25 11:59:17 +00:00
gentle_hu dbd9958443 fix core of function pg_create_physical_replication_slot_extern 2022-04-25 19:09:58 +08:00
TotaJ 38b5a0ac95 Fix logical decode core. 2022-04-25 17:48:53 +08:00
opengauss-bot a548f5c3c6
!1675 修复发布订阅死锁问题
Merge pull request !1675 from 薛蒙恩/pubsub_deadlock
2022-04-24 01:53:42 +00:00
opengauss-bot eb4e54d4eb
!1678 openGauss 发布订阅支持gs_probackup备份恢复后连接不断开
Merge pull request !1678 from chenxiaobin/probackup
2022-04-22 02:42:08 +00:00
chenxiaobin19 3f7a909887 gs_probackup支持备份发布订阅的逻辑复制槽 2022-04-18 20:56:52 +08:00
xue_meng_en d8b89ceea5 修复发布订阅死锁问题 2022-04-16 19:34:20 +08:00
opengauss-bot 2250adfd4b
!1671 Implementing Monte Carlo Tree Search Algorithm
Merge pull request !1671 from liuly/master
2022-04-15 07:36:01 +00:00
flyly fd34b5da2a Implementing Monte Carlo Tree Search Algorithm 2022-04-14 17:11:09 +08:00
opengauss-bot 7f97d633f1
!1665 发布订阅支持以二进制格式发送数据和发布端主备切换不断开
Merge pull request !1665 from 薛蒙恩/pubsub330
2022-04-12 01:32:52 +00:00
opengauss-bot 6ba4c95f5f
!1666 修复enable_global_syscache关闭时连接B兼容性数据库的core问题
Merge pull request !1666 from chenxiaobin/fixbcore
2022-04-11 11:10:58 +00:00
xue_meng_en 5755feee5d 发布订阅支持主备切换不断开 2022-04-11 10:14:20 +08:00
opengauss-bot cd5d44d66c
!1668 gs_ctl添加-C参数适配流式容灾
Merge pull request !1668 from zhangxubo/master
2022-04-08 08:37:04 +00:00
zhang_xubo 2d657cddbe 添加参数适配流式容灾 2022-04-08 15:13:35 +08:00
chenxiaobin19 ccd674c159 修复enable_global_syscache关闭时连接B兼容性数据库的core问题 2022-04-08 11:11:07 +08:00
xue_meng_en 8292238381 发布订阅支持以二进制格式发送数据 2022-04-07 11:08:45 +08:00
opengauss-bot 5054ddd002
!1661 修复sql插件切换数据库插件依然存在
Merge pull request !1661 from 仲夏十三/bb0aa02e
2022-04-06 08:26:34 +00:00
ganyang 48a5033c18 fix space error 2022-04-06 10:32:10 +08:00
ganyang 811a9afcd9 optimize judgement 2022-04-02 16:44:36 +08:00
ganyang bb0aa02eb0 fix plugin hook issue 2022-04-02 15:01:58 +08:00
opengauss-bot 02c14696bf
!1657 【轻量级 PR】:修复mxid_to_string在TopMemoryContext分配内存的问题
Merge pull request !1657 from chenxiaobin/N/A
2022-04-01 07:59:00 +00:00
chenxiaobin 877f0b69e3
修复mxid_to_string在TopMemoryContext分配内存的问题 2022-04-01 06:53:42 +00:00
opengauss-bot 120ddcc6d8
!1654 【轻量级 PR】:修复CheckTimeout TimestampTz和float类型运算导致的精度丢失问题
Merge pull request !1654 from chenxiaobin/N/A
2022-04-01 06:17:39 +00:00
opengauss-bot 2cc80a5727
!1656 回滚pg_stat_get_wal_senders的升级
Merge pull request !1656 from 胡正超/master
2022-04-01 03:38:06 +00:00
gentle_hu 6d8bec171c revert upgrade of pg_stat_get_wal_senders() 2022-04-01 10:42:18 +08:00
chenxiaobin 9f7da01725
修复CheckTimeout TimestampTz和float类型运算导致的精度丢失问题 2022-04-01 02:17:51 +00:00
opengauss-bot ea938c947e
!1635 修复om安装时gs_guc设置 '' 给sync_standby_names解析错误的问题。
Merge pull request !1635 from 胡正超/anyxmaster
2022-03-31 14:53:24 +00:00
opengauss-bot 498d7ac08d
!1652 修复主备升级到3.0.0时失败的问题
Merge pull request !1652 from 胡正超/fixanyxupgrade
2022-03-31 14:33:55 +00:00
gentle_hu 40b717d9dd mv new column of pg_stat_get_wal_senders to tail 2022-03-31 21:29:49 +08:00
gentle_hu 94aeb766e5 fix issue of sync_standby_names='' 2022-03-31 20:08:33 +08:00
opengauss-bot 8577a61c7b
!1649 revert “发布订阅支持以二进制格式发送数据和主备切换不断开”
Merge pull request !1649 from 薛蒙恩/pubsub_revert
2022-03-31 11:33:59 +00:00
xue_meng_en 59db2a14cc Revert "发布订阅支持以二进制格式发送数据"
This reverts commit 71f53e575c.
2022-03-31 14:55:10 +08:00
xue_meng_en e7795cd01c Revert "发布订阅支持主备切换不断开"
This reverts commit aadf88ecc6.
2022-03-31 14:54:58 +08:00
106 changed files with 2068 additions and 612 deletions

View File

@ -1,4 +1,5 @@
#!/usr/bin/perl
#Again
use warnings;
use strict;

View File

@ -72,7 +72,7 @@ select_package_command
export PLAT_FORM_STR=$(sh "${ROOT_DIR}/src/get_PlatForm_str.sh")
if [ "${PLAT_FORM_STR}"x == "Failed"x -o "${PLAT_FORM_STR}"x == ""x ]
then
echo "We only support openEuler(aarch64), EulerOS(aarch64), CentOS, Kylin(aarch64) platform."
echo "We only support openEuler(aarch64), EulerOS(aarch64), CentOS, Kylin(aarch64), Asianux platform."
exit 1;
fi
@ -96,16 +96,21 @@ elif [[ "$PLAT_FORM_STR" =~ "kylin" ]]; then
if [ "$PLATFORM_ARCH"X == "aarch64"X ];then
GAUSSDB_EXTRA_FLAGS=" -D__USE_NUMA"
fi
elif [[ "$PLAT_FORM_STR" =~ "asianux" ]]; then
dist_version="Asianux"
if [ "$PLATFORM_ARCH"X == "aarch64"X ];then
GAUSSDB_EXTRA_FLAGS=" -D__USE_NUMA"
fi
else
echo "We only support openEuler(aarch64), EulerOS(aarch64), CentOS, Kylin(aarch64) platform."
echo "We only support openEuler(aarch64), EulerOS(aarch64), CentOS, Kylin(aarch64), Asianux platform."
echo "Kernel is $kernel"
exit 1
fi
##add platform architecture information
if [ "$PLATFORM_ARCH"X == "aarch64"X ] ; then
if [ "$dist_version" != "openEuler" ] && [ "$dist_version" != "EulerOS" ] && [ "$dist_version" != "Kylin" ] ; then
echo "We only support NUMA on openEuler(aarch64), EulerOS(aarch64), Kylin(aarch64) platform."
if [ "$dist_version" != "openEuler" ] && [ "$dist_version" != "EulerOS" ] && [ "$dist_version" != "Kylin" ] && [ "$dist_version" != "Asianux" ]; then
echo "We only support NUMA on openEuler(aarch64), EulerOS(aarch64), Kylin(aarch64), Asianux platform."
exit 1
fi
fi

View File

@ -26,6 +26,7 @@ Complete list of usable sgml source files in this directory.
<!ENTITY alterOperator SYSTEM "alter_operator.sgml">
<!ENTITY alterOperatorClass SYSTEM "alter_opclass.sgml">
<!ENTITY alterOperatorFamily SYSTEM "alter_opfamily.sgml">
<!ENTITY alterProcedure SYSTEM "alter_procedure.sgml">
<!ENTITY alterRole SYSTEM "alter_role.sgml">
<!ENTITY alterSchema SYSTEM "alter_schema.sgml">
<!ENTITY alterServer SYSTEM "alter_server.sgml">

View File

@ -0,0 +1,37 @@
<refentry id="sql-alterprocedure">
<indexterm zone="sql-alterprocedure">
<primary>ALTER PROCEDURE</primary>
</indexterm>
<refmeta>
<refentrytitle>ALTER PROCEDURE</refentrytitle>
<manvolnum>7</manvolnum>
<refmiscinfo>SQL - Language Statements</refmiscinfo>
</refmeta>
<refnamediv>
<refname>ALTER PROCEDURE</refname>
<refpurpose>change the definition of a procedure</refpurpose>
</refnamediv>
<refsynopsisdiv>
<synopsis>
ALTER PROCEDURE <replaceable>name</replaceable> [ ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">argname</replaceable> ] <replaceable class="parameter">argtype</replaceable> [, ...] ] ) ]
<replaceable class="parameter">action</replaceable> [ ... ] [ RESTRICT ]
ALTER PROCEDURE <replaceable>name</replaceable> [ ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">argname</replaceable> ] <replaceable class="parameter">argtype</replaceable> [, ...] ] ) ]
RENAME TO <replaceable>new_name</replaceable>
ALTER PROCEDURE <replaceable>name</replaceable> [ ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">argname</replaceable> ] <replaceable class="parameter">argtype</replaceable> [, ...] ] ) ]
OWNER TO { <replaceable>new_owner</replaceable> | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
ALTER PROCEDURE <replaceable>name</replaceable> [ ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">argname</replaceable> ] <replaceable class="parameter">argtype</replaceable> [, ...] ] ) ]
SET SCHEMA <replaceable>new_schema</replaceable>
<phrase>where <replaceable class="parameter">action</replaceable> is one of:</phrase>
[ EXTERNAL ] SECURITY INVOKER | [ EXTERNAL ] SECURITY DEFINER
SET <replaceable class="parameter">configuration_parameter</replaceable> { TO | = } { <replaceable class="parameter">value</replaceable> | DEFAULT }
SET <replaceable class="parameter">configuration_parameter</replaceable> FROM CURRENT
RESET <replaceable class="parameter">configuration_parameter</replaceable>
RESET ALL
</synopsis>
</refsynopsisdiv>
</refentry>

View File

@ -11,7 +11,7 @@
<refsynopsisdiv>
<synopsis>
DROP TABLE [ IF EXISTS ]
{[schema.]table_name} [, ...] [ CASCADE | RESTRICT ] [ PURGE ]};
{[schema.]table_name} [, ...] [ CASCADE | RESTRICT ] [ PURGE ];
</synopsis>
</refsynopsisdiv>
</refentry>

View File

@ -27,7 +27,14 @@
#include "securec_check.h"
#include "cipher.h"
#include "crypt.h"
/*
function name: crypt_malloc_zero
description: Distribute internal memory
arguments: An integer that designates the size of internal memory distributed
return value: A pointer of type void*
NoteIf the size of internal memory distributed is zero, it's unreasonable. The size should be greater than zero.
At the same time, if malloc fails, program would exit.
*/
void* crypt_malloc_zero(size_t size)
{
void* ret = NULL;

View File

@ -34,6 +34,14 @@
static int check_key_num(const char* password);
static void create_child_dir(const char* pathdir);
/*
function name: check_path
description: Check if the string delivered has the character that should not be included
arguments: A pointer to string that its type is const char
return value: void
Notenone
*/
void check_path(const char *path_name)
{
const char* danger_character_list[] = {"|",
@ -69,6 +77,14 @@ void check_path(const char *path_name)
}
}
/*
function name: check_key_num
description: Check if the password is a null string, if so, then the password is invalid.
At the same time, the function check if the length of password exceeds MAX_CRYPT_LEN, if so, print the error.
arguments: A pointer to string that its type is const char
return value: An integer that its type is static int
NoteThe length of password should not be zero, and never exceeds MAX_CRYPT_LEN
*/
static int check_key_num(const char* password)
{
int key_len = 0;
@ -84,6 +100,13 @@ static int check_key_num(const char* password)
return key_len;
}
/*
function name: create_child_dir
description:
arguments: A pointer to string that its type is const char
return value: static void
Note西
*/
static void create_child_dir(const char* pathdir)
{
if (pathdir == NULL) {

View File

@ -1229,6 +1229,12 @@ parse_next_sync_groups(char **pgroup, char *result)
static int
transform_az_name(char *config_value, char *allAZString, int allAZStringBufLen, const char *data_dir)
{
if (strcmp(config_value, "''") == 0) {
errno_t rc = strncpy_s(allAZString, allAZStringBufLen, config_value, strlen(config_value));
securec_check_c(rc, "\0", "\0");
return SUCCESS;
}
char *azString = NULL;
char *buf = allAZString;
int buflen = allAZStringBufLen;

View File

@ -5923,7 +5923,7 @@ int main(int argc, char** argv)
&option_index)) != -1)
#endif
#else
while ((c = getopt_long(argc, argv, "b:cD:e:fi:G:l:m:M:N:o:O:p:P:r:R:v:x:sS:t:u:U:wWZ:dqL:T:Q:", long_options,
while ((c = getopt_long(argc, argv, "b:cD:e:fi:G:l:m:M:N:o:O:p:P:r:R:v:x:sS:t:u:U:wWZ:C:dqL:T:Q:", long_options,
&option_index)) != -1)
#endif
#endif

View File

@ -233,7 +233,7 @@ char* all_data_nodename_list = NULL;
const uint32 USTORE_UPGRADE_VERSION = 92368;
const uint32 PACKAGE_ENHANCEMENT = 92444;
const uint32 SUBSCRIPTION_VERSION = 92580;
const uint32 SUBSCRIPTION_BINARY_VERSION_NUM = 92607;
const uint32 SUBSCRIPTION_BINARY_VERSION_NUM = 92606;
#ifdef DUMPSYSLOG
char* syslogpath = NULL;
@ -4454,16 +4454,7 @@ void getSubscriptions(Archive *fout)
}
if (!isExecUserSuperRole(fout)) {
res = ExecuteSqlQuery(fout,
"SELECT count(*) FROM pg_subscription "
"WHERE subdbid = (SELECT oid FROM pg_catalog.pg_database"
" WHERE datname = current_database())",
PGRES_TUPLES_OK);
uint64 n = (res != NULL) ? strtoul(PQgetvalue(res, 0, 0), NULL, 10) : 0;
if (n > 0) {
write_msg(NULL, "WARNING: subscriptions not dumped because current user is not a superuser\n");
}
PQclear(res);
write_msg(NULL, "WARNING: subscriptions not dumped because current user is not a superuser\n");
return;
}
@ -10795,6 +10786,11 @@ static void dumpDirectory(Archive* fout)
char* dirpath = NULL;
char* diracl = NULL;
if (!isExecUserSuperRole(fout)) {
write_msg(NULL, "WARNING: directory not dumped because current user is not a superuser\n");
return;
}
/* Make sure we are in proper schema */
selectSourceSchema(fout, "pg_catalog");
@ -21404,6 +21400,11 @@ static void dumpSynonym(Archive* fout)
PQExpBuffer q;
PQExpBuffer delq;
if (!isExecUserSuperRole(fout)) {
write_msg(NULL, "WARNING: synonym not dumped because current user is not a superuser\n");
return;
}
selectSourceSchema(fout, "pg_catalog");
query = createPQExpBuffer();
printfPQExpBuffer(query,

View File

@ -31,6 +31,9 @@
it will be backuped up in external dirs */
parray *pgdata_nobackup_dir = NULL;
/* list of logical replication slots */
parray *logical_replslot = NULL;
static int standby_message_timeout_local = 10 ; /* 10 sec = default */
static XLogRecPtr stop_backup_lsn = InvalidXLogRecPtr;
static XLogRecPtr stop_stream_lsn = InvalidXLogRecPtr;
@ -89,10 +92,11 @@ static void backup_cleanup(bool fatal, void *userdata);
static void *backup_files(void *arg);
static void do_backup_instance(PGconn *backup_conn, PGNodeInfo *nodeInfo, bool no_sync, bool backup_logs);
static void do_backup_instance(PGconn *backup_conn, PGNodeInfo *nodeInfo, bool no_sync, bool backup_logs,
bool backup_replslots);
static void pg_start_backup(const char *label, bool smooth, pgBackup *backup,
PGNodeInfo *nodeInfo, PGconn *conn);
PGNodeInfo *nodeInfo, PGconn *conn, bool backup_replslots);
static void pg_stop_backup(pgBackup *backup, PGconn *pg_startbackup_conn, PGNodeInfo *nodeInfo);
static int checkpoint_timeout(PGconn *backup_conn);
@ -558,7 +562,7 @@ static void sync_files(parray *database_map, const char *database_path, parray *
* Move files from 'pgdata' to a subdirectory in 'backup_path'.
*/
static void
do_backup_instance(PGconn *backup_conn, PGNodeInfo *nodeInfo, bool no_sync, bool backup_logs)
do_backup_instance(PGconn *backup_conn, PGNodeInfo *nodeInfo, bool no_sync, bool backup_logs, bool backup_replslots)
{
int i;
char database_path[MAXPGPATH];
@ -591,7 +595,7 @@ do_backup_instance(PGconn *backup_conn, PGNodeInfo *nodeInfo, bool no_sync, bool
securec_check_c(rc, "\0", "\0");
/* Call pg_start_backup function in openGauss connect */
pg_start_backup(label, smooth_checkpoint, &current, nodeInfo, backup_conn);
pg_start_backup(label, smooth_checkpoint, &current, nodeInfo, backup_conn, backup_replslots);
/* Obtain current timeline */
#if PG_VERSION_NUM >= 90600
@ -624,10 +628,10 @@ do_backup_instance(PGconn *backup_conn, PGNodeInfo *nodeInfo, bool no_sync, bool
/* list files with the logical path. omit $PGDATA */
if (fio_is_remote(FIO_DB_HOST))
fio_list_dir(backup_files_list, instance_config.pgdata,
true, true, false, backup_logs, true, 0);
true, true, false, backup_logs, true, 0, backup_replslots);
else
dir_list_file(backup_files_list, instance_config.pgdata,
true, true, false, backup_logs, true, 0, FIO_LOCAL_HOST);
true, true, false, backup_logs, true, 0, FIO_LOCAL_HOST, backup_replslots);
/*
* Get database_map (name to oid) for use in partial restore feature.
@ -749,6 +753,11 @@ do_backup_instance(PGconn *backup_conn, PGNodeInfo *nodeInfo, bool no_sync, bool
}
pgdata_nobackup_dir = NULL;
if (logical_replslot) {
free_dir_list(logical_replslot);
}
logical_replslot = NULL;
/* Cleanup */
if (backup_list)
{
@ -849,7 +858,7 @@ static void do_after_backup()
*/
int
do_backup(time_t start_time, pgSetBackupParams *set_backup_params,
bool no_validate, bool no_sync, bool backup_logs)
bool no_validate, bool no_sync, bool backup_logs, bool backup_replslots)
{
PGconn *backup_conn = NULL;
PGNodeInfo nodeInfo;
@ -925,7 +934,7 @@ do_backup(time_t start_time, pgSetBackupParams *set_backup_params,
add_note(&current, set_backup_params->note);
/* backup data */
do_backup_instance(backup_conn, &nodeInfo, no_sync, backup_logs);
do_backup_instance(backup_conn, &nodeInfo, no_sync, backup_logs, backup_replslots);
pgut_atexit_pop(backup_cleanup, NULL);
/* compute size of wal files of this backup stored in the archive */
@ -1034,13 +1043,15 @@ confirm_block_size(PGconn *conn, const char *name, int blcksz)
*/
static void
pg_start_backup(const char *label, bool smooth, pgBackup *backup,
PGNodeInfo *nodeInfo, PGconn *conn)
PGNodeInfo *nodeInfo, PGconn *conn, bool backup_replslots)
{
PGresult *res;
const char *params[2];
uint32 lsn_hi;
uint32 lsn_lo;
int ret;
int i;
XLogRecPtr startLsn;
params[0] = label;
@ -1068,7 +1079,33 @@ pg_start_backup(const char *label, bool smooth, pgBackup *backup,
XLogDataFromLSN(ret, PQgetvalue(res, 0, 0), &lsn_hi, &lsn_lo);
securec_check_for_sscanf_s(ret, 2, "\0", "\0");
/* Calculate LSN */
backup->start_lsn = ((uint64) lsn_hi )<< 32 | lsn_lo;
startLsn = ((uint64) lsn_hi )<< 32 | lsn_lo;
if (backup_replslots) {
logical_replslot = parray_new();
/* query for logical replication slots of subscriptions */
res = pgut_execute(conn,
"SELECT slot_name, restart_lsn FROM pg_catalog.pg_get_replication_slots()"
"WHERE slot_type = 'logical' AND plugin = 'pgoutput'", 0, NULL);
if (PQntuples(res) == 0) {
elog(LOG, "logical replication slots for subscriptions not found");
} else {
XLogRecPtr repslotLsn;
for (i = 0; i < PQntuples(res); i++) {
XLogDataFromLSN(ret, PQgetvalue(res, i, 1), &lsn_hi, &lsn_lo);
securec_check_for_sscanf_s(ret, 2, "\0", "\0");
repslotLsn = ((uint64) lsn_hi )<< 32 | lsn_lo;
startLsn = Min(startLsn, repslotLsn);
char* slotname = pg_strdup(PQgetvalue(res, i, 0));
parray_append(logical_replslot, slotname);
}
elog(WARNING, "logical replication slots for subscriptions will be backed up. "
"If don't use them after restoring, please drop them to avoid affecting xlog recycling.");
}
}
backup->start_lsn = startLsn;
PQclear(res);
}

View File

@ -42,13 +42,6 @@ const char *pgdata_exclude_dir[] =
(const char *)"pg_stat_tmp",
(const char *)"pgsql_tmp",
/*
* It is generally not useful to backup the contents of this directory even
* if the intention is to restore to another master. See backup.sgml for a
* more detailed description.
*/
(const char *)"pg_replslot",
/* Contents removed on startup, see dsm_cleanup_for_mmap(). */
(const char *)"pg_dynshmem",
@ -68,7 +61,7 @@ const char *pgdata_exclude_dir[] =
(const char *)"pg_subtrans",
/* end of list */
NULL, /* pg_log will be set later */
NULL, /* pg_log and pg_replslot will be set later */
NULL
};
@ -128,17 +121,20 @@ may be removed int the future */
static int pgCompareString(const void *str1, const void *str2);
static char dir_check_file(pgFile *file, bool backup_logs);
static char dir_check_file(pgFile *file, bool backup_logs, bool backup_replslots);
static char check_in_tablespace(pgFile *file, bool in_tablespace);
static char check_db_dir(pgFile *file);
static char check_digit_file(pgFile *file);
static char check_nobackup_dir(pgFile *file);
static void dir_list_file_internal(parray *files, pgFile *parent, const char *parent_dir,
bool exclude, bool follow_symlink, bool backup_logs,
bool skip_hidden, int external_dir_num, fio_location location);
bool skip_hidden, int external_dir_num, fio_location location,
bool backup_replslots);
static void opt_path_map(ConfigOption *opt, const char *arg,
TablespaceList *list, const char *type);
char check_logical_replslot_dir(const char *rel_path);
/* Tablespace mapping */
static TablespaceList tablespace_dirs = {NULL, NULL};
/* Extra directories mapping */
@ -538,7 +534,7 @@ db_map_entry_free(void *entry)
void
dir_list_file(parray *files, const char *root, bool exclude, bool follow_symlink,
bool add_root, bool backup_logs, bool skip_hidden, int external_dir_num,
fio_location location)
fio_location location, bool backup_replslots)
{
pgFile *file;
@ -565,7 +561,7 @@ dir_list_file(parray *files, const char *root, bool exclude, bool follow_symlink
parray_append(files, file);
dir_list_file_internal(files, file, root, exclude, follow_symlink,
backup_logs, skip_hidden, external_dir_num, location);
backup_logs, skip_hidden, external_dir_num, location, backup_replslots);
if (!add_root)
pgFileFree(file);
@ -589,7 +585,7 @@ dir_list_file(parray *files, const char *root, bool exclude, bool follow_symlink
* - datafiles
*/
static char
dir_check_file(pgFile *file, bool backup_logs)
dir_check_file(pgFile *file, bool backup_logs, bool backup_replslots)
{
int i;
int sscanf_res;
@ -652,6 +648,29 @@ dir_check_file(pgFile *file, bool backup_logs)
}
}
/*
* Backup pg_replslot if it is specified.
* It is generally not useful to backup the contents of this directory even
* if the intention is to restore to another master. See backup.sgml for a
* more detailed description.
*/
if (!backup_replslots) {
if (strcmp(file->rel_path, PG_REPLSLOT_DIR) == 0) {
/* Skip */
elog(VERBOSE, "Excluding directory content: %s", file->rel_path);
return CHECK_EXCLUDE_FALSE;
}
} else {
/*
* Check file that under pg_replslot and judge whether it
* belonged to logical replication slots for subscriptions.
*/
if (strcmp(file->rel_path, PG_REPLSLOT_DIR) != 0 &&
path_is_prefix_of_path(PG_REPLSLOT_DIR, file->rel_path)) {
return check_logical_replslot_dir(file->rel_path);
}
}
ret = check_nobackup_dir(file);
if (ret != -1) { /* -1 means need backup */
return ret;
@ -749,6 +768,35 @@ static char check_nobackup_dir(pgFile *file)
return ret;
}
char check_logical_replslot_dir(const char *rel_path)
{
char ret = CHECK_FALSE;
int i = 0;
char *tmp = pg_strdup(rel_path);
char *p;
#define DIRECTORY_DELIMITER "/"
if (logical_replslot) {
/* extract slot name from rel_path, such as sub1 from pg_replslot/sub1/snap */
p = strtok(tmp, DIRECTORY_DELIMITER);
if (p != NULL) {
p = strtok(NULL, DIRECTORY_DELIMITER);
}
for (i = 0; p != NULL && i < (int)parray_num(logical_replslot); i++) {
char *slotName = (char *)parray_get(logical_replslot, i);
if (strcmp(p, slotName) == 0) {
pfree(tmp);
return CHECK_TRUE;
}
}
} else {
ret = CHECK_TRUE;
}
pfree(tmp);
return ret;
}
static char check_db_dir(pgFile *file)
{
char ret = -1;
@ -889,7 +937,8 @@ bool SkipSomeDirFile(pgFile *file, struct dirent *dent, bool skipHidden)
static void
dir_list_file_internal(parray *files, pgFile *parent, const char *parent_dir,
bool exclude, bool follow_symlink, bool backup_logs,
bool skip_hidden, int external_dir_num, fio_location location)
bool skip_hidden, int external_dir_num, fio_location location,
bool backup_replslots)
{
DIR *dir;
struct dirent *dent;
@ -937,7 +986,7 @@ dir_list_file_internal(parray *files, pgFile *parent, const char *parent_dir,
if (exclude)
{
check_res = dir_check_file(file, backup_logs);
check_res = dir_check_file(file, backup_logs, backup_replslots);
if (check_res == CHECK_FALSE)
{
/* Skip */
@ -963,7 +1012,7 @@ dir_list_file_internal(parray *files, pgFile *parent, const char *parent_dir,
*/
if (S_ISDIR(file->mode))
dir_list_file_internal(files, file, child, exclude, follow_symlink,
backup_logs, skip_hidden, external_dir_num, location);
backup_logs, skip_hidden, external_dir_num, location, backup_replslots);
}
if (errno && errno != ENOENT)

View File

@ -51,6 +51,7 @@ typedef struct
bool exclusive_backup;
bool skip_hidden;
int external_dir_num;
bool backup_replslots;
} fio_list_dir_request;
typedef struct
@ -1794,7 +1795,7 @@ cleanup:
/* Compile the array of files located on remote machine in directory root */
void fio_list_dir(parray *files, const char *root, bool exclude,
bool follow_symlink, bool add_root, bool backup_logs,
bool skip_hidden, int external_dir_num)
bool skip_hidden, int external_dir_num, bool backup_replslots)
{
fio_header hdr;
fio_list_dir_request req;
@ -1811,6 +1812,7 @@ void fio_list_dir(parray *files, const char *root, bool exclude,
req.exclusive_backup = exclusive_backup;
req.skip_hidden = skip_hidden;
req.external_dir_num = external_dir_num;
req.backup_replslots = backup_replslots;
hdr.cop = FIO_LIST_DIR;
hdr.size = sizeof(req);
@ -1870,7 +1872,14 @@ void fio_list_dir(parray *files, const char *root, bool exclude,
securec_check_ss_c(nRet, "\0", "\0");
}
/*
* Check file that under pg_replslot and judge whether it
* belonged to logical replication slots for subscriptions.
*/
if (backup_replslots && strcmp(buf, PG_REPLSLOT_DIR) != 0 &&
path_is_prefix_of_path(PG_REPLSLOT_DIR, buf) && check_logical_replslot_dir(file->rel_path) != 1) {
continue;
}
parray_append(files, file);
}
@ -1914,7 +1923,7 @@ static void fio_list_dir_impl(int out, char* buf)
dir_list_file(file_files, req->path, req->exclude, req->follow_symlink,
req->add_root, req->backup_logs, req->skip_hidden,
req->external_dir_num, FIO_LOCAL_HOST);
req->external_dir_num, FIO_LOCAL_HOST, req->backup_replslots);
/* send information about files to the main process */
for (i = 0; i < (int)parray_num(file_files); i++)

View File

@ -163,5 +163,7 @@ extern z_off_t fio_gzseek(gzFile f, z_off_t offset, int whence);
extern const char* fio_gzerror(gzFile file, int *errnum);
#endif
extern char check_logical_replslot_dir(const char *rel_path);
#endif

View File

@ -154,6 +154,7 @@ void help_pg_probackup(void)
printf(_(" [--remote-port=port] [--ssh-options=ssh_options]\n"));
printf(_(" [--remote-libpath=libpath]\n"));
printf(_(" [--ttl=interval] [--expire-time=time]\n"));
printf(_(" [--backup-pg-replslot]\n"));
printf(_(" [--help]\n"));
printf(_("\n %s restore -B backup-path --instance=instance_name\n"), PROGRAM_NAME);
@ -420,6 +421,7 @@ static void help_backup(void)
printf(_(" [--remote-port=port] [--ssh-options=ssh_options]\n"));
printf(_(" [--remote-libpath=libpath]\n"));
printf(_(" [--ttl=interval] [--expire-time=time]\n\n"));
printf(_(" [--backup-pg-replslot]\n"));
printf(_(" -B, --backup-path=backup-path location of the backup storage area\n"));
printf(_(" --instance=instance_name name of the instance\n"));
@ -441,6 +443,7 @@ static void help_backup(void)
printf(_(" --note=text add note to backup\n"));
printf(_(" (example: --note='backup before app update to v13.1')\n"));
printf(_(" --archive-timeout=timeout wait timeout for WAL segment archiving (default: 5min)\n"));
printf(_(" --backup-pg-replslot] backup of '%s' directory\n"), PG_REPLSLOT_DIR);
printf(_("\n Logging options:\n"));
printf(_(" --log-level-console=log-level-console\n"));

View File

@ -77,6 +77,7 @@ int rw_timeout = 0;
/* backup options */
bool backup_logs = false;
bool backup_replslots = false;
bool smooth_checkpoint;
char *remote_agent;
static char *backup_note = NULL;
@ -186,6 +187,7 @@ static ConfigOption cmd_options[] =
{ 'b', 145, "wal", &delete_wal, SOURCE_CMD_STRICT },
{ 'b', 146, "expired", &delete_expired, SOURCE_CMD_STRICT },
{ 's', 172, "status", &delete_status, SOURCE_CMD_STRICT },
{ 'b', 186, "backup-pg-replslot", &backup_replslots, SOURCE_CMD_STRICT},
{ 'b', 147, "force", &force, SOURCE_CMD_STRICT },
{ 'b', 148, "compress", &compress_shortcut, SOURCE_CMD_STRICT },
@ -550,7 +552,7 @@ static int do_actual_operate()
elog(ERROR, "required parameter not specified: BACKUP_MODE "
"(-b, --backup-mode)");
return do_backup(start_time, set_backup_params, no_validate, no_sync, backup_logs);
return do_backup(start_time, set_backup_params, no_validate, no_sync, backup_logs, backup_replslots);
}
case RESTORE_CMD:
return do_restore_or_validate(current.backup_id,

View File

@ -69,6 +69,7 @@ extern const char *PROGRAM_FULL_PATH;
#define HEADER_MAP "page_header_map"
#define HEADER_MAP_TMP "page_header_map_tmp"
#define PG_RELATIVE_TBLSPC_DIR "pg_location"
#define PG_REPLSLOT_DIR "pg_replslot"
/* Timeout defaults */
#define ARCHIVE_TIMEOUT_DEFAULT 300

View File

@ -54,6 +54,9 @@ extern bool smooth_checkpoint;
it will be backuped up in external dirs */
extern parray *pgdata_nobackup_dir;
/* list of logical replication slots */
extern parray *logical_replslot;
/* remote probackup options */
extern char* remote_agent;
@ -89,7 +92,7 @@ extern const char *pgdata_exclude_dir[];
/* in backup.c */
extern int do_backup(time_t start_time, pgSetBackupParams *set_backup_params,
bool no_validate, bool no_sync, bool backup_logs);
bool no_validate, bool no_sync, bool backup_logs, bool backup_replslots);
extern BackupMode parse_backup_mode(const char *value);
extern const char *deparse_backup_mode(BackupMode mode);
extern void process_block_change(ForkNumber forknum, const RelFileNode rnode,
@ -239,7 +242,8 @@ extern const char* deparse_compress_alg(int alg);
/* in dir.c */
extern void dir_list_file(parray *files, const char *root, bool exclude,
bool follow_symlink, bool add_root, bool backup_logs,
bool skip_hidden, int external_dir_num, fio_location location);
bool skip_hidden, int external_dir_num, fio_location location,
bool backup_replslots = false);
extern void create_data_directories(parray *dest_files,
const char *data_dir,
@ -432,7 +436,8 @@ extern int fio_send_file(const char *from_fullpath, const char *to_fullpath, FIL
pgFile *file, char **errormsg);
extern void fio_list_dir(parray *files, const char *root, bool exclude, bool follow_symlink,
bool add_root, bool backup_logs, bool skip_hidden, int external_dir_num);
bool add_root, bool backup_logs, bool skip_hidden, int external_dir_num,
bool backup_replslots = false);
extern bool pgut_rmtree(const char *path, bool rmtopdir, bool strict);

View File

@ -8641,7 +8641,7 @@
),
AddFuncGroup(
"pg_stat_get_wal_senders", 1,
AddBuiltinFunc(_0(3099), _1("pg_stat_get_wal_senders"), _2(0), _3(false), _4(true), _5(pg_stat_get_wal_senders), _6(2249), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(10), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('s'), _19(0), _20(0), _21(22, 20, 23, 25, 25, 25, 25, 1184, 1184, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 23, 23, 25, 25), _22(22, 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o'), _23(22, "pid", "sender_pid", "local_role", "peer_role", "peer_state", "state", "catchup_start", "catchup_end", "sender_sent_location", "sender_write_location", "sender_flush_location", "sender_replay_location", "receiver_received_location", "receiver_write_location", "receiver_flush_location", "receiver_replay_location", "sync_percent", "sync_state", "sync_group", "sync_priority", "sync_most_available", "channel"), _24(NULL), _25("pg_stat_get_wal_senders"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33("statistics: information about currently active replication"), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0))
AddBuiltinFunc(_0(3099), _1("pg_stat_get_wal_senders"), _2(0), _3(false), _4(true), _5(pg_stat_get_wal_senders), _6(2249), _7(PG_CATALOG_NAMESPACE), _8(BOOTSTRAP_SUPERUSERID), _9(INTERNALlanguageId), _10(1), _11(10), _12(0), _13(0), _14(false), _15(false), _16(false), _17(false), _18('s'), _19(0), _20(0), _21(21, 20, 23, 25, 25, 25, 25, 1184, 1184, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 23, 25, 25), _22(21, 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o', 'o'), _23(21, "pid", "sender_pid", "local_role", "peer_role", "peer_state", "state", "catchup_start", "catchup_end", "sender_sent_location", "sender_write_location", "sender_flush_location", "sender_replay_location", "receiver_received_location", "receiver_write_location", "receiver_flush_location", "receiver_replay_location", "sync_percent", "sync_state", "sync_priority", "sync_most_available", "channel"), _24(NULL), _25("pg_stat_get_wal_senders"), _26(NULL), _27(NULL), _28(NULL), _29(0), _30(false), _31(NULL), _32(false), _33("statistics: information about currently active replication"), _34('f'), _35(NULL), _36(0), _37(false), _38(NULL), _39(NULL), _40(0))
),
AddFuncGroup(
"pg_stat_get_wlm_ec_operator_info", 1,

View File

@ -6230,7 +6230,7 @@ Datum GetPartBoundaryByTuple(Relation rel, HeapTuple tuple)
return Timestamp2Boundarys(rel, Align2UpBoundary(value, partMap->intervalValue, boundaryTs));
}
Oid AddNewIntervalPartition(Relation rel, void* insertTuple)
Oid AddNewIntervalPartition(Relation rel, void* insertTuple, bool isDDL)
{
Relation pgPartRel = NULL;
Oid newPartOid = InvalidOid;
@ -6327,7 +6327,13 @@ Oid AddNewIntervalPartition(Relation rel, void* insertTuple)
*/
CommandCounterIncrement();
UpdatePgObjectChangecsn(RelationGetRelid(rel), rel->rd_rel->relkind);
/*
* If add interval partition in the DDL, do not need to change the csn
* because the scn has been changed in the DDL.
*/
if (!isDDL) {
UpdatePgObjectChangecsn(RelationGetRelid(rel), rel->rd_rel->relkind);
}
return newPartOid;
}
@ -7113,7 +7119,7 @@ int lookupHBucketid(oidvector *buckets, int low, int2 bktId)
* Description :
* Notes :
*/
Oid heapTupleGetPartitionId(Relation rel, void *tuple)
Oid heapTupleGetPartitionId(Relation rel, void *tuple, bool isDDL)
{
Oid partitionid = InvalidOid;
@ -7140,7 +7146,7 @@ Oid heapTupleGetPartitionId(Relation rel, void *tuple)
(errcode(ERRCODE_NO_DATA_FOUND), errmsg("inserted partition key does not map to any table partition")));
} break;
case PART_AREA_INTERVAL: {
return AddNewIntervalPartition(rel, tuple);
return AddNewIntervalPartition(rel, tuple, isDDL);
} break;
case PART_AREA_LIST: {
ereport(ERROR,

View File

@ -47,7 +47,8 @@ static void InternalAggIsSupported(const char *aggName)
"json_agg",
"json_object_agg",
"st_summarystatsagg",
"st_union"
"st_union",
"wm_concat"
};
uint len = lengthof(supportList);

View File

@ -52,7 +52,7 @@ static_assert(sizeof(false) == sizeof(char), "illegal bool size");
static struct HTAB* nameHash = NULL;
static struct HTAB* oidHash = NULL;
/* for b_sql_plugin */
/* for dolphin */
struct HTAB* b_nameHash = NULL;
struct HTAB* b_oidHash = NULL;
@ -118,7 +118,7 @@ static const FuncGroup* NameHashTableAccess(HASHACTION action, const char* name,
Assert(name != NULL);
if (DB_IS_CMPT(B_FORMAT) && b_nameHash != NULL && u_sess->attr.attr_sql.b_sql_plugin) {
if (DB_IS_CMPT(B_FORMAT) && b_nameHash != NULL && u_sess->attr.attr_sql.dolphin) {
result = (HashEntryNameToFuncGroup *)hash_search(b_nameHash, &temp_name, action, &found);
} else {
result = (HashEntryNameToFuncGroup *)hash_search(nameHash, &temp_name, action, &found);
@ -144,7 +144,7 @@ static const Builtin_func* OidHashTableAccess(HASHACTION action, Oid oid, const
bool found = false;
Assert(oid > 0);
if (DB_IS_CMPT(B_FORMAT) && b_oidHash != NULL && u_sess->attr.attr_sql.b_sql_plugin) {
if (DB_IS_CMPT(B_FORMAT) && b_oidHash != NULL && u_sess->attr.attr_sql.dolphin) {
result = (HashEntryOidToBuiltinFunc *)hash_search(b_oidHash, &oid, action, &found);
} else {
result = (HashEntryOidToBuiltinFunc *)hash_search(oidHash, &oid, action, &found);

View File

@ -68,7 +68,7 @@ Subscription *GetSubscription(Oid subid, bool missing_ok)
/* Get slotname */
datum = SysCacheGetAttr(SUBSCRIPTIONOID, tup, Anum_pg_subscription_subslotname, &isnull);
if (unlikely(isnull)) {
if (!isnull) {
sub->slotname = pstrdup(NameStr(*DatumGetName(datum)));
} else {
sub->slotname = NULL;
@ -92,10 +92,10 @@ Subscription *GetSubscription(Oid subid, bool missing_ok)
datum = SysCacheGetAttr(SUBSCRIPTIONOID, tup, Anum_pg_subscription_subbinary, &isnull);
if (unlikely(isnull)) {
ereport(ERROR, (errcode(ERRCODE_UNEXPECTED_NULL_VALUE),
errmsg("null binary for subscription %u", subid)));
sub->binary = false;
} else {
sub->binary = DatumGetBool(datum);
}
sub->binary = DatumGetBool(datum);
ReleaseSysCache(tup);

View File

@ -70,6 +70,7 @@
THR_LOCAL bool skip_read_extern_fields = false;
#define IS_DATANODE_BUT_NOT_SINGLENODE (IS_PGXC_DATANODE && !IS_SINGLE_NODE)
/*
* Macros to simplify reading of different kinds of fields. Use these
* wherever possible to reduce the chance for silly typos. Note that these
@ -401,24 +402,27 @@ THR_LOCAL bool skip_read_extern_fields = false;
token = pg_strtok(&length); /* skip :fldname */ \
local_node->fldname = _readBitmapset()
#define READ_TYPEINFO_FIELD(fldname) \
do { \
if (local_node->fldname >= FirstBootstrapObjectId) { \
IF_EXIST(exprtypename) \
{ \
char* exprtypename = NULL; \
char* exprtypenamespace = NULL; \
token = pg_strtok(&length); \
token = pg_strtok(&length); \
exprtypename = nullable_string(token, length); \
token = pg_strtok(&length); \
token = pg_strtok(&length); \
exprtypenamespace = nullable_string(token, length); \
local_node->fldname = get_typeoid(get_namespace_oid(exprtypenamespace, false), exprtypename); \
pfree_ext(exprtypename); \
pfree_ext(exprtypenamespace); \
} \
} \
#define READ_TYPEINFO_FIELD(fldname) \
do { \
if (local_node->fldname >= FirstBootstrapObjectId) { \
IF_EXIST(exprtypename) \
{ \
char* exprtypename = NULL; \
char* exprtypenamespace = NULL; \
token = pg_strtok(&length); \
token = pg_strtok(&length); \
exprtypename = nullable_string(token, length); \
token = pg_strtok(&length); \
token = pg_strtok(&length); \
exprtypenamespace = nullable_string(token, length); \
/* No need to reset field on CN or singlenode, keep pg_strtok() for forward compatibility */ \
if (IS_DATANODE_BUT_NOT_SINGLENODE) { \
local_node->fldname = get_typeoid(get_namespace_oid(exprtypenamespace, false), exprtypename); \
} \
pfree_ext(exprtypename); \
pfree_ext(exprtypenamespace); \
} \
} \
} while (0)
#define READ_TYPEINFO(typePtr) \
@ -493,9 +497,30 @@ THR_LOCAL bool skip_read_extern_fields = false;
token = pg_strtok(&length); \
token = pg_strtok(&length); \
funcnamespace = nullable_string(token, length); \
if (IS_PGXC_DATANODE && !skip_read_extern_fields) { \
local_node->fldname = \
get_func_oid(funcname, get_namespace_oid(funcnamespace, false), (Expr*)local_node); \
bool notfound = false; \
if (IS_DATANODE_BUT_NOT_SINGLENODE && !skip_read_extern_fields) { \
Oid funcoid = InvalidOid; \
do { \
Oid nspid = get_namespace_oid(funcnamespace, true); \
if (!OidIsValid(nspid)) { \
notfound = true; \
break; \
} \
funcoid = get_func_oid(funcname, nspid, (Expr*)local_node); \
} while (0); \
if (notfound || !OidIsValid(funcoid)) { \
ereport(ERROR, \
(errmodule(MOD_OPT), errcode(ERRCODE_UNDEFINED_OBJECT), \
errmsg("Cannot identify function %s.%s while deserializing field.", \
funcname, funcnamespace), \
errdetail("Function with oid %u or its namespace may be renamed", \
local_node->fldname), \
errhint("Please rebuild column defalt expression, views etc. that are" \
" related to this renamed object."), \
errcause("Object renamed after recorded as nodetree."), \
erraction("Rebuild relevant object."))); \
} \
local_node->fldname = funcoid; \
} \
pfree_ext(funcname); \
pfree_ext(funcnamespace); \
@ -525,7 +550,7 @@ THR_LOCAL bool skip_read_extern_fields = false;
token = pg_strtok(&length); \
token = pg_strtok(&length); \
oprrightname = nullable_string(token, length); \
if (IS_PGXC_DATANODE) { \
if (IS_DATANODE_BUT_NOT_SINGLENODE) { \
namespaceId = get_namespace_oid(opnamespace, false); \
oprleft = get_typeoid(namespaceId, oprleftname); \
oprright = oprleft; \
@ -568,7 +593,7 @@ THR_LOCAL bool skip_read_extern_fields = false;
token = pg_strtok(&length); \
token = pg_strtok(&length); \
oprrightname = nullable_string(token, length); \
if (IS_PGXC_DATANODE) { \
if (IS_DATANODE_BUT_NOT_SINGLENODE) { \
namespaceId = get_namespace_oid(opnamespace, false); \
oprleft = get_typeoid(namespaceId, oprleftname); \
oprright = oprleft; \
@ -2126,14 +2151,21 @@ static FuncExpr* _readFuncExpr(void)
ereport(ERROR, (errcode(ERRCODE_UNEXPECTED_NULL_VALUE), errmsg("NULL seqNamespace for nextval()")));
}
if (!IS_PGXC_COORDINATOR && !skip_read_extern_fields) {
Oid seqid = get_valid_relname_relid(seqNamespace, seqName);
if (IS_DATANODE_BUT_NOT_SINGLENODE && !skip_read_extern_fields) {
Oid seqid = get_valid_relname_relid(seqNamespace, seqName, true);
Const* firstArg = (Const*)linitial(local_node->args);
if (OidIsValid(seqid)) {
Const* firstArg = (Const*)linitial(local_node->args);
if (firstArg != NULL) {
firstArg->constvalue = ObjectIdGetDatum(seqid);
}
} else {
ereport(ERROR, (errmodule(MOD_OPT), errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("Cannot identify sequence %s.%s while deserializing field.", seqNamespace, seqName),
errdetail("Sequence with oid %u or its namespace may be renamed",
DatumGetObjectId(firstArg->constvalue)),
errhint("Please rebuild column defalt expression, views etc. that are related to this sequence"),
errcause("Object renamed after recorded as nodetree."), erraction("Rebuild relevant object.")));
}
}
pfree_ext(seqName);

View File

@ -1,90 +1,52 @@
/* -------------------------------------------------------------------------
*
* kwlookup.cpp
* lexical token lookup for key words in openGauss
*
* NB - this file is also used by ECPG and several frontend programs in
* src/bin/ including pg_dump and psql
*
* Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* src/common/backend/parser/kwlookup.cpp
*
* -------------------------------------------------------------------------
*/
/* use c.h so this can be built as either frontend or backend */
#include "c.h"
#include <ctype.h>
#include "parser/keywords.h"
/*
* ScanKeywordLookup - see if a given word is a keyword
*
* Returns a pointer to the ScanKeyword table entry, or NULL if no match.
*
* The match is done case-insensitively. Note that we deliberately use a
* dumbed-down case conversion that will only translate 'A'-'Z' into 'a'-'z',
* even if we are in a locale where tolower() would produce more or different
* translations. This is to conform to the SQL99 spec, which says that
* keywords are to be matched in this way even though non-keyword identifiers
* receive a different case-normalization mapping.
*/
//返回指向ScanKeyword表项的指针如果不匹配则返回NULL。
/* 匹配是不区分大小写的。注意,我们故意使用简化的大小写转换,只将'A'-' Z'翻译成'a'-' z'即使我们在tolower()会产生更多或不同的翻译。这是为了符合SQL99规范该规范规定即使非关键字标识符接收不同的大小写规范化映射也要以这种方式匹配关键字。*/
//用于判断信息的关键字从而将关键词返回为具体的token给程序
const ScanKeyword* ScanKeywordLookup(const char* text, const ScanKeyword* keywords, int num_keywords)
{
int len, i;
char word[NAMEDATALEN] = {0};
const ScanKeyword* low = NULL;
const ScanKeyword* high = NULL;
if (text == NULL) {
return NULL;
}
len = strlen(text);
/* We assume all keywords are shorter than NAMEDATALEN. */
/* 我们假设所有关键字都比NAMEDATALEN短。 */
if (len >= NAMEDATALEN) {
return NULL;
}
/*
* Apply an ASCII-only downcasing. We must not use tolower() since it may
* produce the wrong translation in some locales (eg, Turkish).
ascII的下标使tolower()()
*/
for (i = 0; i < len; i++) {
char ch = text[i];
if (ch >= 'A' && ch <= 'Z') {
ch += 'a' - 'A';
}
word[i] = ch;
}
word[len] = '\0';
/*
* Now do a binary search using plain strcmp() comparison.
*使strcmp()
*/
low = keywords;
high = keywords + (num_keywords - 1);
while (low <= high) {
const ScanKeyword* middle = NULL;
int difference;
middle = low + (high - low) / 2;
difference = strcmp(middle->name, word);
if (difference == 0) {
return middle;
} else if (difference < 0) {
}
//如果middle->name比word短返回-1
else if (difference < 0) {
low = middle + 1;
} else {
}
//如果middle->name比word长返回1
else {
high = middle - 1;
}
}
return NULL;
}
}

View File

@ -1454,7 +1454,14 @@ FuncCandidateList sort_candidate_func_list(FuncCandidateList oldCandidates)
}
candidates[smallestIndex] = NULL;
}
for (int i = 0; i < size; i++) {
if (candidates[i] != NULL) {
lastCandidate->next = candidates[i];
lastCandidate = lastCandidate->next;
}
}
lastCandidate->next = NULL;
pfree(candidates);
return sortedCandidates;
}

View File

@ -43,76 +43,57 @@ char* scanstr(const char* s)
newStr = (char*)palloc(len + 1); /* string cannot get longer */
for (i = 0, j = 0; i < len; i++) {
if (s[i] == '\'') {
/*
* Note: if scanner is working right, unescaped quotes can only
* appear in pairs, so there should be another character.
*/
i++;
newStr[j] = s[i];
} else if (s[i] == '\\') {
i++;
switch (s[i]) {
case 'b':
newStr[j] = '\b';
break;
case 'f':
newStr[j] = '\f';
break;
case 'n':
newStr[j] = '\n';
break;
case 'r':
newStr[j] = '\r';
break;
case 't':
newStr[j] = '\t';
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7': {
int k;
unsigned long octVal = 0;
for (i = 0, j = 0; i < len; i++) {
if (s[i] == '\'') {
i++;
newStr[j] = s[i];//说明不是转义字符
} else if (s[i] == '\\') {
i++;
switch (s[i]) {
case 'b':
newStr[j] = '\b';
break;
case 'f':
newStr[j] = '\f';
break;
case 'n':
newStr[j] = '\n';
break;
case 'r':
newStr[j] = '\r';
break;
case 't':
newStr[j] = '\t';
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7': {
int k;
unsigned long octVal = 0;
for (k = 0; s[i + k] >= '0' && s[i + k] <= '7' && k < 3; k++){
octVal = (octVal << 3) + (s[i + k] - '0');
}
i += k - 1;
newStr[j] = ((char)octVal);
} break;
default:
newStr[j] = s[i];
break;
} /* switch */
} /* s[i] == '\\' */
else {
newStr[j] = s[i];
}
j++;
}
newStr[j] = '\0';
for (k = 0; s[i + k] >= '0' && s[i + k] <= '7' && k < 3; k++){
octVal = (octVal << 3) + (s[i + k] - '0');
}
i += k - 1;
newStr[j] = ((char)octVal);
} break;
default:
newStr[j] = s[i];
break;
} /* switch */
} /* s[i] == '\\' */
else {
newStr[j] = s[i];
}
j++;
}
newStr[j] = '\0';
return newStr;
}
/*
* downcase_truncate_identifier() --- do appropriate downcasing and
* truncation of an unquoted identifier. Optionally warn of truncation.
*
* Returns a palloc'd string containing the adjusted identifier.
*
* Note: in some usages the passed string is not null-terminated.
*
* Note: the API of this function is designed to allow for downcasing
* transformations that increase the string length, but we don't yet
* support that. If you want to implement it, you'll need to fix
* SplitIdentifierString() in utils/adt/varlena.c.
*/
//对未加引号的标识符进行适当的大小写转换和截断。可选的截断警告。
char* downcase_truncate_identifier(const char* ident, int len, bool warn)
{
char* result = NULL;
@ -180,15 +161,8 @@ void truncate_identifier(char* ident, int len, bool warn)
}
}
/*
* scanner_isspace() --- return TRUE if flex scanner considers char whitespace
*
* This should be used instead of the potentially locale-dependent isspace()
* function when it's important to match the lexer's behavior.
*
* In principle we might need similar functions for isalnum etc, but for the
* moment only isspace seems needed.
*/
// 如果flex scanner识别出字符空白则返回TRUE
bool scanner_isspace(char ch)
{
/* This must match scan.l's list of {space} characters */

View File

@ -61,7 +61,7 @@ void GlobalBaseDefCache::RemoveElemFromBucket(GlobalBaseEntry *base)
if (is_relation) {
GlobalRelationEntry *entry = (GlobalRelationEntry *)base;
uint64 rel_size = GetRelEstimateSize(entry);
pg_atomic_fetch_sub_u64(&m_base_space, rel_size);
pg_atomic_fetch_sub_u64(&m_base_space, AllocSetContextUsedSpace(((AllocSet)entry->rel_mem_manager)));
m_db_entry->MemoryEstimateSub(rel_size);
} else {
GlobalPartitionEntry *entry = (GlobalPartitionEntry *)base;
@ -77,7 +77,7 @@ void GlobalBaseDefCache::AddHeadToBucket(Index hash_index, GlobalBaseEntry *base
if (is_relation) {
GlobalRelationEntry *entry = (GlobalRelationEntry *)base;
uint64 rel_size = GetRelEstimateSize(entry);
pg_atomic_fetch_add_u64(&m_base_space, rel_size);
pg_atomic_fetch_add_u64(&m_base_space, AllocSetContextUsedSpace(((AllocSet)entry->rel_mem_manager)));
m_db_entry->MemoryEstimateAdd(rel_size);
} else {
GlobalPartitionEntry *entry = (GlobalPartitionEntry *)base;
@ -400,4 +400,4 @@ GlobalBaseDefCache::GlobalBaseDefCache(Oid db_oid, bool is_shared, GlobalSysDBCa
m_base_space = 0;
m_obj_locks = NULL;
m_db_entry = entry;
}
}

View File

@ -659,7 +659,27 @@ void GlobalSysDBCache::InitSysCacheRelIds()
*/
void GlobalSysDBCache::RefreshHotStandby()
{
if (!EnableGlobalSysCache()) {
return;
}
hot_standby = (t_thrd.postmaster_cxt.HaShmData->current_mode != STANDBY_MODE || XLogStandbyInfoActive());
if (hot_standby || !m_is_inited) {
return;
}
/* clean all */
for (int hash_index = 0; hash_index < m_nbuckets; hash_index ++) {
PthreadRWlockRdlock(LOCAL_SYSDB_RESOWNER, &m_db_locks[hash_index]);
for (Dlelem * elt = DLGetTail(m_bucket_list.GetBucket(hash_index)); elt != NULL;) {
GlobalSysDBCacheEntry *entry = (GlobalSysDBCacheEntry *)DLE_VAL(elt);
elt = DLGetPred(elt);
entry->ResetDBCache<true>();
}
PthreadRWlockUnlock(LOCAL_SYSDB_RESOWNER, &m_db_locks[hash_index]);
}
if (m_global_shared_db_entry != NULL) {
m_global_shared_db_entry->ResetDBCache<true>();
}
}
void GlobalSysDBCache::Init(MemoryContext parent)
@ -1272,9 +1292,18 @@ int ResizeHashBucket(int origin_nbucket, DynamicHashBucketStrategy strategy)
return cc_nbuckets;
}
void NotifyGscRecoveryStarted()
{
if (!EnableGlobalSysCache()) {
return;
}
g_instance.global_sysdbcache.recovery_finished = false;
}
void NotifyGscRecoveryFinished()
{
if (EnableGlobalSysCache()) {
g_instance.global_sysdbcache.recovery_finished = true;
}
}
}

View File

@ -183,7 +183,7 @@ void GlobalSysTabCache::InvalidTuples(int cache_id, uint32 hash_value, bool rese
/* maybe upgrade from version before v5r2c00, the cacheid is out of order
* whatever, we cache nothing except relmap, so just ignore the catcache invalmsg */
if (unlikely(!g_instance.global_sysdbcache.recovery_finished) && m_global_systupcaches[cache_id] == NULL) {
if (unlikely(!g_instance.global_sysdbcache.recovery_finished && m_global_systupcaches[cache_id] == NULL)) {
return;
}

View File

@ -74,7 +74,7 @@ Partition LocalPartDefCache::SearchPartitionFromGlobalCopy(Oid part_oid)
if (!g_instance.global_sysdbcache.hot_standby) {
return NULL;
}
if (unlikely(!g_instance.global_sysdbcache.recovery_finished)) {
if (unlikely(!IsPrimaryRecoveryFinished())) {
return NULL;
}
uint32 hash_value = oid_hash((void *)&(part_oid), sizeof(Oid));
@ -165,7 +165,7 @@ static bool IsPartOidStoreInGlobal(Oid part_oid)
if (!g_instance.global_sysdbcache.hot_standby) {
return false;
}
if (unlikely(!g_instance.global_sysdbcache.recovery_finished)) {
if (unlikely(!IsPrimaryRecoveryFinished())) {
return false;
}
if (g_instance.global_sysdbcache.StopInsertGSC()) {
@ -456,4 +456,4 @@ Partition LocalPartDefCache::PartitionIdGetPartition(Oid part_oid, StorageType s
}
return pd;
}
}

View File

@ -433,7 +433,7 @@ LocalCatCTup *LocalSysTupCache::SearchTupleFromGlobal(Datum *arguments, uint32 h
bool bypass_gsc = HistoricSnapshotActive() ||
m_global_systupcache->enable_rls ||
!g_instance.global_sysdbcache.hot_standby ||
unlikely(!g_instance.global_sysdbcache.recovery_finished);
unlikely(!IsPrimaryRecoveryFinished());
if (invalid_entries.ExistTuple(hash_value) || bypass_gsc) {
global_ct = m_global_systupcache->SearchTupleFromFile(hash_value, arguments, true);
} else {
@ -585,7 +585,7 @@ LocalCatCList *LocalSysTupCache::SearchListFromGlobal(int nkeys, Datum *argument
bool bypass_gsc = HistoricSnapshotActive() ||
m_global_systupcache->enable_rls ||
!g_instance.global_sysdbcache.hot_standby ||
unlikely(!g_instance.global_sysdbcache.recovery_finished);
unlikely(!IsPrimaryRecoveryFinished());
GlobalCatCList *global_cl;
if (invalid_entries.ExistList() || bypass_gsc) {
global_cl = m_global_systupcache->SearchListFromFile(hash_value, nkeys, arguments, true);
@ -703,7 +703,7 @@ LocalCatCTup *LocalSysTupCache::SearchTupleFromGlobalForProcAllArgs(
bool bypass_gsc = HistoricSnapshotActive() ||
m_global_systupcache->enable_rls ||
!g_instance.global_sysdbcache.hot_standby ||
unlikely(!g_instance.global_sysdbcache.recovery_finished);
unlikely(!IsPrimaryRecoveryFinished());
if (invalid_entries.ExistTuple(hash_value) || bypass_gsc) {
global_ct = m_global_systupcache->SearchTupleFromFileWithArgModes(hash_value, arguments, argModes, true);
} else {

View File

@ -93,7 +93,7 @@ Relation LocalTabDefCache::SearchRelationFromGlobalCopy(Oid rel_oid)
if (!g_instance.global_sysdbcache.hot_standby) {
return NULL;
}
if (unlikely(!g_instance.global_sysdbcache.recovery_finished)) {
if (unlikely(!IsPrimaryRecoveryFinished())) {
return NULL;
}
uint32 hash_value = oid_hash((void *)&(rel_oid), sizeof(Oid));
@ -190,7 +190,7 @@ static bool IsRelOidStoreInGlobal(Oid rel_oid)
if (!g_instance.global_sysdbcache.hot_standby) {
return false;
}
if (unlikely(!g_instance.global_sysdbcache.recovery_finished)) {
if (unlikely(!IsPrimaryRecoveryFinished())) {
return false;
}
if (g_instance.global_sysdbcache.StopInsertGSC()) {
@ -1137,4 +1137,4 @@ void LocalTabDefCache::ResetInitFlag()
m_is_inited_phase3 = false;
m_db_id = InvalidOid;
}
}

View File

@ -1723,7 +1723,7 @@ char* get_relname_relid_extend(
extern bool StreamTopConsumerAmI();
/* same as get_relname_relid except we check for cache invalidation here */
Oid get_valid_relname_relid(const char* relnamespace, const char* relname)
Oid get_valid_relname_relid(const char* relnamespace, const char* relname, bool nsp_missing_ok)
{
Oid nspid = InvalidOid;
Oid oldnspid = InvalidOid;
@ -1747,7 +1747,10 @@ Oid get_valid_relname_relid(const char* relnamespace, const char* relname)
if (EnableLocalSysCache()) {
thrd_inval_count = t_thrd.lsc_cxt.lsc->inval_cxt.SIMCounter;
}
nspid = get_namespace_oid(relnamespace, false);
nspid = get_namespace_oid(relnamespace, nsp_missing_ok);
if (!OidIsValid(nspid)) {
return InvalidOid;
}
relid = get_relname_relid(relname, nspid);
/*
* In bootstrap processing mode, we don't bother with locking

View File

@ -59,7 +59,7 @@ bool open_join_children = true;
bool will_shutdown = false;
/* hard-wired binary version number */
const uint32 GRAND_VERSION_NUM = 92607;
const uint32 GRAND_VERSION_NUM = 92606;
const uint32 PREDPUSH_SAME_LEVEL_VERSION_NUM = 92522;
const uint32 UPSERT_WHERE_VERSION_NUM = 92514;
@ -101,7 +101,7 @@ const uint32 PRIVS_DIRECTORY_VERSION_NUM = 92460;
const uint32 COMMENT_RECORD_PARAM_VERSION_NUM = 92484;
const uint32 SCAN_BATCH_MODE_VERSION_NUM = 92568;
const uint32 PUBLICATION_VERSION_NUM = 92580;
const uint32 SUBSCRIPTION_BINARY_VERSION_NUM = 92607;
const uint32 SUBSCRIPTION_BINARY_VERSION_NUM = 92606;
/* Version number of the guc parameter backend_version added in V500R001C20 */
const uint32 V5R1C20_BACKEND_VERSION_NUM = 92305;

View File

@ -2712,8 +2712,8 @@ void PostgresInitializer::InitExtensionVariable()
}
/* check whether the extension has been created */
const char* b_sql_plugin = "b_sql_plugin";
u_sess->attr.attr_sql.b_sql_plugin = CheckIfExtensionExists(b_sql_plugin);
const char* dolphin = "dolphin";
u_sess->attr.attr_sql.dolphin = CheckIfExtensionExists(dolphin);
}
void PostgresInitializer::FinishInit()

View File

@ -10340,7 +10340,16 @@ check_sql_expr(const char *stmt, int location, int leaderlen)
oldCxt = MemoryContextSwitchTo(u_sess->plsql_cxt.curr_compile_context->compile_tmp_cxt);
u_sess->plsql_cxt.plpgsql_yylloc = plpgsql_yylloc;
(void) raw_parser(stmt);
RawParserHook parser_hook= raw_parser;
#ifndef ENABLE_MULTIPLE_NODES
if (u_sess->attr.attr_sql.dolphin) {
int id = GetCustomParserId();
if (id >= 0 && g_instance.raw_parser_hook[id] != NULL) {
parser_hook = (RawParserHook)g_instance.raw_parser_hook[id];
}
}
#endif
(void)parser_hook(stmt, NULL);
MemoryContextSwitchTo(oldCxt);
/* Restore former ereport callback */

View File

@ -44,11 +44,22 @@ static int g_iPosBlackList = 0;
/* array store for black list */
static BBOX_BLACKLIST_STRU g_stBlackList[BBOX_BLACK_LIST_COUNT_MAX];
/*
* Determines whether the byte order of the local machine is large or small
* return : ELFDATA2LSB - large
* : ELFDATA2MSB - small
*/
/*
function name: BBOX_DetermineMsb
description: The function should judge the mode that PC uses to store data is Big-endian/Little-endian.
arguments: void
return value: An integer that indicates the mode is Big-endian/Little-endian,
if it is ELFDATA2LSB, the mode is Little-endian,
if it is ELFDATA2MSB, the mode is Big-endian.
noteThe way that this function judge the mode that PC uses to store data is through a union variable unProbe,
at first we give its first member variable sShortInt a value BBOX_MSB_LSB_INT of type short, then its second
member variable cSplit[sizeof(short)] equaling to cSplit[2] would have the equal value of the first. Finally we
just need to compare BBOX_LITTER_BITS and BBOX_HIGH_BITS, namely the low byte and high byte of
BBOX_MSB_LSB_INT, with unProbe.cSplit[0] and unProbe.cSplit[1], if they are correspondingly equal, the mode is
Little-endian, else is the Big-endian.
date: 2022/8/2
contact tel: 18720816902
*/
int BBOX_DetermineMsb(void)
{
union INT_PROBE {

View File

@ -51,8 +51,19 @@ struct PIPE_IDS {
static struct PIPE_IDS astPipeIds[BBOX_MAX_PIDS];
/*
* compare string pszSrc and pszTarget
*/
function name: bbox_strncmp
description: To compare two substrings, the pointers pszSrc and pszTarget store their host strings'addresses.
arguments: Two pointers of type const char*, pointing to two strings needed to be compared.
An integer indicates the number of characters at the former of two strings that
will be compared.
return value: Type s32, an interger.
If it's zero, then the former substrings of string pszSrc and pszTarget are same,
else it indicates the difference between the first two characters that these two
strings can't match.
noteThe two pointers shouldn't be null. The last argument shouldn't less than zero.
date: 2022/8/2
contact tel: 18720816902
*/
s32 bbox_strncmp(const char* pszSrc, const char* pszTarget, s32 count)
{
signed char cRes = 0;
@ -68,8 +79,20 @@ s32 bbox_strncmp(const char* pszSrc, const char* pszTarget, s32 count)
}
/*
* compare string pszSrc and pszTarget
*/
function name: bbox_strcmp
description: compare two strings, the pointer pszSrc and pszTarget store their addresses.
arguments: Two pointers of type const char*, pointing to two strings needed to be compared.
An integer indicates the number of characters at the former of two strings that
will be compared.
return value: Type s32, an interger.
If it's zero, then the former substrings of string pszSrc and pszTarget are same,
else if it's 1, then it indicates between first two characters that these two
strings can't match, the character of first string that pszSrc points is greater,
else if it's -1, the character of second string that pszTarget points is greater.
noteThe two pointers shouldn't be null. The last argument shouldn't less than zero.
date: 2022/8/2
contact tel:same
*/
s32 bbox_strcmp(const char* pszSrc, const char* pszTarget)
{
unsigned char c1, c2;
@ -90,8 +113,15 @@ s32 bbox_strcmp(const char* pszSrc, const char* pszTarget)
}
/*
* get the length of string pszString
*/
function name: bbox_strlen
description: Calculate the length of string.
arguments: An pointer that indicates the address of a string.
return value: Type s32, an integer indicating the length of string.
note: the length of string=(address of the last character not '\0'-address of the first character)/sizeof(char), and sizeof(char)
equals to 1, so the length of string=(address of the last character not '\0'-address of the first character).
date: 2022/8/2
contact tel:same
*/
s32 bbox_strlen(const char* pszString)
{
const char* pszTemp = NULL;
@ -105,8 +135,16 @@ s32 bbox_strlen(const char* pszString)
}
/*
* get the length of string pszString
*/
function name: bbox_strnlen
description: Calculate the length of string, but having some restrictive conditions.
arguments: An pointer that indicates the address of a string.
And an integer that indicates the maxlenth.
return value: Type s32, an integer indicating the length of string.
note: If the length of string exceed the argument count, then return the length of string,
else return the argument count.
date: 2022/8/2
contact tel:same
*/
s32 bbox_strnlen(const char* pszString, s32 count)
{
const char* pszTemp = NULL;
@ -119,8 +157,16 @@ s32 bbox_strnlen(const char* pszString, s32 count)
}
/*
* convert a string to interger
*/
function name: bbox_atoi
description: Convert a string that includes continuous digital characters to an integer,
if the first character of the string is '-', then we will return a negative result.
arguments: An pointer that indicates the address of a string.
return value: Type s32, an integer indicating the result of string converted.
note: I think the function isn't perfect, though it's not a core function. For example, what about
the condition that the first character of the string is '+'?
date: 2022/8/2
contact tel:same
*/
s32 bbox_atoi(const char* pszString)
{
s32 n = 0;
@ -140,10 +186,18 @@ s32 bbox_atoi(const char* pszString)
return iNeg ? -n : n;
}
/*
* compare memory
*/
function name: bbox_memcmp
description: Compare former count bytes in ASCII of data stored in two areas that pointers cs and ct direct.
arguments: Two pointers to areas of memory, and an integer indicating the max counts compared.
return value: Type s32, an integer.
If the value returned is 0, then the data stored in two areas destined are same,
else if is 1, then between two first data in ASCII of byte different, cs's is greater,
else if is -1, then ct's is greater.
note: The two pointers should not be null, it's dangerous.
date: 2022/8/2
contact tel: same
*/
s32 bbox_memcmp(const void* cs, const void* ct, s32 count)
{
const unsigned char *su1 = NULL;
@ -159,8 +213,18 @@ s32 bbox_memcmp(const void* cs, const void* ct, s32 count)
}
/*
* search string l2 in l1
*/
function name: bbox_strstr
description: Judge if the string s2 directs is substring of string s1 directs.
arguments: Two pointers of type const char*, pointing to two strings.
return value: Type char*, a pointer. Actually it's a address, if s2 directs a
null string, then return the address of the first character of s1,
if the string s2 directs isn't substring of string s1 directs, return
null, if the string s2 directs is substring of string s1 directs, then return
the address of first character matched.
note: The two pointers should not be null, it's dangerous.
date: 2022/8/2
contact tel: same
*/
char* bbox_strstr(const char* s1, const char* s2)
{
int l1, l2;
@ -182,8 +246,17 @@ char* bbox_strstr(const char* s1, const char* s2)
}
/*
* make a directory
*/
function name: bbox_mkdir
description: We distinguish parent directory and child directory through character '/',
normally through a for loop, we can make sure all directories above the directory
we want to creat exist, finally we will creat the flag directory after its parent.
arguments: A pointers of type const char*, pointing to one strings, which indicates the filename and its full path.
return value: An integer of type s32, if it's RET_ERR, then we fail to make a directory, else if it's RET_OK then we succeed.
note: Take care the last non-null character of the string needed to be '/', and once if flag directory's
ancestors aren't exist, the function return RET_ERR.
date: 2022/8/2
contact tel: same
*/
s32 bbox_mkdir(const char* pszDir)
{
char szDirName[BBOX_TMP_LEN_32 * 16];
@ -228,8 +301,16 @@ s32 bbox_mkdir(const char* pszDir)
}
/*
* search free pipe id
*/
function name: bbox_GetFreePid
description: Through a for loop, we search a free pipe in a structure array, to an array element if its
member variable isUsed's value is 0, we return the array element's another member variable
stPid's address.
arguments: void
return value: An pointer of type struct PIPE_ID* or NULL.
note: none
date: 2022/8/2
contact tel: same
*/
struct PIPE_ID* bbox_GetFreePid(void)
{
u32 i;
@ -245,8 +326,14 @@ struct PIPE_ID* bbox_GetFreePid(void)
}
/*
* Release the occupied pipeid
*/
function name: bbox_PutPid
description: Release the occupied pipe.
arguments: A pointer of type struct PIPE_ID*.
return value: void
note: If the argument pointer is null, then there is no need to free the storage, the function ends.
date: 2022/8/2
contact tel: same
*/
void bbox_PutPid(struct PIPE_ID* pstPid)
{
struct PIPE_IDS* pstPids = NULL;
@ -261,8 +348,16 @@ void bbox_PutPid(struct PIPE_ID* pstPid)
}
/*
* find available pipe id by file handle
*/
function name: bbox_FindPid
description: In all occupied pipes, the function search the flag pipe through compare all structure
array elements's member variable stPid's member variable iFd with the function
argument iFd, if they are equal, then return the addres of this array elements.
arguments: An integer that indicates a file's file handle.
return value: A pointer of type struct PIPE_ID* or NULL.
note: none
date: 2022/8/2
contact tel: same
*/
struct PIPE_ID* bbox_FindPid(int iFd)
{
u32 i;
@ -281,8 +376,17 @@ struct PIPE_ID* bbox_FindPid(int iFd)
}
/*
* run popen
*/
function name: sys_popen
description: The function gets a free pipe by function bbox_GetFreePid, if normally, then creat a pipe
through sys_pipe, andcreat a child process through function sys_fork, execute a shell command
to run a process.
arguments: One pointer to a string that represents command line, another pointer of type const char*
indicates that the file file handle directs is used in the this mode.
return value: A pointer of type struct PIPE_ID* or NULL.
note: The string that indicates pszMode should only be "r" or "w",
date: 2022/8/2
contact tel: same
*/
s32 sys_popen(char* pszCmd, const char* pszMode)
{
struct PIPE_ID* volatile stCurPid = NULL;
@ -387,8 +491,15 @@ s32 sys_popen(char* pszCmd, const char* pszMode)
}
/*
* close file handle
*/
function name: sys_pclose
description: The function has an contrary action to function sys_popen, it close the pipe
that sys_popen open.
arguments: iFd, an integer that indicates a file handle.
return value: An integer that indicates the final status of the process working before.
note: none
date: 2022/8/2
contact tel: same
*/
int sys_pclose(s32 iFd)
{
struct PIPE_ID* pstCur = NULL;
@ -411,8 +522,17 @@ int sys_pclose(s32 iFd)
}
/*
* list file in directory
*/
function name: bbox_listdir
description: The function list all files below this path in directory.
arguments: The first argument is a pointer to a string representing a file path, all files below
this path will be listed in directory. The second argument is a pointer to a callback
function. The last is a pointer of type void*, it indicates a command line.
return value: An integer that indicates the result of function, if normal, it's RET_OK, else
it's RET_ERR.
note: The path that the first argument represents should be absolute path, take care.
date: 2022/8/2
contact tel: same
*/
s32 bbox_listdir(const char* pstPath, BBOX_LIST_DIR_CALLBACK callback, void* pArgs)
{
struct linux_dirent* pstEntry = NULL;

View File

@ -57,23 +57,37 @@ void bbox_initlog(int iLogScreen)
}
/*
* convert int to string
*/
function name: bbox_itoc
description: Convert an integer to a character.
arguments: An integer needed to be converted.
return value: An character that corresponds to the function's integer argument.
note: The integer argument can be converted in radices more than decimalism.
date: 2022/8/2
contact tel: 18720816902
*/
inline char bbox_itoc(u8 sNum)
{
return (char)((sNum < 10) ? (sNum + 48) : (sNum + 87));
}
/*
* convert int to string
* in : pCallback - call back function
* ptr - private data to call this function
* piCount - offset pointer
* iSize - buffer size
* uNum - the variable to convert
* sSys - type of variable
* isNeg - is negative
* return : need call back
*/
function name: bbox_put_dox
description: Conversion of number systems.
arguments: The first argument pCallback is a pointer to a callback function, we
use it to reverse the final result. The second argument is a pointer of
type void* used as a argument of function pCallback. The third argument
piCount is a pointer of type int, an offset pointer, also be used as a argument
of pCallback. The fourth argument is an integer of 32 bits, it indicates the buffer
size pCallback uses.The fifth argument uNum is a decimal integer that will
be converted to an integer in another radix. The sixth argument is used as
base to conversion of number systems. The last argument indicates the integer
after converted is a negative integer or not.
return value: An integer, indicating if the function pCallback work successfully.
note: The argument uNum should be a positive integer, after conversion of number systems
the sign will be appended to string's tail.
date: 2022/8/2
contact tel: 18720816902
*/
s32 bbox_put_dox(BBOX_vnprintCallBack pCallback, void* ptr, s32* piCount, u32 iSize, u64 uNum, s32 sSys, s32 isNeg)
{
s64 i = 0;
@ -114,7 +128,7 @@ s32 bbox_put_dox(BBOX_vnprintCallBack pCallback, void* ptr, s32* piCount, u32 iS
* ptr - private data to call this function
* iSize - buffer size
* pFmt - format type
* ap - parameter list pointer¸ñʽ
* ap - parameter list pointer<EFBFBD><EFBFBD>ʽ
* return : length of string
*/
s32 bbox_vsnprintf(BBOX_vnprintCallBack pCallback, void* ptr, s32 iSize, const char* pFmt, va_list ap)

View File

@ -222,6 +222,7 @@ NON_EXEC_STATIC void PercentileMain()
g_instance.stat_cxt.force_process = false;
sleep(SLEEP_INTERVAL);
}
elog(LOG, "instrumention percentile ended");
gs_thread_exit(0);
}

View File

@ -14,11 +14,23 @@ import os
from . import feature_mapping
from . import features
# To import file feature_mapping and features from parent folder
#function name: load_feature_lib
#description: Print the variable FEATURE_LIB in the file-- features
#return value: The value of FEATURE_LIB
#date: 2022/8/2
#contact: 1865997821
def load_feature_lib():
return features.FEATURE_LIB
#function name: get_feature_mapper
#description: Get the item and value of a dictionary type in the file-- feature_mapping and output it as a generator.
#return value: The item and value in _dict_ variable
#noteDictionary key-value pairs must start with C then the item and value will be return.
#date: 2022/8/2
#contact: 1865997821
def get_feature_mapper():
return {

View File

@ -11,22 +11,27 @@
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
# See the Mulan PSL v2 for more details.
import csv
#import csv packet
from collections import defaultdict
from typing import List
# To import defaultdict in the parent floder collections and List in the parent floder typing
import numpy as np
# import numpy packet as the name np
from ..analyzer import _euclid_distance as euclid_distance
from dbmind.common.utils import ExceptionCatch
#To import private function-- _euclid_distance as euclid_distance
#function name: calculate_weight
#description: This function will output feature_weight (= residual_vector / the sum of residual_vector)
#The data used for the calculation is from the features_labels_dict, and the key value pairs of the features_labels_dict are filtered
#arguments: np.ndarray and np.ndarray
#return value: weight_matrix
#date: 2022/8/2
#contact: 1865997821
def calculate_weight(features: np.ndarray, labels: np.ndarray) -> List:
"""
Calculate weight matrix based on feature set
:param features: feature set
:param labels: label set
:return: weight_matrix
"""
normalize_features, normalize_labels = [], []
features_labels_dict = defaultdict(list)
for i in range(len(labels)):
@ -56,6 +61,16 @@ def calculate_weight(features: np.ndarray, labels: np.ndarray) -> List:
return weight_matrix
# function name: build_model
# description: Create two variables-- features and labels.There are refer to two numpy array(all elements are zero)
# The features array's size is feature_number and dimension is feature_dimension
# This function will read the two arrays and write it as a matrix in a csv file(the save path is './features_new.npz')
# And then it will call the function calculate_weight to calculate the matrix
# arguments: feature_path, feature_number, feature_dimension
# return value: None
# noteA ExceptionCatch function modifier is used
# date: 2022/8/2
#contact: 1865997821
@ExceptionCatch(strategy='exit', name='FEATURE')
def build_model(feature_path: str, feature_number: int, feature_dimension: int,
save_path: str = './features_new.npz') -> None:

View File

@ -11,6 +11,13 @@
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
# See the Mulan PSL v2 for more details.
#function name: detect
#description: if the method is "bool" type, then call the functions sum_detect、avg_detect、ks_detect to diagnose errors
#These functions are in the parent slow_sql/significance_detection
#arguments: data1(array), data2(array), method
#return value: bool type
#date: 2022/8/2
#contact: 1865997821
def detect(data1, data2, method='bool', threshold=0.01, p_value=0.5):
if method == 'bool':

View File

@ -12,17 +12,16 @@
# See the Mulan PSL v2 for more details.
alpha = 1e-10
#Define a minimum number of errors
#function name: detect
#description: Calculate whether the data has abrupt changes based on the average value
#arguments: data1, data2, threshold,method
#return value: bool
#date: 2022/8/
#contact: 1865997821
def detect(data1, data2, threshold=0.5, method='bool'):
"""
Calculate whether the data has abrupt changes based on the average value
:param data1: input data array
:param data2: input data array
:param threshold: Mutation rate
:param method: The way to calculate the mutation
:return: bool
"""
if not isinstance(data1, list) or not isinstance(data2, list):
raise TypeError("The format of the input data is wrong.")
avg1 = sum(data1) / len(data1) if data1 else 0

View File

@ -26,9 +26,11 @@ import logging
try:
from .dao.gsql_execute import GSqlExecute
from .dao.execute_factory import ExecuteFactory
from .mcts import MCTS
except ImportError:
from dao.gsql_execute import GSqlExecute
from dao.execute_factory import ExecuteFactory
from mcts import MCTS
ENABLE_MULTI_NODE = False
SAMPLE_NUM = 5
@ -192,9 +194,12 @@ class IndexAdvisor:
self.workload_used_index))
if DRIVER:
self.db.close_conn()
opt_config = greedy_determine_opt_config(self.workload_info[0], atomic_config_total,
candidate_indexes, self.index_cost_total[0])
if MAX_INDEX_STORAGE:
opt_config = MCTS(self.workload_info[0], atomic_config_total, candidate_indexes,
MAX_INDEX_STORAGE, MAX_INDEX_NUM)
else:
opt_config = greedy_determine_opt_config(self.workload_info[0], atomic_config_total,
candidate_indexes, self.index_cost_total[0])
self.retain_lower_cost_index(candidate_indexes)
if len(opt_config) == 0:
print("No optimal indexes generated!")
@ -943,7 +948,7 @@ def check_parameter(args):
raise argparse.ArgumentTypeError("%s is an invalid positive int value" %
args.max_index_num)
if args.max_index_storage is not None and args.max_index_storage <= 0:
raise argparse.ArgumentTypeError("%s is an invalid positive int value" %
raise argparse.ArgumentTypeError("%s is an invalid positive float value" %
args.max_index_storage)
JSON_TYPE = args.json
MAX_INDEX_NUM = args.max_index_num
@ -971,7 +976,7 @@ def main(argv):
arg_parser.add_argument(
"--max_index_num", help="Maximum number of suggested indexes", type=int)
arg_parser.add_argument("--max_index_storage",
help="Maximum storage of suggested indexes/MB", type=int)
help="Maximum storage of suggested indexes/MB", type=float)
arg_parser.add_argument("--multi_iter_mode", action='store_true',
help="Whether to use multi-iteration algorithm", default=False)
arg_parser.add_argument("--multi_node", action='store_true',

View File

@ -0,0 +1,397 @@
import sys
import math
import random
import copy
STORAGE_THRESHOLD = 0
AVAILABLE_CHOICES = None
ATOMIC_CHOICES = None
WORKLOAD_INFO = None
MAX_INDEX_NUM = 0
def is_same_index(index, compared_index):
return index.table == compared_index.table and \
index.columns == compared_index.columns and \
index.index_type == compared_index.index_type
def atomic_config_is_valid(atomic_config, config):
# if candidate indexes contains all atomic index of current config1, then record it
for atomic_index in atomic_config:
is_exist = False
for index in config:
if is_same_index(index, atomic_index):
index.storage = atomic_index.storage
is_exist = True
break
if not is_exist:
return False
return True
def find_subsets_num(choice):
atomic_subsets_num = []
for pos, atomic in enumerate(ATOMIC_CHOICES):
if not atomic or len(atomic) > len(choice):
continue
# find valid atomic index
if atomic_config_is_valid(atomic, choice):
atomic_subsets_num.append(pos)
# find the same atomic index as the candidate index
if len(atomic) == 1 and (is_same_index(choice[-1], atomic[0])):
choice[-1].atomic_pos = pos
return atomic_subsets_num
def find_best_benefit(choice):
atomic_subsets_num = find_subsets_num(choice)
total_benefit = 0
for ind, obj in enumerate(WORKLOAD_INFO):
# calculate the best benefit for the current sql
max_benefit = 0
for pos in atomic_subsets_num:
if (obj.cost_list[0] - obj.cost_list[pos]) > max_benefit:
max_benefit = obj.cost_list[0] - obj.cost_list[pos]
total_benefit += max_benefit
return total_benefit
def get_diff(available_choices, choices):
except_choices = copy.copy(available_choices)
for i in available_choices:
for j in choices:
if is_same_index(i, j):
except_choices.remove(i)
return except_choices
class State(object):
"""
The game state of the Monte Carlo tree search,
the state data recorded under a certain Node node,
including the current game score, the current number of game rounds,
and the execution record from the beginning to the current.
It is necessary to realize whether the current state has reached the end of the game state,
and support the operation of randomly fetching from the Action collection.
"""
def __init__(self):
self.current_storage = 0.0
self.current_benefit = 0.0
# record the sum of choices up to the current state
self.accumulation_choices = []
# record available choices of current state
self.available_choices = []
self.displayable_choices = []
def get_available_choices(self):
return self.available_choices
def set_available_choices(self, choices):
self.available_choices = choices
def get_current_storage(self):
return self.current_storage
def set_current_storage(self, value):
self.current_storage = value
def get_current_benefit(self):
return self.current_benefit
def set_current_benefit(self, value):
self.current_benefit = value
def get_accumulation_choices(self):
return self.accumulation_choices
def set_accumulation_choices(self, choices):
self.accumulation_choices = choices
def is_terminal(self):
# the current node is a leaf node
return len(self.accumulation_choices) == MAX_INDEX_NUM
def compute_benefit(self):
return self.current_benefit
def get_next_state_with_random_choice(self):
# ensure that the choices taken are not repeated
if not self.available_choices:
return None
random_choice = random.choice([choice for choice in self.available_choices])
self.available_choices.remove(random_choice)
choice = copy.copy(self.accumulation_choices)
choice.append(random_choice)
benefit = find_best_benefit(choice)
# if current choice not satisfy restrictions, then continue get next choice
if benefit <= self.current_benefit or \
self.current_storage + random_choice.storage > STORAGE_THRESHOLD:
return self.get_next_state_with_random_choice()
next_state = State()
# initialize the properties of the new state
next_state.set_accumulation_choices(choice)
next_state.set_current_benefit(benefit)
next_state.set_current_storage(self.current_storage + random_choice.storage)
next_state.set_available_choices(get_diff(AVAILABLE_CHOICES, choice))
return next_state
def __repr__(self):
self.displayable_choices = ['{}: {}'.format(choice.table, choice.columns)
for choice in self.accumulation_choices]
return "reward: {}, storage :{}, choices: {}".format(
self.current_benefit, self.current_storage, self.displayable_choices)
class Node(object):
"""
The Node of the Monte Carlo tree search tree contains the parent node and
current point information,
which is used to calculate the traversal times and quality value of the UCB,
and the State of the Node selected by the game.
"""
def __init__(self):
self.visit_number = 0
self.quality = 0.0
self.parent = None
self.children = []
self.state = None
def get_parent(self):
return self.parent
def set_parent(self, parent):
self.parent = parent
def get_children(self):
return self.children
def expand_child(self, node):
node.set_parent(self)
self.children.append(node)
def set_state(self, state):
self.state = state
def get_state(self):
return self.state
def get_visit_number(self):
return self.visit_number
def set_visit_number(self, number):
self.visit_number = number
def update_visit_number(self):
self.visit_number += 1
def get_quality_value(self):
return self.quality
def set_quality_value(self, value):
self.quality = value
def update_quality_value(self, reward):
self.quality += reward
def is_all_expand(self):
return len(self.children) == \
len(AVAILABLE_CHOICES) - len(self.get_state().get_accumulation_choices())
def __repr__(self):
return "Node: {}, Q/N: {}/{}, State: {}".format(
hash(self), self.quality, self.visit_number, self.state)
def tree_policy(node):
"""
In the Selection and Expansion stages of Monte Carlo tree search,
the node that needs to be searched (such as the root node) is passed in,
and the best node that needs to be expanded is returned
according to the exploration/exploitation algorithm.
Note that if the node is a leaf node, it will be returned directly.
The basic strategy is to first find the child nodes that have not been selected at present,
and select them randomly if there are more than one. If both are selected,
find the one with the largest UCB value that has weighed exploration/exploitation,
and randomly select if the UCB values are equal.
"""
# check if the current node is leaf node
while node and not node.get_state().is_terminal():
if node.is_all_expand():
node = best_child(node, True)
else:
# return the new sub node
sub_node = expand(node)
# when there is no node that satisfies the condition in the remaining nodes,
# this state is empty
if sub_node.get_state():
return sub_node
# return the leaf node
return node
def default_policy(node):
"""
In the Simulation stage of Monte Carlo tree search, input a node that needs to be expanded,
create a new node after random operation, and return the reward of the new node.
Note that the input node should not be a child node,
and there are unexecuted Actions that can be expendable.
The basic strategy is to choose the Action at random.
"""
# get the state of the game
current_state = copy.deepcopy(node.get_state())
# run until the game over
while not current_state.is_terminal():
# pick one random action to play and get next state
next_state = current_state.get_next_state_with_random_choice()
if not next_state:
break
current_state = next_state
final_state_reward = current_state.compute_benefit()
return final_state_reward
def expand(node):
"""
Enter a node, expand a new node on the node, use the random method to execute the Action,
and return the new node. Note that it is necessary to ensure that the newly
added nodes are different from other node Action
"""
new_state = node.get_state().get_next_state_with_random_choice()
sub_node = Node()
sub_node.set_state(new_state)
node.expand_child(sub_node)
return sub_node
def best_child(node, is_exploration):
"""
Using the UCB algorithm,
select the child node with the highest score after weighing the exploration and exploitation.
Note that if it is the prediction stage,
the current Q-value score with the highest score is directly selected.
"""
best_score = -sys.maxsize
best_sub_node = None
# travel all sub nodes to find the best one
for sub_node in node.get_children():
# The children nodes of the node contains the children node whose state is empty,
# this kind of node comes from the node that does not meet the conditions.
if not sub_node.get_state():
continue
# ignore exploration for inference
if is_exploration:
C = 1 / math.sqrt(2.0)
else:
C = 0.0
# UCB = quality / times + C * sqrt(2 * ln(total_times) / times)
left = sub_node.get_quality_value() / sub_node.get_visit_number()
right = 2.0 * math.log(node.get_visit_number()) / sub_node.get_visit_number()
score = left + C * math.sqrt(right)
# get the maximum score, while filtering nodes that do not meet the space constraints and
# nodes that have no revenue
if score > best_score \
and sub_node.get_state().get_current_storage() <= STORAGE_THRESHOLD \
and sub_node.get_state().get_current_benefit() > 0:
best_sub_node = sub_node
best_score = score
return best_sub_node
def backpropagate(node, reward):
"""
In the Backpropagation stage of Monte Carlo tree search,
input the node that needs to be expended and the reward of the newly executed Action,
feed it back to the expend node and all upstream nodes,
and update the corresponding data.
"""
# update util the root node
while node is not None:
# update the visit number
node.update_visit_number()
# update the quality value
node.update_quality_value(reward)
# change the node to the parent node
node = node.parent
def monte_carlo_tree_search(node):
"""
Implement the Monte Carlo tree search algorithm, pass in a root node,
expand new nodes and update data according to the
tree structure that has been explored before in a limited time,
and then return as long as the child node with the highest exploitation.
When making predictions,
you only need to select the node with the largest exploitation according to the Q value,
and find the next optimal node.
"""
computation_budget = len(AVAILABLE_CHOICES) * 3
# run as much as possible under the computation budget
for i in range(computation_budget):
# 1. find the best node to expand
expand_node = tree_policy(node)
if not expand_node:
# when it is None, it means that all nodes are added but no nodes meet the space limit
break
# 2. random get next action and get reward
reward = default_policy(expand_node)
# 3. update all passing nodes with reward
backpropagate(expand_node, reward)
# get the best next node
best_next_node = best_child(node, False)
return best_next_node
def MCTS(workload_info, atomic_choices, available_choices, storage_threshold, max_index_num):
global ATOMIC_CHOICES, STORAGE_THRESHOLD, WORKLOAD_INFO, AVAILABLE_CHOICES, MAX_INDEX_NUM
WORKLOAD_INFO = workload_info
AVAILABLE_CHOICES = available_choices
ATOMIC_CHOICES = atomic_choices
STORAGE_THRESHOLD = storage_threshold
MAX_INDEX_NUM = max_index_num if max_index_num else len(available_choices)
# create the initialized state and initialized node
init_state = State()
choices = copy.copy(available_choices)
init_state.set_available_choices(choices)
init_node = Node()
init_node.set_state(init_state)
current_node = init_node
opt_config = []
# set the rounds to play
for i in range(len(AVAILABLE_CHOICES)):
if current_node:
current_node = monte_carlo_tree_search(current_node)
if current_node:
opt_config = current_node.state.accumulation_choices
else:
break
return opt_config

View File

@ -27,6 +27,7 @@ from collections.abc import Iterable
from collections import defaultdict
import index_advisor_workload as iaw
import mcts
def hash_any(obj):
@ -227,6 +228,32 @@ select * from student_range_part1 where credit=1;
class IndexAdvisorTester(unittest.TestCase):
def test_mcts(self):
storage_threshold = 12
index1 = iaw.IndexItem('public.a', 'col1', index_type='global')
index2 = iaw.IndexItem('public.b', 'col1', index_type='global')
index3 = iaw.IndexItem('public.c', 'col1', index_type='global')
index4 = iaw.IndexItem('public.d', 'col1', index_type='global')
atomic_index1 = iaw.IndexItem('public.a', 'col1', index_type='global')
atomic_index2 = iaw.IndexItem('public.b', 'col1', index_type='global')
atomic_index3 = iaw.IndexItem('public.c', 'col1', index_type='global')
atomic_index4 = iaw.IndexItem('public.d', 'col1', index_type='global')
atomic_index1.storage = 10
atomic_index2.storage = 4
atomic_index3.storage = 7
available_choices = [index1, index2, index3, index4]
atomic_choices = [[], [atomic_index2], [atomic_index1], [atomic_index3],
[atomic_index2, atomic_index3], [atomic_index4]]
query = iaw.QueryItem('select * from gia_01', 1)
query.cost_list = [10, 7, 5, 9, 4, 11]
workload_info = [query]
results = mcts.MCTS(workload_info, atomic_choices, available_choices, storage_threshold, 2)
self.assertLessEqual([index1.atomic_pos, index2.atomic_pos, index3.atomic_pos], [2, 1, 3])
self.assertSetEqual({results[0].table, results[1].table}, {'public.b', 'public.c'})
def test_get_indexable_columns(self):
tables = 'table1 table2 table2 table3 table3 table3'.split()
columns = 'col1,col2 col2 col3 col1,col2 col2,col3 col2,col5'.split()

View File

@ -90,7 +90,10 @@ static void DropExtensionInListIsSupported(List* objname)
}
}
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("EXTENSION is not yet supported.")));
/* Enable DROP operation of the above objects during inplace upgrade or support_extended_features is true */
if (!u_sess->attr.attr_common.IsInplaceUpgrade && !g_instance.attr.attr_common.support_extended_features) {
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("EXTENSION is not yet supported.")));
}
}
/*

View File

@ -1175,7 +1175,7 @@ void CreateExtension(CreateExtensionStmt* stmt)
FEATURE_NOT_PUBLIC_ERROR("EXTENSION is not yet supported.");
}
if (pg_strcasecmp(stmt->extname, "b_sql_plugin") == 0 && !DB_IS_CMPT(B_FORMAT)) {
if (pg_strcasecmp(stmt->extname, "dolphin") == 0 && !DB_IS_CMPT(B_FORMAT)) {
ereport(ERROR,
(errmsg("please create extension \"%s\" with B type DBCOMPATIBILITY", stmt->extname)));
}
@ -1418,8 +1418,8 @@ void CreateExtension(CreateExtensionStmt* stmt)
u_sess->exec_cxt.extension_is_valid = true;
if (pg_strcasecmp(stmt->extname, "b_sql_plugin") == 0) {
u_sess->attr.attr_sql.b_sql_plugin = true;
if (pg_strcasecmp(stmt->extname, "dolphin") == 0) {
u_sess->attr.attr_sql.dolphin = true;
}
/*

View File

@ -23175,7 +23175,7 @@ static void checkValidationForExchangeTable(Relation partTableRel, Relation ordT
int2 bucketId = InvalidBktId;
// get right partition oid for the tuple
targetPartOid = heapTupleGetPartitionId(partTableRel, (HeapTuple) tuple);
targetPartOid = heapTupleGetPartitionId(partTableRel, (HeapTuple)tuple, true);
searchFakeReationForPartitionOid(
partRelHTAB, CurrentMemoryContext, partTableRel, targetPartOid, partRel, part, RowExclusiveLock);
@ -24797,7 +24797,8 @@ static Oid AddTemporaryPartitionForAlterPartitions(const AlterTableCmd* cmd, Rel
destPartOid = AddTemporaryHashPartitionForAlterPartitions(cmd, partTableRel, partSeq, renameTargetPart);
break;
}
case PART_TYPE_RANGE: {
case PART_TYPE_RANGE:
case PART_TYPE_INTERVAL: {
destPartOid = AddTemporaryRangePartitionForAlterPartitions(cmd, partTableRel, partSeq, renameTargetPart);
break;
}
@ -25098,11 +25099,11 @@ static void readTuplesAndInsertInternal(Relation tempTableRel, Relation partTabl
/* tableam_tops_copy_tuple is not ready so we add UStore hack path */
copyTuple = tableam_tops_copy_tuple(tuple);
targetPartOid = heapTupleGetPartitionId(partTableRel, (void *)tuple);
targetPartOid = heapTupleGetPartitionId(partTableRel, (void *)tuple, true);
searchFakeReationForPartitionOid(
partRelHTAB, CurrentMemoryContext, partTableRel, targetPartOid, partRel, part, RowExclusiveLock);
if (RelationIsSubPartitioned(partTableRel)) {
targetPartOid = heapTupleGetPartitionId(partRel, (void *)tuple);
targetPartOid = heapTupleGetPartitionId(partRel, (void *)tuple, true);
searchFakeReationForPartitionOid(partRelHTAB, CurrentMemoryContext, partRel, targetPartOid, subPartRel,
subPart, RowExclusiveLock);
partRel = subPartRel;

View File

@ -1181,6 +1181,17 @@ static Node* pull_up_simple_subquery(PlannerInfo* root, Node* jtnode, RangeTblEn
return jtnode;
}
/*
* We must flatten any join alias Vars in the subquery's targetlist,
* because pulling up the subquery's subqueries might have changed their
* expansions into arbitrary expressions, which could affect
* pullup_replace_vars' decisions about whether PlaceHolderVar wrappers
* are needed for tlist entries. (Likely it'd be better to do
* flatten_join_alias_vars on the whole query tree at some earlier stage,
* maybe even in the rewriter; but for now let's just fix this case here.)
*/
subquery->targetList = (List *) flatten_join_alias_vars(subroot, (Node *) subquery->targetList);
/*
* Adjust level-0 varnos in subquery so that we can append its rangetable
* to upper query's. We have to fix the subquery's append_rel_list as

View File

@ -1263,7 +1263,7 @@ static void ckpt_pagewriter_main_thread_loop(void)
HandlePageWriterMainInterrupts();
candidate_num = get_curr_candidate_nums(false) + get_curr_candidate_nums(true);
if (candidate_num == 0) {
if (candidate_num == 0 && !t_thrd.pagewriter_cxt.shutdown_requested) {
/* wakeup sub thread scan the buffer pool, init the candidate list */
wakeup_sub_thread();
}

View File

@ -825,13 +825,10 @@ void client_read_ended(void)
#define INIT_PLUGIN_OBJECT "init_plugin_object"
void InitBSqlPluginHookIfNeeded()
{
const char* b_sql_plugin = "b_sql_plugin";
const char* dolphin = "dolphin";
CFunInfo tmpCF;
if (!CheckIfExtensionExists(b_sql_plugin)) {
return;
}
tmpCF = load_external_function(b_sql_plugin, INIT_PLUGIN_OBJECT, false, false);
tmpCF = load_external_function(dolphin, INIT_PLUGIN_OBJECT, false, false);
if (tmpCF.user_fn != NULL) {
((void* (*)(void))(tmpCF.user_fn))();
}
@ -865,9 +862,11 @@ List* pg_parse_query(const char* query_string, List** query_string_locationlist)
List* (*parser_hook)(const char*, List**) = raw_parser;
#ifndef ENABLE_MULTIPLE_NODES
int id = GetCustomParserId();
if (id >= 0 && g_instance.raw_parser_hook[id] != NULL) {
parser_hook = (List* (*)(const char*, List**))g_instance.raw_parser_hook[id];
if (u_sess->attr.attr_sql.dolphin) {
int id = GetCustomParserId();
if (id >= 0 && g_instance.raw_parser_hook[id] != NULL) {
parser_hook = (List* (*)(const char*, List**))g_instance.raw_parser_hook[id];
}
}
#endif
raw_parsetree_list = parser_hook(query_string, query_string_locationlist);
@ -6115,6 +6114,9 @@ void ProcessInterrupts(void)
/* The logical replication launcher can be stopped at any time. */
proc_exit(0);
} else if (IsLogicalWorker()) {
ereport(FATAL, (errcode(ERRCODE_ADMIN_SHUTDOWN),
errmsg("terminating logical replication worker due to administrator command")));
#endif
} else if (IsTxnSnapCapturerProcess()) {
ereport(FATAL,
@ -7572,7 +7574,7 @@ int PostgresMain(int argc, char* argv[], const char* dbname, const char* usernam
init_set_params_htab();
#ifndef ENABLE_MULTIPLE_NODES
if (u_sess->proc_cxt.MyDatabaseId != InvalidOid && DB_IS_CMPT(B_FORMAT)) {
if (u_sess->proc_cxt.MyDatabaseId != InvalidOid && DB_IS_CMPT(B_FORMAT) && u_sess->attr.attr_sql.dolphin) {
InitBSqlPluginHookIfNeeded();
}
#endif

View File

@ -848,7 +848,7 @@ static bool InitSession(knl_session_context* session)
t_thrd.proc_cxt.PostInit->InitSession();
#ifndef ENABLE_MULTIPLE_NODES
if (u_sess->proc_cxt.MyDatabaseId != InvalidOid && DB_IS_CMPT(B_FORMAT)) {
if (u_sess->proc_cxt.MyDatabaseId != InvalidOid && DB_IS_CMPT(B_FORMAT) && u_sess->attr.attr_sql.dolphin) {
InitBSqlPluginHookIfNeeded();
}
#endif

View File

@ -720,7 +720,6 @@ static Datum ExecEvalWholeRowVar(
{
Var* variable = (Var*)wrvstate->xprstate.expr;
TupleTableSlot* slot = NULL;
TupleDesc slot_tupdesc;
bool needslow = false;
if (isDone != NULL)
@ -802,21 +801,13 @@ static Datum ExecEvalWholeRowVar(
if (wrvstate->wrv_junkFilter != NULL)
slot = ExecFilterJunk(wrvstate->wrv_junkFilter, slot);
slot_tupdesc = slot->tts_tupleDescriptor;
/*
* If it's a RECORD Var, we'll use the slot's type ID info. It's likely
* that the slot's type is also RECORD; if so, make sure it's been
* "blessed", so that the Datum can be interpreted later.
*
* If the Var identifies a named composite type, we must check that the
* actual tuple type is compatible with it.
*/
if (variable->vartype == RECORDOID) {
if (slot_tupdesc->tdtypeid == RECORDOID && slot_tupdesc->tdtypmod < 0)
assign_record_type_typmod(slot_tupdesc);
} else {
if (variable->vartype != RECORDOID) {
TupleDesc var_tupdesc;
TupleDesc slot_tupdesc;
int i;
/*
@ -833,6 +824,8 @@ static Datum ExecEvalWholeRowVar(
*/
var_tupdesc = lookup_rowtype_tupdesc(variable->vartype, -1);
slot_tupdesc = slot->tts_tupleDescriptor;
if (var_tupdesc->natts != slot_tupdesc->natts)
ereport(ERROR,
(errcode(ERRCODE_DATATYPE_MISMATCH),
@ -886,6 +879,7 @@ static Datum ExecEvalWholeRowFast(
{
Var* variable = (Var*)wrvstate->xprstate.expr;
TupleTableSlot* slot = NULL;
TupleDesc slot_tupdesc;
HeapTuple tuple;
TupleDesc tupleDesc;
HeapTupleHeader dtuple;
@ -915,6 +909,17 @@ static Datum ExecEvalWholeRowFast(
if (wrvstate->wrv_junkFilter != NULL)
slot = ExecFilterJunk(wrvstate->wrv_junkFilter, slot);
/*
* If it's a RECORD Var, we'll use the slot's type ID info. It's likely
* that the slot's type is also RECORD; if so, make sure it's been
* "blessed", so that the Datum can be interpreted later.
*/
slot_tupdesc = slot->tts_tupleDescriptor;
if (variable->vartype == RECORDOID) {
if (slot_tupdesc->tdtypeid == RECORDOID && slot_tupdesc->tdtypmod < 0)
assign_record_type_typmod(slot_tupdesc);
}
tuple = ExecFetchSlotTuple(slot);
tupleDesc = slot->tts_tupleDescriptor;

View File

@ -322,7 +322,6 @@ static bool RelationFindReplTupleByIndex(EState *estate, Relation rel, Relation
}
if (found) {
/* Found tuple, try to lock it in the lockmode. */
outslot->tts_tuple = ExecMaterializeSlot(outslot);
xwait = TransactionIdIsValid(snap.xmin) ? snap.xmin : snap.xmax;
/*
* If the tuple is locked, wait for locking transaction to finish
@ -346,12 +345,16 @@ static bool RelationFindReplTupleByIndex(EState *estate, Relation rel, Relation
ItemPointer tid = tableam_tops_get_t_self(targetRel, outslot->tts_tuple);
if (RelationIsUstoreFormat(targetRel)) {
/* materialize the slot, so we can visit it after the scan is end */
outslot->tts_tuple = UHeapMaterialize(outslot);
ItemPointerCopy(tid, &UHeaplocktup.ctid);
rc = memset_s(&tbuf, sizeof(tbuf), 0, sizeof(tbuf));
securec_check(rc, "\0", "\0");
UHeaplocktup.disk_tuple = &tbuf.hdr;
locktup = &UHeaplocktup;
} else {
/* materialize the slot, so we can visit it after the scan is end */
outslot->tts_tuple = ExecMaterializeSlot(outslot);
ItemPointerCopy(tid, &heaplocktup.t_self);
locktup = &heaplocktup;
}
@ -401,6 +404,10 @@ static bool tuple_equals_slot(TupleDesc desc, const Tuple tup, TupleTableSlot *s
/* Check equality of the attributes. */
for (attrnum = 0; attrnum < desc->natts; attrnum++) {
TypeCacheEntry *typentry;
/* skip generate column */
if (GetGeneratedCol(desc, attrnum)) {
continue;
}
/*
* If one value is NULL and other is not, then they are certainly not
* equal
@ -478,7 +485,6 @@ static bool RelationFindReplTupleSeq(Relation rel, LockTupleMode lockmode, Tuple
found = true;
ExecStoreTuple(scantuple, outslot, InvalidBuffer, false);
outslot->tts_tuple = ExecMaterializeSlot(outslot);
xwait = TransactionIdIsValid(snap.xmin) ? snap.xmin : snap.xmax;
/*
@ -511,12 +517,16 @@ static bool RelationFindReplTupleSeq(Relation rel, LockTupleMode lockmode, Tuple
ItemPointer tid = tableam_tops_get_t_self(rel, outslot->tts_tuple);
if (RelationIsUstoreFormat(targetRel)) {
/* materialize the slot, so we can visit it after the scan is end */
outslot->tts_tuple = UHeapMaterialize(outslot);
ItemPointerCopy(tid, &UHeaplocktup.ctid);
rc = memset_s(&tbuf, sizeof(tbuf), 0, sizeof(tbuf));
securec_check(rc, "\0", "\0");
UHeaplocktup.disk_tuple = &tbuf.hdr;
locktup = &UHeaplocktup;
} else {
/* materialize the slot, so we can visit it after the scan is end */
outslot->tts_tuple = ExecMaterializeSlot(outslot);
ItemPointerCopy(tid, &heaplocktup.t_self);
locktup = &heaplocktup;
}
@ -653,7 +663,6 @@ void ExecSimpleRelationUpdate(EState *estate, EPQState *epqstate, TupleTableSlot
/* Compute stored generated columns */
if (rel->rd_att->constr && rel->rd_att->constr->has_generated_stored) {
ExecComputeStoredGenerated(resultRelInfo, estate, slot, tuple, CMD_UPDATE);
tuple = slot->tts_tuple;
}
/* Check the constraints of the tuple */
@ -672,10 +681,11 @@ void ExecSimpleRelationUpdate(EState *estate, EPQState *epqstate, TupleTableSlot
rowMovement = true;
}
tuple = slot->tts_tuple;
CommandId cid = GetCurrentCommandId(true);
/* OK, update the tuple and index entries for it */
if (!rowMovement) {
res = tableam_tuple_update(targetRelation, parentRelation, searchSlotTid, slot->tts_tuple, cid,
res = tableam_tuple_update(targetRelation, parentRelation, searchSlotTid, tuple, cid,
InvalidSnapshot, estate->es_snapshot, true, &oldslot, &tmfd, &updateIndexes, &modifiedIdxAttrs,
false, allowInplaceUpdate);
CheckTupleModifyRes(res);

View File

@ -2947,9 +2947,9 @@ void SetOneOfCompressOption(DefElem* defElem, TableCreateSupport* tableCreateSup
} else if (pg_strcasecmp(defname, "compress_level") == 0) {
tableCreateSupport->compressLevel = true;
} else if (pg_strcasecmp(defname, "compress_byte_convert") == 0) {
tableCreateSupport->compressByteConvert = true;
tableCreateSupport->compressByteConvert = defGetBoolean(defElem);
} else if (pg_strcasecmp(defname, "compress_diff_convert") == 0) {
tableCreateSupport->compressDiffConvert = true;
tableCreateSupport->compressDiffConvert = defGetBoolean(defElem);
}
}

View File

@ -1278,13 +1278,10 @@ static const char *MXStatusToString(MultiXactStatus status)
static char *mxid_to_string(MultiXactId multi, int nmembers, MultiXactMember *members)
{
static char *str = NULL;
char *str = NULL;
StringInfoData buf;
int i;
if (str != NULL)
pfree(str);
initStringInfo(&buf);
appendStringInfo(&buf, XID_FMT " %d[" XID_FMT " (%s)", multi, nmembers,
@ -1295,7 +1292,7 @@ static char *mxid_to_string(MultiXactId multi, int nmembers, MultiXactMember *me
}
appendStringInfoChar(&buf, ']');
str = MemoryContextStrdup(TopMemoryContext, buf.data);
str = MemoryContextStrdup(SESS_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_STORAGE), buf.data);
pfree(buf.data);
return str;
}

View File

@ -8965,6 +8965,8 @@ void StartupXLOG(void)
g_instance.comm_cxt.predo_cxt.redoPf.redo_done_time = 0;
pg_atomic_write_u32(&(g_instance.comm_cxt.localinfo_cxt.is_finish_redo), 0);
NotifyGscRecoveryStarted();
/*
* Initialize WAL insert status array and the flush index - lastWalStatusEntryFlushed.
*/

View File

@ -1818,3 +1818,47 @@ void UHeapSlotStoreUHeapTuple(UHeapTuple utuple, TupleTableSlot *slot, bool shou
/* Mark extracted state invalid */
slot->tts_nvalid = 0;
}
/*
* Make the contents of the uheap table's slot contents solely depend on the slot(make them a local copy),
* and not on underlying external resources like another memory context, buffers etc.
*
* @pram slot: slot to be materialized.
*/
Tuple UHeapMaterialize(TupleTableSlot *slot)
{
Assert(!slot->tts_isempty);
Assert(slot->tts_tupslotTableAm == TAM_USTORE);
Assert(slot->tts_tupleDescriptor != NULL);
/*
* If we have a regular physical tuple, and it's locally palloc'd, we have
* nothing to do.
*/
if (slot->tts_tuple && slot->tts_shouldFree) {
return slot->tts_tuple;
}
/*
* Otherwise, copy or build a physical tuple, and store it into the slot.
*
* We may be called in a context that is shorter-lived than the tuple
* slot, but we have to ensure that the materialized tuple will survive
* anyway.
*/
MemoryContext old_context = MemoryContextSwitchTo(slot->tts_mcxt);
if (slot->tts_tuple != NULL) {
slot->tts_tuple = UHeapCopyTuple((UHeapTuple)slot->tts_tuple);
} else {
slot->tts_tuple = UHeapFormTuple(slot->tts_tupleDescriptor, slot->tts_values, slot->tts_isnull);
}
slot->tts_shouldFree = true;
MemoryContextSwitchTo(old_context);
/*
* Have to deform from scratch, otherwise tts_values[] entries could point
* into the non-materialized tuple (which might be gone when accessed).
*/
slot->tts_nvalid = 0;
return slot->tts_tuple;
}

View File

@ -448,9 +448,7 @@ static void RecycleWaitIfNotUsed()
#endif
) {
uint64 nonRecycled = 0;
while (g_instance.attr.attr_storage.undo_zone_count == 0) {
/* Clear any already-pending wakeups */
ResetLatch(&t_thrd.proc->procLatch);
while (true) {
if (t_thrd.undorecycler_cxt.shutdown_requested) {
ereport(LOG, (errmodule(MOD_UNDO), errmsg(UNDOFORMAT("UndoRecycler: shutting down"))));
ResourceOwnerRelease(t_thrd.utils_cxt.CurrentResourceOwner, RESOURCE_RELEASE_BEFORE_LOCKS, false, true);

View File

@ -238,15 +238,19 @@ public:
return m_purpose;
}
void GcStartTxnMTtests()
GcEpochType GcStartInnerTxn()
{
if (m_gcEpoch != GetGlobalEpoch())
m_gcEpoch = GetGlobalEpoch();
m_gcEpoch = GetGlobalEpoch();
return m_gcEpoch;
}
void GcEndTxnMTtests()
void GcEndInnerTxn(bool clean_gc)
{
RunQuicese();
if (clean_gc) {
RunQuicese();
}
m_gcEpoch = 0;
}
void GcStartTxn()
@ -272,6 +276,7 @@ public:
RunQuicese();
m_managerLock.unlock();
}
m_gcEpoch = 0;
m_isTxnStarted = false;
}
@ -313,7 +318,6 @@ public:
{
if (m_performGcEpoch != g_gcActiveEpoch)
HardQuiesce(m_rcuFreeCount);
m_gcEpoch = 0;
}
/** @brief Clean all object at the end of the session */

View File

@ -258,6 +258,15 @@ bool Index::IndexInsert(Sentinel*& outputSentinel, const Key* key, uint32_t pid,
outputSentinel = IndexInsertImpl(key, sentinel, inserted, pid);
// sync between rollback/delete and insert
if (inserted == false) {
if (unlikely(outputSentinel == nullptr)) {
MOT_REPORT_ERROR(
MOT_ERROR_OOM, "Index Insert", "Failed to insert sentinel to index %s", m_name.c_str());
rc = RC_MEMORY_ALLOCATION_ERROR;
m_sentinelPool->Release<Sentinel>(sentinel);
sentinel = nullptr;
return false;
}
// Spin if the counter is 0 - aborting in parallel or sentinel is marks for commit
if (outputSentinel->RefCountUpdate(INC, pid) == RC_OK)
retryInsert = false;
@ -300,8 +309,16 @@ Sentinel* Index::IndexInsert(const Key* key, Row* row, uint32_t pid)
// no need to report to full error stack
SetLastError(MOT_ERROR_UNIQUE_VIOLATION, MOT_SEVERITY_NORMAL);
m_sentinelPool->Release<Sentinel>(sentinel);
sentinel = nullptr;
return nullptr;
} else {
if (inserted == false) {
MOT_REPORT_ERROR(MOT_ERROR_OOM, "Index Insert", "Failed to insert sentinel to index %s", m_name.c_str());
m_sentinelPool->Release<Sentinel>(sentinel);
sentinel = nullptr;
return nullptr;
}
if (GetIndexOrder() == IndexOrder::INDEX_ORDER_PRIMARY) {
sentinel->SetPrimaryIndex();
sentinel->SetNextPtr(row);
@ -343,9 +360,6 @@ Sentinel* Index::IndexReadHeader(const Key* key, uint32_t pid) const
Sentinel* Index::IndexRemove(const Key* key, uint32_t pid)
{
Sentinel* sentinel = IndexRemoveImpl(key, pid);
MOT_ASSERT(sentinel != nullptr);
MOT_ASSERT(sentinel->GetCounter() == 0);
return sentinel;
}

View File

@ -56,12 +56,22 @@ void* basic_table<P>::insert(MOT::Key const* const& key, void* const& entry, boo
5. Update the the key slice, keylen, key suffix and key's value in the
leaf
6. Add the key's location in permutation's back (key is not visible for
readers yet) As key's location is not part of the permutation yet, the key
readers yet) as key's location is not part of the permutation yet, the key
is not reachable (aka not present). In addition, the leaf is still locked.
Unlocking the node and enter the key into the permutation will be done
later in finish_insert (called from lp.finish). */
later in finish_insert (done in lp.finish function). */
bool found = lp.find_insert(*mtSessionThreadInfo);
bool found = false;
if (!lp.find_insert(*mtSessionThreadInfo, found)) {
// Failed to insert key due to memory allocation failure.
MOT_ASSERT(!mtSessionThreadInfo->non_disruptive_error());
MOT_ASSERT(found == false);
lp.finish(0, *mtSessionThreadInfo);
result = false;
return nullptr;
}
MOT_ASSERT(mtSessionThreadInfo->non_disruptive_error());
// If the key is new (not previously existing) then we record the entry under
// that key

View File

@ -33,15 +33,15 @@ namespace Masstree {
template <typename P>
struct gc_layer_rcu_callback_ng : public P::threadinfo_type::mrcu_callback {
typedef typename P::threadinfo_type threadinfo;
node_base<P>* root_;
node_base<P>** root_ref_;
int len_;
size_t size_;
MOT::MasstreePrimaryIndex* index_;
char s_[0];
gc_layer_rcu_callback_ng(node_base<P>* root, Str prefix, size_t size)
: root_(root), len_(prefix.length()), size_(size), index_(mtSessionThreadInfo->get_working_index())
gc_layer_rcu_callback_ng(node_base<P>** root_ref, Str prefix, size_t size)
: root_ref_(root_ref), len_(prefix.length()), size_(size), index_(mtSessionThreadInfo->get_working_index())
{
errno_t erc = memcpy_s(s_, size_, prefix.data(), len_);
errno_t erc = memcpy_s(s_, len_, prefix.data(), len_);
securec_check(erc, "\0", "\0");
}
size_t operator()(bool drop_index);
@ -51,7 +51,7 @@ struct gc_layer_rcu_callback_ng : public P::threadinfo_type::mrcu_callback {
return size_;
}
static void make(node_base<P>* root, Str prefix, threadinfo& ti);
static void make(node_base<P>** root_ref, Str prefix, threadinfo& ti);
};
template <typename P>
@ -60,8 +60,8 @@ size_t gc_layer_rcu_callback_ng<P>::operator()(bool drop_index)
// If drop_index == true, all index's pools are going to be cleaned, so we can skip gc_layer call (which might add
// more elements into GC)
if (drop_index == false) {
// GC layer remove might delete elements from tree and add them to the limbolist. Index must be provided to
// allow access to the memory pools.
// GC layer remove might delete elements from tree and might create new gc layer removal requests and add them to GC.
// Index must be provided to allow access to the memory pools.
mtSessionThreadInfo->set_working_index(index_);
(*this)(*mtSessionThreadInfo);
mtSessionThreadInfo->set_working_index(NULL);
@ -73,30 +73,33 @@ size_t gc_layer_rcu_callback_ng<P>::operator()(bool drop_index)
template <typename P>
void gc_layer_rcu_callback_ng<P>::operator()(threadinfo& ti)
{
// root_ node while creating gc_layer_rcu_callback_ng might not be the current root. Find updated tree's root.
while (!root_->is_root()) {
root_ = root_->maybe_parent();
}
masstree_invariant(root_ref_);
// If root was already deleted, do nothing.
if (root_->deleted()) {
return;
}
tcursor<P> node_cursor(root_, s_, len_);
if (!node_cursor.gc_layer(ti) || !node_cursor.finish_remove(ti)) {
tcursor<P> node_cursor(root_ref_, s_, len_);
bool do_remove = node_cursor.gc_layer(ti);
if (!do_remove || !node_cursor.finish_remove(ti)) {
node_cursor.n_->unlock();
}
ti.add_nodes_to_gc();
}
template <typename P>
void gc_layer_rcu_callback_ng<P>::make(node_base<P>* root, Str prefix, threadinfo& ti)
void gc_layer_rcu_callback_ng<P>::make(node_base<P>** root_ref, Str prefix, threadinfo& ti)
{
size_t sz = prefix.len + sizeof(gc_layer_rcu_callback_ng<P>);
// As we are using slab allocator to allocate the memory, sz is will updated in ti.allocate with the real allocated
// size
void* data = ti.allocate(sz, memtag_masstree_gc, &sz /*OUT PARAM*/);
gc_layer_rcu_callback_ng<P>* cb = new (data) gc_layer_rcu_callback_ng<P>(root, prefix, sz);
// As we are using slab allocator for allocation, sz is will be updated by ti.allocate with the real allocation
// size. We need this size for GC deallocation size report
void* data = ti.allocate(sz, memtag_masstree_gc, &sz /* IN/OUT PARAM */);
if (!data) {
// If allocation fails, gc layer removal command will not be added to GC and this layer wont be removed.
// We might deal with this issue in the future by replacing the current mechanism with one of the following options:
// 1. Use thread local GC layer removal object (per threadinfo) and keep list of key suffixes to clean (also in threadinfo)
// 2. Move this feature to VACUUM process: Create special iterator that adds GC Layer callbacks when it finds empty layers
ti.set_last_error(MT_MERR_GC_LAYER_REMOVAL_MAKE);
return;
}
gc_layer_rcu_callback_ng<P>* cb = new (data) gc_layer_rcu_callback_ng<P>(root_ref, prefix, sz);
ti.rcu_register(cb, sz);
}

View File

@ -69,14 +69,17 @@ Sentinel* MasstreePrimaryIndex::IndexInsertImpl(const Key* key, Sentinel* sentin
mtSessionThreadInfo->set_gc_session(
MOTEngine::GetInstance()->GetCurrentGcSession()); // set current GC session in thread-pooled envelope
mtSessionThreadInfo->set_last_error(MT_MERR_OK);
existingItem = m_index.insert(key, sentinel, inserted, pid);
mtSessionThreadInfo->set_gc_session(NULL);
mtSessionThreadInfo->set_working_index(NULL);
if (!inserted) { // key mapping already exists in unique index
if (!inserted && existingItem) { // key mapping already exists in unique index
result = reinterpret_cast<Sentinel*>(existingItem);
} // otherwise return null pointer
} // otherwise return null pointer (if !inserted && !existingItem, Key does not exist and insertation failed due to
// memory issue)
return result;
}
@ -108,6 +111,8 @@ Sentinel* MasstreePrimaryIndex::IndexRemoveImpl(const Key* key, uint32_t pid)
mtSessionThreadInfo->set_gc_session(
MOTEngine::GetInstance()->GetCurrentGcSession()); // set current GC session in thread-pooled envelope
mtSessionThreadInfo->set_last_error(MT_MERR_OK);
output = m_index.remove(key->GetKeyBuf(), key->GetKeyLength(), result, pid);
mtSessionThreadInfo->set_gc_session(NULL);

View File

@ -37,6 +37,7 @@
#include "masstree/mot_masstree_struct.hpp"
#include "masstree/mot_masstree_iterator.hpp"
#include <cmath>
#include "mot_engine.h"
namespace MOT {
/**
@ -302,11 +303,38 @@ public:
/**
* @brief Print Masstree pools memory consumption details to log.
*/
virtual void PrintPoolsStats()
virtual void PrintPoolsStats(LogLevel level = LogLevel::LL_DEBUG)
{
m_leafsPool->Print("Leafs pool: ");
m_internodesPool->Print("Internode pool: ");
m_ksuffixSlab->Print("Ksuffix slab: ");
m_leafsPool->Print("Leafs pool", level);
m_internodesPool->Print("Internode pool", level);
m_ksuffixSlab->Print("Ksuffix slab", level);
}
virtual void GetLeafsPoolStats(uint64_t& objSize, uint64_t& numUsedObj, uint64_t& totalSize, uint64_t& netto)
{
PoolStatsSt stats = {};
m_leafsPool->GetStats(stats);
objSize = stats.m_objSize;
numUsedObj = stats.m_totalObjCount - stats.m_freeObjCount;
totalSize = stats.m_poolCount * stats.m_poolGrossSize;
netto = numUsedObj * objSize;
}
virtual void GetInternodesPoolStats(uint64_t& objSize, uint64_t& numUsedObj, uint64_t& totalSize, uint64_t& netto)
{
PoolStatsSt stats = {};
m_internodesPool->GetStats(stats);
objSize = stats.m_objSize;
numUsedObj = stats.m_totalObjCount - stats.m_freeObjCount;
totalSize = stats.m_poolCount * stats.m_poolGrossSize;
netto = numUsedObj * objSize;
}
virtual PoolStatsSt* GetKsuffixSlabStats()
{
return m_ksuffixSlab->GetStats();
}
/**
@ -316,6 +344,8 @@ public:
{
m_initialized = false;
DestroyPools();
// remove masstree's root pointer (not valid anymore)
*(m_index.root_ref()) = nullptr;
return IndexInitImpl(NULL);
}
@ -332,7 +362,7 @@ public:
* @param tag Hint to determine which pool to use.
* @return Pointer to allocated memory.
*/
void* AllocateMem(int& size, enum memtag tag)
virtual void* AllocateMem(int& size, enum memtag tag)
{
switch (tag) {
case memtag_masstree_leaf:
@ -360,7 +390,7 @@ public:
* @param Pointer to allocated memory.
* @return True if deallocation succeeded.
*/
bool DeallocateMem(void* ptr, int size, enum memtag tag)
virtual bool DeallocateMem(void* ptr, int size, enum memtag tag)
{
switch (tag) {
case memtag_masstree_leaf:
@ -431,10 +461,16 @@ public:
{
// If dropIndex == true, all index's pools are going to be cleaned, so we skip the release here
mtSessionThreadInfo->set_gc_session(GetCurrentGcSession());
GcEpochType local_epoch =
GetSessionManager()->GetCurrentSessionContext()->GetTxnManager()->GetGcSession()->GcStartInnerTxn();
size_t allocationSize = (*static_cast<mrcu_callback*>(gcRemoveLayerFuncObjPtr))(dropIndex);
if (dropIndex == false) {
((SlabAllocator*)slab)->Release(gcRemoveLayerFuncObjPtr, allocationSize);
}
GetSessionManager()->GetCurrentSessionContext()->GetTxnManager()->GetGcSession()->GcEndInnerTxn(false);
mtSessionThreadInfo->set_gc_session(NULL);
return allocationSize;
}

View File

@ -582,6 +582,7 @@ Row* Table::RemoveKeyFromIndex(Row* row, Sentinel* sentinel, uint64_t tid, GcMan
#endif
currSentinel = ix->IndexRemove(&key, tid);
MOT_ASSERT(currSentinel == sentinel);
MOT_ASSERT(currSentinel->GetCounter() == 0);
if (likely(gc != nullptr)) {
if (ix->GetIndexOrder() == IndexOrder::INDEX_ORDER_PRIMARY) {
OutputRow = currSentinel->GetData();

View File

@ -413,6 +413,8 @@ RC TxnManager::RollbackInsert(Access* ac)
#endif
outputSen = index_->IndexRemove(&m_key, GetThdId());
MOT_ASSERT(outputSen != nullptr);
MOT_ASSERT(outputSen->GetCounter() == 0);
GcSessionRecordRcu(index_->GetIndexId(), outputSen, nullptr, Index::SentinelDtor, SENTINEL_SIZE(index_));
// If we are the owner of the key and insert on top of a deleted row,
// lets check if we can reclaim the deleted row
@ -820,6 +822,8 @@ void TxnInsertAction::CleanupOptimisticInsert(
MOT_ASSERT(pIndexInsertResult->GetCounter() == 0);
Sentinel* outputSen = index_->IndexRemove(currentItem->m_key, m_manager->GetThdId());
MOT_ASSERT(outputSen != nullptr);
MOT_ASSERT(outputSen->GetCounter() == 0);
m_manager->GcSessionRecordRcu(
index_->GetIndexId(), outputSen, nullptr, Index::SentinelDtor, SENTINEL_SIZE(index_));
m_manager->m_accessMgr->IncreaseTableStat(table);

View File

@ -223,6 +223,7 @@ void LogicalDecodingProcessRecord(LogicalDecodingContext *ctx, XLogReaderState *
return;
}
ResourceOwner tmpOwner = t_thrd.utils_cxt.CurrentResourceOwner;
/* cast so we get a warning when new rmgrs are added */
switch ((RmgrIds)XLogRecGetRmid(record)) {
/*
@ -257,6 +258,7 @@ void LogicalDecodingProcessRecord(LogicalDecodingContext *ctx, XLogReaderState *
default:
break;
}
t_thrd.utils_cxt.CurrentResourceOwner = tmpOwner;
}
/*

View File

@ -406,7 +406,7 @@ static void logicalrep_write_tuple(StringInfo out, Relation rel, HeapTuple tuple
pfree(outputbytes);
}
} else {
char *outputstr;
char* outputstr = NULL;
pq_sendbyte(out, LOGICALREP_COLUMN_TEXT);
if (!typclass->typbyval && typclass->typlen == -1) {
/* definitely detoasted Datum */
@ -464,10 +464,8 @@ static void logicalrep_read_tuple(StringInfo in, LogicalRepTupleData *tuple)
len = pq_getmsgint(in, sizeof(uint32)); /* read length */
/* and data */
value->data = (char *) palloc((len + 1) * sizeof(char));
value->data = (char *)palloc0((len + 1) * sizeof(char));
pq_copymsgbytes(in, value->data, len);
/* not strictly necessary but per StringInfo practice */
value->data[len] = '\0';
/* make StringInfo fully valid */
value->len = len;
value->cursor = 0;

View File

@ -94,7 +94,7 @@
#include "utils/relcache.h"
static const int NAPTIME_PER_CYCLE = 10; /* max sleep time between cycles (10ms) */
static const float HALF = 0.5;
static const double HALF = 0.5;
typedef struct FlushPosition {
dlist_node node;
@ -121,18 +121,6 @@ static void LogicalrepWorkerSighub(SIGNAL_ARGS)
t_thrd.applyworker_cxt.got_SIGHUP = true;
}
/* SIGTERM: time to die */
static void LogicalrepWorkerSigterm(SIGNAL_ARGS)
{
int saveErrno = errno;
t_thrd.applyworker_cxt.got_SIGTERM = true;
if (t_thrd.proc)
SetLatch(&t_thrd.proc->procLatch);
errno = saveErrno;
}
/*
* Make sure that we started local transaction.
*
@ -1068,13 +1056,15 @@ static void ApplyLoop(void)
/* mark as idle, before starting to loop */
pgstat_report_activity(STATE_IDLE, NULL);
while (!t_thrd.applyworker_cxt.got_SIGTERM) {
for (;;) {
MemoryContextSwitchTo(t_thrd.applyworker_cxt.messageContext);
int len;
char *buf = NULL;
unsigned char type;
CHECK_FOR_INTERRUPTS();
/* Wait a while for data to arrive */
if ((WalReceiverFuncTable[GET_FUNC_IDX]).walrcv_receive(NAPTIME_PER_CYCLE, &type, &buf, &len)) {
StringInfoData s;
@ -1371,7 +1361,7 @@ void ApplyWorkerMain()
*/
gspqsignal(SIGHUP, LogicalrepWorkerSighub);
gspqsignal(SIGINT, StatementCancelHandler);
gspqsignal(SIGTERM, LogicalrepWorkerSigterm);
gspqsignal(SIGTERM, die);
gspqsignal(SIGQUIT, quickdie);
gspqsignal(SIGALRM, handle_sig_alarm);
@ -1727,3 +1717,11 @@ static void UpdateConninfo(char* standbysInfo)
ereport(LOG, (errmsg("Update conninfo successfully, new conninfo %s.", standbysInfo)));
}
/*
* Is current process a logical replication worker?
*/
bool IsLogicalWorker(void)
{
return t_thrd.applyworker_cxt.curWorker != NULL;
}

View File

@ -78,7 +78,7 @@ void _PG_output_plugin_init(OutputPluginCallbacks *cb)
cb->shutdown_cb = pgoutput_shutdown;
}
static void parse_output_parameters(List* options, PGOutputData* data)
static void parse_output_parameters(List *options, PGOutputData *data)
{
ListCell *lc;
bool protocol_version_given = false;

View File

@ -1934,14 +1934,18 @@ ArchiveConfig* formArchiveConfigFromStr(char *content, bool encrypted)
ArchiveConnConfig* conn_config = NULL;
char* media_type = NULL;
errno_t rc = EOK;
/* SplitIdentifierString will change origin string */
char *content_copy = pstrdup(content);
char *content_copy = NULL;
char *tmp = NULL;
List* elemlist = NIL;
int param_num = 0;
size_t elem_index = 0;
archive_config = (ArchiveConfig *)palloc0(sizeof(ArchiveConfig));
char decryptSecretAccessKeyStr[DEST_CIPHER_LENGTH] = {'\0'};
if (content == NULL || strlen(content) == 0) {
goto FAILURE;
}
/* SplitIdentifierString will change origin string */
content_copy = pstrdup(content);
/* Parse string into list of identifiers */
if (!SplitIdentifierString(content_copy, ';', &elemlist, false, false)) {
goto FAILURE;

View File

@ -401,6 +401,7 @@ int WalSenderMain(void)
t_thrd.walsender_cxt.server_run_mode = t_thrd.postmaster_cxt.HaShmData->current_mode;
SetHaWalSenderChannel();
Assert(t_thrd.utils_cxt.CurrentResourceOwner != NULL);
/* Handle handshake messages before streaming */
WalSndHandshake();
@ -496,6 +497,7 @@ static void WalSndHandshake(void)
while (!repCxt.replicationStarted) {
int firstchar;
Assert(t_thrd.utils_cxt.CurrentResourceOwner != NULL);
WalSndSetState(WALSNDSTATE_STARTUP);
set_ps_display("idle", false);
@ -2033,6 +2035,8 @@ bool isLogicalSlotExist(char* slotName)
}
static void IdentifyCommand(Node* cmd_node, ReplicationCxt* repCxt, const char *cmd_string){
ResourceOwner tmpOwner = t_thrd.utils_cxt.CurrentResourceOwner;
Assert(tmpOwner != NULL);
switch (cmd_node->type) {
case T_IdentifySystemCmd:
IdentifySystem();
@ -2140,7 +2144,7 @@ static void IdentifyCommand(Node* cmd_node, ReplicationCxt* repCxt, const char *
ereport(FATAL,
(errcode(ERRCODE_PROTOCOL_VIOLATION), errmsg("invalid standby query string: %s", cmd_string)));
}
t_thrd.utils_cxt.CurrentResourceOwner = tmpOwner;
}
/*
@ -3596,8 +3600,12 @@ static int WalSndLoop(WalSndSendDataCallback send_data)
t_thrd.walsender_cxt.last_logical_xlog_advanced_timestamp = GetCurrentTimestamp();
t_thrd.walsender_cxt.waiting_for_ping_response = false;
ResourceOwner tmpOwner = t_thrd.utils_cxt.CurrentResourceOwner;
Assert(!IsTransactionOrTransactionBlock() &&
strcmp(ResourceOwnerGetName(tmpOwner), "walsender top-level resource owner") == 0);
/* Loop forever, unless we get an error */
for (;;) {
t_thrd.utils_cxt.CurrentResourceOwner = tmpOwner;
TimestampTz now;
/* Clear any already-pending wakeups */
@ -4006,6 +4014,7 @@ static int WalSndLoop(WalSndSendDataCallback send_data)
}
}
t_thrd.utils_cxt.CurrentResourceOwner = tmpOwner;
WalSndShutdown();
return 1; /* keep the compiler quiet */
}
@ -5814,7 +5823,7 @@ Datum gs_paxos_stat_replication(PG_FUNCTION_ARGS)
*/
Datum pg_stat_get_wal_senders(PG_FUNCTION_ARGS)
{
#define PG_STAT_GET_WAL_SENDERS_COLS 22
#define PG_STAT_GET_WAL_SENDERS_COLS 21
TupleDesc tupdesc;
int *sync_priority = NULL;
@ -6051,11 +6060,9 @@ Datum pg_stat_get_wal_senders(PG_FUNCTION_ARGS)
/* sync_state and sync_prority */
if (!SyncRepRequested()) {
values[j++] = CStringGetTextDatum("Async");
nulls[j++] = true;
values[j++] = Int32GetDatum(0);
} else {
values[j++] = CStringGetTextDatum("Sync");
nulls[j++] = true;
values[j++] = Int32GetDatum(sync_priority[i]);
}
} else {
@ -6077,15 +6084,12 @@ Datum pg_stat_get_wal_senders(PG_FUNCTION_ARGS)
*/
if (priority == 0) {
values[j++] = CStringGetTextDatum("Async");
nulls[j++] = true;
} else if (list_member_int((List*)list_nth(sync_standbys, group), i)) {
values[j++] = GetWalsndSyncRepConfig(walsnd)->syncrep_method == SYNC_REP_PRIORITY
? CStringGetTextDatum("Sync")
: CStringGetTextDatum("Quorum");
values[j++] = Int32GetDatum(group);
} else {
values[j++] = CStringGetTextDatum("Potential");
values[j++] = Int32GetDatum(group);
}
values[j++] = Int32GetDatum(priority);
}

View File

@ -394,8 +394,6 @@ void mdcreate(SMgrRelation reln, ForkNumber forkNum, bool isRedo)
}
if (fd < 0) {
int save_errno = errno;
/*
* During bootstrap, there are cases where a system relation will be
* accessed (by internal backend processes) before the bootstrap
@ -407,26 +405,7 @@ void mdcreate(SMgrRelation reln, ForkNumber forkNum, bool isRedo)
* new catalogs can by no means be used by other relations, we simply
* truncate them.
*/
if (isRedo || IsBootstrapProcessingMode() ||
(u_sess->attr.attr_common.IsInplaceUpgrade && filenode.rnode.node.relNode < FirstNormalObjectId)) {
ADIO_RUN()
{
flags = O_RDWR | PG_BINARY | O_DIRECT | (u_sess->attr.attr_common.IsInplaceUpgrade ? O_TRUNC : 0);
}
ADIO_ELSE()
{
flags = O_RDWR | PG_BINARY | (u_sess->attr.attr_common.IsInplaceUpgrade ? O_TRUNC : 0);
}
ADIO_END();
fd = DataFileIdOpenFile(path, filenode, flags, 0600);
}
if (fd < 0) {
/* be sure to report the error reported by create, not open */
errno = save_errno;
ereport(ERROR, (errcode_for_file_access(), errmsg("could not create file \"%s\": %m", path)));
}
fd = RetryDataFileIdOpenFile(isRedo, path, filenode, flags);
}
File fd_pca = -1;

View File

@ -145,6 +145,29 @@ then
plat_form_str=ubuntu18.04_"$cpu_bit"
fi
##################################################################################
# the modification here will also lead to the synchronous modification of the 3rd-party compilation library path
# PR link : https://gitee.com/opengauss/openGauss-third_party/pulls/130
# redflag platform
# the result form like this: asianux_x86_64
##################################################################################
if [ "$kernel"x = "redflag"x ]
then
plat_form_str=asianux7.6_"$cpu_bit"
fi
##################################################################################
# the modification here will also lead to the synchronous modification of the 3rd-party compilation library path
# PR link : https://gitee.com/opengauss/openGauss-third_party/pulls/130
# asianux platform
# the result form like this: asianux_aarch64
##################################################################################
if [ "$kernel"x = "asianux"x ]
then
plat_form_str=asianux7.5_"$cpu_bit"
fi
##################################################################################
#
# other platform

View File

@ -314,4 +314,5 @@ template<bool hasnull>
void UHeapFillDiskTuple(TupleDesc tupleDesc, Datum *values, const bool *isnull, UHeapDiskTupleData *diskTuple,
uint32 dataSize, bool enableReverseBitmap, bool enableReserve);
void CheckTupleValidity(Relation rel, UHeapTuple utuple);
Tuple UHeapMaterialize(TupleTableSlot *slot);
#endif

View File

@ -165,7 +165,7 @@ extern void addNewPartitionTuple(Relation pg_part_desc, Partition new_part_desc,
Datum interval, Datum maxValues, Datum transitionPoint, Datum reloptions);
extern void heap_truncate_one_part(Relation rel , Oid partOid);
extern Oid heapTupleGetPartitionId(Relation rel, void *tuple);
extern Oid heapTupleGetPartitionId(Relation rel, void *tuple, bool isDDL = false);
extern Oid heapTupleGetSubPartitionId(Relation rel, void *tuple);
extern void heap_truncate(List *relids);
extern void heap_truncate_one_rel(Relation rel);
@ -240,7 +240,7 @@ extern char* make_column_map(TupleDesc tuple_desc);
*/
extern bool* CheckPartkeyHasTimestampwithzone(Relation partTableRel, bool isForSubPartition = false);
extern Oid AddNewIntervalPartition(Relation rel, void* insertTuple);
extern Oid AddNewIntervalPartition(Relation rel, void* insertTuple, bool isDDL = false);
extern int GetIndexKeyAttsByTuple(Relation relation, HeapTuple indexTuple);

View File

@ -1,37 +0,0 @@
-- for any x group
DO $$
DECLARE
ans boolean;
BEGIN
select case when working_version_num()=92301 then true else false end as ans into ans;
if ans = false then
DROP FUNCTION IF EXISTS pg_catalog.pg_stat_get_wal_senders() CASCADE;
SET LOCAL inplace_upgrade_next_system_object_oids = IUO_PROC, 3099;
CREATE FUNCTION pg_catalog.pg_stat_get_wal_senders(
OUT pid bigint,
OUT sender_pid integer,
OUT local_role text,
OUT peer_role text,
OUT peer_state text,
OUT state text,
OUT catchup_start timestamp with time zone,
OUT catchup_end timestamp with time zone,
OUT sender_sent_location text,
OUT sender_write_location text,
OUT sender_flush_location text,
OUT sender_replay_location text,
OUT receiver_received_location text,
OUT receiver_write_location text,
OUT receiver_flush_location text,
OUT receiver_replay_location text,
OUT sync_percent text,
OUT sync_state text,
OUT sync_priority integer,
OUT sync_most_available text,
OUT channel text
) RETURNS SETOF record
STABLE NOT FENCED NOT SHIPPABLE ROWS 10
LANGUAGE internal AS 'pg_stat_get_wal_senders';
end if;
END$$;
SET LOCAL inplace_upgrade_next_system_object_oids = IUO_PROC, 0;

View File

@ -1,37 +0,0 @@
-- for any x group
DO $$
DECLARE
ans boolean;
BEGIN
select case when working_version_num()=92301 then true else false end as ans into ans;
if ans = false then
DROP FUNCTION IF EXISTS pg_catalog.pg_stat_get_wal_senders() CASCADE;
SET LOCAL inplace_upgrade_next_system_object_oids = IUO_PROC, 3099;
CREATE FUNCTION pg_catalog.pg_stat_get_wal_senders(
OUT pid bigint,
OUT sender_pid integer,
OUT local_role text,
OUT peer_role text,
OUT peer_state text,
OUT state text,
OUT catchup_start timestamp with time zone,
OUT catchup_end timestamp with time zone,
OUT sender_sent_location text,
OUT sender_write_location text,
OUT sender_flush_location text,
OUT sender_replay_location text,
OUT receiver_received_location text,
OUT receiver_write_location text,
OUT receiver_flush_location text,
OUT receiver_replay_location text,
OUT sync_percent text,
OUT sync_state text,
OUT sync_priority integer,
OUT sync_most_available text,
OUT channel text
) RETURNS SETOF record
STABLE NOT FENCED NOT SHIPPABLE ROWS 10
LANGUAGE internal AS 'pg_stat_get_wal_senders';
end if;
END$$;
SET LOCAL inplace_upgrade_next_system_object_oids = IUO_PROC, 0;

View File

@ -1,38 +0,0 @@
-- for any x group
DO $$
DECLARE
ans boolean;
BEGIN
select case when working_version_num()=92301 then true else false end as ans into ans;
if ans = false then
DROP FUNCTION IF EXISTS pg_catalog.pg_stat_get_wal_senders() CASCADE;
SET LOCAL inplace_upgrade_next_system_object_oids = IUO_PROC, 3099;
CREATE FUNCTION pg_catalog.pg_stat_get_wal_senders(
OUT pid bigint,
OUT sender_pid integer,
OUT local_role text,
OUT peer_role text,
OUT peer_state text,
OUT state text,
OUT catchup_start timestamp with time zone,
OUT catchup_end timestamp with time zone,
OUT sender_sent_location text,
OUT sender_write_location text,
OUT sender_flush_location text,
OUT sender_replay_location text,
OUT receiver_received_location text,
OUT receiver_write_location text,
OUT receiver_flush_location text,
OUT receiver_replay_location text,
OUT sync_percent text,
OUT sync_state text,
OUT sync_group integer,
OUT sync_priority integer,
OUT sync_most_available text,
OUT channel text
) RETURNS SETOF record
STABLE NOT FENCED NOT SHIPPABLE ROWS 10
LANGUAGE internal AS 'pg_stat_get_wal_senders';
end if;
END$$;
SET LOCAL inplace_upgrade_next_system_object_oids = IUO_PROC, 0;

View File

@ -1,38 +0,0 @@
-- for any x group
DO $$
DECLARE
ans boolean;
BEGIN
select case when working_version_num()=92301 then true else false end as ans into ans;
if ans = false then
DROP FUNCTION IF EXISTS pg_catalog.pg_stat_get_wal_senders() CASCADE;
SET LOCAL inplace_upgrade_next_system_object_oids = IUO_PROC, 3099;
CREATE FUNCTION pg_catalog.pg_stat_get_wal_senders(
OUT pid bigint,
OUT sender_pid integer,
OUT local_role text,
OUT peer_role text,
OUT peer_state text,
OUT state text,
OUT catchup_start timestamp with time zone,
OUT catchup_end timestamp with time zone,
OUT sender_sent_location text,
OUT sender_write_location text,
OUT sender_flush_location text,
OUT sender_replay_location text,
OUT receiver_received_location text,
OUT receiver_write_location text,
OUT receiver_flush_location text,
OUT receiver_replay_location text,
OUT sync_percent text,
OUT sync_state text,
OUT sync_group integer,
OUT sync_priority integer,
OUT sync_most_available text,
OUT channel text
) RETURNS SETOF record
STABLE NOT FENCED NOT SHIPPABLE ROWS 10
LANGUAGE internal AS 'pg_stat_get_wal_senders';
end if;
END$$;
SET LOCAL inplace_upgrade_next_system_object_oids = IUO_PROC, 0;

View File

@ -238,7 +238,7 @@ typedef struct knl_session_attr_sql {
#ifndef ENABLE_MULTIPLE_NODES
bool enable_custom_parser;
#endif
bool b_sql_plugin;
bool dolphin;
} knl_session_attr_sql;
#endif /* SRC_INCLUDE_KNL_KNL_SESSION_ATTR_SQL */

View File

@ -31,6 +31,7 @@
#include "access/extreme_rto/spsc_blocking_queue.h"
#include "access/parallel_recovery/redo_item.h"
#include "nodes/parsenodes_common.h"
#include "nodes/replnodes.h"
#include "access/ustore/knl_utuple.h"
#include "replication/logical_queue.h"

View File

@ -13,5 +13,6 @@
#define LOGICALWORKER_H
extern void ApplyWorkerMain();
extern bool IsLogicalWorker(void);
#endif /* LOGICALWORKER_H */

View File

@ -229,10 +229,15 @@ private:
bool m_syscache_relids[FirstNormalObjectId];
};
void NotifyGscRecoveryStarted();
void NotifyGscRecoveryFinished();
extern Datum gs_gsc_dbstat_info(PG_FUNCTION_ARGS);
extern Datum gs_gsc_clean(PG_FUNCTION_ARGS);
extern Datum gs_gsc_catalog_detail(PG_FUNCTION_ARGS);
extern Datum gs_gsc_table_detail(PG_FUNCTION_ARGS);
extern int ResizeHashBucket(int origin_nbucket, DynamicHashBucketStrategy strategy);
#endif
/* only primary node check recovery, recovery from upgrade may have misorder cacheids */
#define IsPrimaryRecoveryFinished() \
(g_instance.global_sysdbcache.recovery_finished || t_thrd.postmaster_cxt.HaShmData->current_mode == STANDBY_MODE)
#endif

View File

@ -213,7 +213,7 @@ extern bool check_rel_is_partitioned(Oid relid);
extern Oid partid_get_parentid(Oid partid);
extern bool is_not_strict_agg(Oid funcOid);
extern bool is_pgxc_class_table(Oid tableoid);
extern Oid get_valid_relname_relid(const char* relnamespace, const char* relname);
extern Oid get_valid_relname_relid(const char* relnamespace, const char* relname, bool nsp_missing_ok = false);
extern bool get_func_iswindow(Oid funcid);
extern char get_func_prokind(Oid funcid);
extern char get_typecategory(Oid typid);

View File

@ -1385,6 +1385,8 @@ typedef struct PlDebugEntry {
PLpgSQL_function* func;
} PlDebugEntry;
typedef List* (*RawParserHook)(const char*, List**);
const int MAXINT8LEN = 25;
const int DEFAULT_DEBUG_BUF_SIZE = 1024;
const long NANOSECOND_PER_SECOND = 1000000000L; /* 1s */

View File

@ -0,0 +1,37 @@
--
-- check for over-optimization of whole-row Var referencing an Append plan
--
create table int4_test(f1 int4);
select (select q from (select 1,2,3 where f1>0 union all select 4,5,6 where f1<=0) q) from int4_test;
q
---
(0 rows)
select (select q from (select 1,2,3 where f1>0 union all select 4,5,6.0 where f1<=0) q) from int4_test;
q
---
(0 rows)
insert into int4_test(f1) values(' 0 ');
insert into int4_test(f1) values('123456 ');
select * from int4_test;
f1
--------
0
123456
(2 rows)
select (select q from (select 1,2,3 where f1>0 union all select 4,5,6 where f1<=0) q) from int4_test;
q
---------
(4,5,6)
(1,2,3)
(2 rows)
select (select q from (select 1,2,3 where f1>0 union all select 4,5,6.0 where f1<=0) q) from int4_test;
q
-----------
(4,5,6.0)
(1,2,3)
(2 rows)

View File

@ -0,0 +1,116 @@
create schema deserialize_func1;
set current_schema = deserialize_func1;
create sequence test_seq;
create or replace function test_func() return int
as
begin
return 1;
end;
/
create table t1(key int, id int default nextval('test_seq'));
create table t2(key int, id int default test_func());
select * from pg_get_tabledef('deserialize_func1.t1');
pg_get_tabledef
------------------------------------------------------
SET search_path = deserialize_func1; +
CREATE TABLE t1 ( +
key integer, +
id integer DEFAULT nextval('test_seq'::regclass)+
) +
WITH (orientation=row, compression=no);
(1 row)
select * from pg_get_tabledef('deserialize_func1.t2');
pg_get_tabledef
-----------------------------------------
SET search_path = deserialize_func1; +
CREATE TABLE t2 ( +
key integer, +
id integer DEFAULT test_func() +
) +
WITH (orientation=row, compression=no);
(1 row)
alter schema deserialize_func1 rename to deserialize_func2;
select * from pg_get_tabledef('deserialize_func2.t1');
pg_get_tabledef
------------------------------------------------------------------------
SET search_path = deserialize_func2; +
CREATE TABLE t1 ( +
key integer, +
id integer DEFAULT nextval('deserialize_func2.test_seq'::regclass)+
) +
WITH (orientation=row, compression=no);
(1 row)
select * from pg_get_tabledef('deserialize_func2.t2');
pg_get_tabledef
------------------------------------------------------
SET search_path = deserialize_func2; +
CREATE TABLE t2 ( +
key integer, +
id integer DEFAULT deserialize_func2.test_func()+
) +
WITH (orientation=row, compression=no);
(1 row)
alter table deserialize_func2.t1 alter column id drop default;
alter table deserialize_func2.t1 alter column id set default nextval('deserialize_func2.test_seq');
select * from pg_get_tabledef('deserialize_func2.t1');
pg_get_tabledef
------------------------------------------------------------------------
SET search_path = deserialize_func2; +
CREATE TABLE t1 ( +
key integer, +
id integer DEFAULT nextval('deserialize_func2.test_seq'::regclass)+
) +
WITH (orientation=row, compression=no);
(1 row)
alter table deserialize_func2.t2 alter column id drop default;
alter table deserialize_func2.t2 alter column id set default deserialize_func2.test_func();
select * from pg_get_tabledef('deserialize_func2.t2');
pg_get_tabledef
------------------------------------------------------
SET search_path = deserialize_func2; +
CREATE TABLE t2 ( +
key integer, +
id integer DEFAULT deserialize_func2.test_func()+
) +
WITH (orientation=row, compression=no);
(1 row)
set current_schema = deserialize_func2;
create type type1 as (a int);
create view v1 as select '(1)'::type1;
alter type type1 rename to type2;
select pg_get_viewdef('v1');
pg_get_viewdef
-------------------------------
SELECT '(1)'::type2 AS type1;
(1 row)
drop view v1 cascade;
create table atest12 as select x as a, 10001-x as b from generate_series(1, 10000) x;
create function func1(integer, integer) returns boolean as $$begin return $1 < $2; end $$ language plpgsql immutable;
create operator <<< (procedure=func1, leftarg=integer, rightarg=integer, restrict=scalarltsel);
create view atest12v as select * from atest12 where b <<< 5;
select pg_get_viewdef('atest12v');
pg_get_viewdef
-------------------------------------------------
SELECT * FROM atest12 WHERE (atest12.b <<< 5);
(1 row)
drop schema if exists deserialize_func1 cascade;
NOTICE: schema "deserialize_func1" does not exist, skipping
drop schema if exists deserialize_func2 cascade;
NOTICE: drop cascades to 9 other objects
DETAIL: drop cascades to sequence test_seq
drop cascades to function test_func()
drop cascades to table t1
drop cascades to table t2
drop cascades to type type2
drop cascades to table atest12
drop cascades to function func1(integer,integer)
drop cascades to operator <<<(integer,integer)
drop cascades to view atest12v

View File

@ -132,11 +132,14 @@ DROP EXTENSION test_extension_exists;
ERROR: extension "test_extension_exists" does not exist
DROP EXTENSION IF EXISTS test_extension_exists;
NOTICE: extension "test_extension_exists" does not exist, skipping
-- exists but doesn't support drop
DROP EXTENSION plpgsql;
ERROR: EXTENSION is not yet supported.
DROP EXTENSION IF EXISTS plpgsql;
ERROR: EXTENSION is not yet supported.
-- only extension in white list support drop, but the guc support_extended_features is true in pg_regress mode, so hdfs_fdw can be droped
CREATE DATABASE ext_test_db;
\c ext_test_db
DROP EXTENSION hdfs_fdw;
DROP EXTENSION IF EXISTS hdfs_fdw;
NOTICE: extension "hdfs_fdw" does not exist, skipping
\c regression
DROP DATABASE ext_test_db;
-- functions
DROP FUNCTION test_function_exists();
ERROR: function test_function_exists does not exist

View File

@ -215,3 +215,107 @@ select * from interval_normal_exchange where logdate > '2020-06-01' order by log
(0 rows)
drop table interval_normal_exchange;
drop table table_001;
ERROR: table "table_001" does not exist
create table table_001(
COL_1 smallint,
COL_2 char(5),
COL_3 int,
COL_4 date,
COL_5 boolean,
COL_6 nchar(5),
COL_7 float
);
drop table partition_table_001;
ERROR: table "partition_table_001" does not exist
create table partition_table_001(
COL_1 smallint,
COL_2 char(5),
COL_3 int,
COL_4 date,
COL_5 boolean,
COL_6 nchar(5),
COL_7 float
)
PARTITION BY RANGE (COL_4)
INTERVAL ('1 month')
(
PARTITION partition_table_001_p1 VALUES LESS THAN ('2020-03-01'),
PARTITION partition_table_001_p2 VALUES LESS THAN ('2020-04-01'),
PARTITION partition_table_001_p3 VALUES LESS THAN ('2020-05-01')
);
insert into partition_table_001 values (1,'aaa',1,'2020-02-23',true,'aaa',1.1);
insert into partition_table_001 values (2,'bbb',2,'2020-03-23',false,'bbb',2.2);
insert into partition_table_001 values (3,'ccc',3,'2020-04-23',true,'ccc',3.3);
insert into partition_table_001 values (4,'ddd',4,'2020-05-23',false,'ddd',4.4);
insert into partition_table_001 values (5,'eee',5,'2020-06-23',true,'eee',5.5);
insert into partition_table_001 values (6,'fff',6,'2020-07-23',false,'fff',6.6);
ALTER TABLE partition_table_001 EXCHANGE PARTITION (sys_p1) WITH TABLE table_001;
select * from table_001 order by 1;
col_1 | col_2 | col_3 | col_4 | col_5 | col_6 | col_7
-------+-------+-------+--------------------------+-------+-------+-------
4 | ddd | 4 | Sat May 23 00:00:00 2020 | f | ddd | 4.4
(1 row)
select * from partition_table_001 order by 1;
col_1 | col_2 | col_3 | col_4 | col_5 | col_6 | col_7
-------+-------+-------+--------------------------+-------+-------+-------
1 | aaa | 1 | Sun Feb 23 00:00:00 2020 | t | aaa | 1.1
2 | bbb | 2 | Mon Mar 23 00:00:00 2020 | f | bbb | 2.2
3 | ccc | 3 | Thu Apr 23 00:00:00 2020 | t | ccc | 3.3
5 | eee | 5 | Tue Jun 23 00:00:00 2020 | t | eee | 5.5
6 | fff | 6 | Thu Jul 23 00:00:00 2020 | f | fff | 6.6
(5 rows)
select relname, parttype, partstrategy, boundaries from pg_partition
where parentid = (select oid from pg_class where relname = 'partition_table_001')
order by relname;
relname | parttype | partstrategy | boundaries
------------------------+----------+--------------+------------------------------
partition_table_001 | r | i |
partition_table_001_p1 | p | r | {2020-03-01}
partition_table_001_p2 | p | r | {2020-04-01}
partition_table_001_p3 | p | r | {2020-05-01}
sys_p1 | p | i | {"Mon Jun 01 00:00:00 2020"}
sys_p2 | p | i | {"Wed Jul 01 00:00:00 2020"}
sys_p3 | p | i | {"Sat Aug 01 00:00:00 2020"}
(7 rows)
ALTER TABLE partition_table_001 EXCHANGE PARTITION (sys_p1) WITH TABLE table_001;
select * from table_001 order by 1;
col_1 | col_2 | col_3 | col_4 | col_5 | col_6 | col_7
-------+-------+-------+-------+-------+-------+-------
(0 rows)
select * from partition_table_001 order by 1;
col_1 | col_2 | col_3 | col_4 | col_5 | col_6 | col_7
-------+-------+-------+--------------------------+-------+-------+-------
1 | aaa | 1 | Sun Feb 23 00:00:00 2020 | t | aaa | 1.1
2 | bbb | 2 | Mon Mar 23 00:00:00 2020 | f | bbb | 2.2
3 | ccc | 3 | Thu Apr 23 00:00:00 2020 | t | ccc | 3.3
4 | ddd | 4 | Sat May 23 00:00:00 2020 | f | ddd | 4.4
5 | eee | 5 | Tue Jun 23 00:00:00 2020 | t | eee | 5.5
6 | fff | 6 | Thu Jul 23 00:00:00 2020 | f | fff | 6.6
(6 rows)
insert into table_001 values (7,'eee',7,'2020-08-23',true,'eee',7.7);
ALTER TABLE partition_table_001 EXCHANGE PARTITION (sys_p1) WITH TABLE table_001 with validation verbose;
select * from table_001 order by 1;
col_1 | col_2 | col_3 | col_4 | col_5 | col_6 | col_7
-------+-------+-------+--------------------------+-------+-------+-------
4 | ddd | 4 | Sat May 23 00:00:00 2020 | f | ddd | 4.4
(1 row)
select * from partition_table_001 order by 1;
col_1 | col_2 | col_3 | col_4 | col_5 | col_6 | col_7
-------+-------+-------+--------------------------+-------+-------+-------
1 | aaa | 1 | Sun Feb 23 00:00:00 2020 | t | aaa | 1.1
2 | bbb | 2 | Mon Mar 23 00:00:00 2020 | f | bbb | 2.2
3 | ccc | 3 | Thu Apr 23 00:00:00 2020 | t | ccc | 3.3
5 | eee | 5 | Tue Jun 23 00:00:00 2020 | t | eee | 5.5
6 | fff | 6 | Thu Jul 23 00:00:00 2020 | f | fff | 6.6
7 | eee | 7 | Sun Aug 23 00:00:00 2020 | t | eee | 7.7
(6 rows)
drop table table_001;
drop table partition_table_001;

View File

@ -0,0 +1,55 @@
CREATE TABLE t11 (
sec_code character(6) NOT NULL,
issue_type character(3) NOT NULL
);
CREATE TABLE t22 (
company_code character(6) NOT NULL,
list_profit_flag character(1) NOT NULL
);
CREATE TABLE t33 (
company_code character(6) NOT NULL,
issue_flag character(6) NOT NULL
);
insert into t11 values(1,'S04');
insert into t22 values(1,'Y');
insert into t33 values(1,'1');
insert into t33 values(2,'2');
select
T5.issue_type
,T6.is_type
from
(
select T1.sec_code
,issue_type
--,case when list_profit_flag='Y' then '是' else '否' end as list_profit_flag
from
(
select sec_code
,case when issue_type in ('S04','S05','S06','S09') then '增发'
when issue_type in ('S01','S02') then '首发'
else '其他' end as issue_type
from t11
)T1
left join
(
select list_profit_flag
,company_code
from t22
)T2
on T1.sec_code=T2.company_code
)T5
full join
(
SELECT CASE
WHEN issue_flag = ANY (ARRAY['1'::bpchar, '3'::bpchar, '11'::bpchar]) THEN '首发'::text
ELSE '增发'::text
END AS is_type from t33
)T6
on T5.issue_type=T6.is_type
;
issue_type | is_type
------------+---------
增发 | 增发
| 首发
(2 rows)

View File

@ -89,5 +89,8 @@ ERROR: Can not use compress option in ustore index.
-- segment
CREATE TABLE unspported_feature.segment_table(id int, c1 text) WITH(compresstype=2, segment=on); --failed
ERROR: only row orientation table support compresstype.
CREATE INDEX on unspported_feature.index_test(c1) WITH(compresstype=2, segment=on); --faled
CREATE INDEX on unspported_feature.index_test(c1) WITH(compresstype=2, segment=on); --failed
ERROR: Can not use compress option in segment storage.
-- set compress_diff_convert
create table unspported_feature.compress_byte_test(id int) with (compresstype=2, compress_byte_convert=false, compress_diff_convert = true); -- failed
ERROR: compress_diff_convert should be used with compress_byte_convert.

View File

@ -1062,6 +1062,73 @@ select /*+ indexscan(tg_hash i_tg_hash_local_a) */ * from tg_hash where a < 9;
(81 rows)
drop table tg_hash;
drop table if exists test_ugi_045;
NOTICE: table "test_ugi_045" does not exist, skipping
create table test_ugi_045
(
c_id integer not null,
c_date DATE,
c_info varchar(20) not null
)
partition by range(c_date)
interval('2 day')
(
partition p1 values less than ('2021-06-01 00:00:00'),
partition p2 values less than ('2021-06-03 00:00:00'),
partition p3 values less than ('2021-06-05 00:00:00'),
partition p4 values less than ('2021-06-07 00:00:00'),
partition p5 values less than ('2021-06-09 00:00:00')
);
insert into test_ugi_045(c_id, c_date, c_info) values(1, '2021-05-30 00:00:00', '1-1');
insert into test_ugi_045(c_id, c_date, c_info) values(2, '2021-05-31 00:00:00', '1-1');
insert into test_ugi_045(c_id, c_date, c_info) values(3, '2021-06-01 00:00:00', '1-1');
insert into test_ugi_045(c_id, c_date, c_info) values(4, '2021-06-02 00:00:00', '1-2');
insert into test_ugi_045(c_id, c_date, c_info) values(5, '2021-06-03 00:00:00', '1-2');
insert into test_ugi_045(c_id, c_date, c_info) values(6, '2021-06-04 00:00:00', '1-3');
insert into test_ugi_045(c_id, c_date, c_info) values(7, '2021-06-05 00:00:00', '1-3');
insert into test_ugi_045(c_id, c_date, c_info) values(8, '2021-06-06 00:00:00', '1-4');
insert into test_ugi_045(c_id, c_date, c_info) values(9, '2021-06-07 00:00:00', '1-4');
insert into test_ugi_045(c_id, c_date, c_info) values(10, '2021-06-08 00:00:00', '1-5');
create index global_index_id_045 on test_ugi_045(c_date) global;
create index global_index_info_045 on test_ugi_045(c_info) global;
select *from test_ugi_045;
c_id | c_date | c_info
------+---------------------+--------
1 | 2021-05-30 00:00:00 | 1-1
2 | 2021-05-31 00:00:00 | 1-1
3 | 2021-06-01 00:00:00 | 1-1
4 | 2021-06-02 00:00:00 | 1-2
5 | 2021-06-03 00:00:00 | 1-2
6 | 2021-06-04 00:00:00 | 1-3
7 | 2021-06-05 00:00:00 | 1-3
8 | 2021-06-06 00:00:00 | 1-4
9 | 2021-06-07 00:00:00 | 1-4
10 | 2021-06-08 00:00:00 | 1-5
(10 rows)
alter table test_ugi_045 truncate partition p3 update global index;
set enable_seqscan = off;
set enable_bitmapscan = off;
select *from test_ugi_045;
c_id | c_date | c_info
------+---------------------+--------
1 | 2021-05-30 00:00:00 | 1-1
2 | 2021-05-31 00:00:00 | 1-1
3 | 2021-06-01 00:00:00 | 1-1
4 | 2021-06-02 00:00:00 | 1-2
7 | 2021-06-05 00:00:00 | 1-3
8 | 2021-06-06 00:00:00 | 1-4
9 | 2021-06-07 00:00:00 | 1-4
10 | 2021-06-08 00:00:00 | 1-5
(8 rows)
select *from test_ugi_045 where c_info = '1-2';
c_id | c_date | c_info
------+---------------------+--------
4 | 2021-06-02 00:00:00 | 1-2
(1 row)
drop table if exists test_ugi_045;
-- 清理过程
drop view check_truncate_results;
drop materialized view pg_partition_before_truncate;

View File

@ -25,7 +25,7 @@ test: pldeveloper_gs_source
test: index_advisor
test: pl_debugger_server pl_debugger_client
test: update_for_wait_s1 update_for_wait_s2
test: plan_hint plan_hint_set plan_hint_no_expand plan_hint_iud null_test_opt
test: plan_hint plan_hint_set plan_hint_no_expand plan_hint_iud null_test_opt deserialize_func
test: large_sequence int16 gs_dump_sequence
test: gs_dump_tableof
test: analyze_commands
@ -916,3 +916,5 @@ test: fdw_audit
test: gs_global_config_audit
test: detail
test: gs_dump_encrypt
test: composite_datum_record
test: join_test_alias

View File

@ -5238,7 +5238,7 @@ static void check_global_variables()
}
}
#define BASE_PGXC_LIKE_MACRO_NUM 1401
#define BASE_PGXC_LIKE_MACRO_NUM 1402
static void check_pgxc_like_macros()
{
#ifdef BUILD_BY_CMAKE

View File

@ -0,0 +1,11 @@
--
-- check for over-optimization of whole-row Var referencing an Append plan
--
create table int4_test(f1 int4);
select (select q from (select 1,2,3 where f1>0 union all select 4,5,6 where f1<=0) q) from int4_test;
select (select q from (select 1,2,3 where f1>0 union all select 4,5,6.0 where f1<=0) q) from int4_test;
insert into int4_test(f1) values(' 0 ');
insert into int4_test(f1) values('123456 ');
select * from int4_test;
select (select q from (select 1,2,3 where f1>0 union all select 4,5,6 where f1<=0) q) from int4_test;
select (select q from (select 1,2,3 where f1>0 union all select 4,5,6.0 where f1<=0) q) from int4_test;

Some files were not shown because too many files have changed in this diff Show More