!1876 新增pgformat_substr兼容选项,在PG兼容模式下,substr的表现兼容PG

Merge pull request !1876 from pengjiong/array
This commit is contained in:
opengauss-bot
2022-06-22 01:45:37 +00:00
committed by Gitee
6 changed files with 360 additions and 5 deletions

View File

@ -42,6 +42,8 @@
#include "executor/node/nodeSort.h"
#include "pgxc/groupmgr.h"
#define SUBSTR_WITH_LEN_OFFSET 2
#define SUBSTR_A_CMPT_OFFSET 4
#define JUDGE_INPUT_VALID(X, Y) ((NULL == (X)) || (NULL == (Y)))
#define GET_POSITIVE(X) ((X) > 0 ? (X) : ((-1) * (X)))
static int getResultPostionReverse(text* textStr, text* textStrToSearch, int32 beginIndex, int occurTimes);
@ -1278,8 +1280,12 @@ Datum text_substr_orclcompat(PG_FUNCTION_ARGS)
FUNC_CHECK_HUGE_POINTER(PG_ARGISNULL(0), DatumGetPointer(str), "text_substr()");
is_compress = (VARATT_IS_COMPRESSED(DatumGetPointer(str)) || VARATT_IS_EXTERNAL(DatumGetPointer(str)));
// orclcompat is true, withlen is true
baseIdx = 6 + (int)is_compress + (eml - 1) * 8;
/* withlen is true */
baseIdx = SUBSTR_WITH_LEN_OFFSET + (int)is_compress + (eml - 1) * 8;
if (!PGFORMAT_SUBSTR || !DB_IS_CMPT(PG_FORMAT)) {
/* if pgformat_substr is not on or current database is not pg format, use A cmpt */
baseIdx += SUBSTR_A_CMPT_OFFSET;
}
result = (*substr_Array[baseIdx])(str, start, length, &is_null, fun_mblen);

View File

@ -329,7 +329,8 @@ static const struct behavior_compat_entry behavior_compat_options[OPT_MAX] = {
{"aformat_regexp_match", OPT_AFORMAT_REGEX_MATCH},
{"rownum_type_compat", OPT_ROWNUM_TYPE_COMPAT},
{"compat_cursor", OPT_COMPAT_CURSOR},
{"char_coerce_compat", OPT_CHAR_COERCE_COMPAT}
{"char_coerce_compat", OPT_CHAR_COERCE_COMPAT},
{"pgformat_substr", OPT_PGFORMAT_SUBSTR}
};
/*

View File

@ -127,7 +127,8 @@ extern bool contain_backend_version(uint32 version_number);
#define OPT_ROWNUM_TYPE_COMPAT 1048576
#define OPT_COMPAT_CURSOR 2097152
#define OPT_CHAR_COERCE_COMPAT 4194304
#define OPT_MAX 23
#define OPT_PGFORMAT_SUBSTR 8388608
#define OPT_MAX 24
#define DISPLAY_LEADING_ZERO (u_sess->utils_cxt.behavior_compat_flags & OPT_DISPLAY_LEADING_ZERO)
@ -156,6 +157,7 @@ extern bool contain_backend_version(uint32 version_number);
#define ROWNUM_TYPE_COMPAT (u_sess->utils_cxt.behavior_compat_flags & OPT_ROWNUM_TYPE_COMPAT)
#define COMPAT_CURSOR (u_sess->utils_cxt.behavior_compat_flags & OPT_COMPAT_CURSOR)
#define CHAR_COERCE_COMPAT (u_sess->utils_cxt.behavior_compat_flags & OPT_CHAR_COERCE_COMPAT)
#define PGFORMAT_SUBSTR (u_sess->utils_cxt.behavior_compat_flags & OPT_PGFORMAT_SUBSTR)
/* define database compatibility Attribute */
typedef struct {

View File

@ -0,0 +1,228 @@
CREATE DATABASE substr_pg_format with dbcompatibility 'pg';
\c substr_pg_format
show behavior_compat_options;
behavior_compat_options
-------------------------
(1 row)
CREATE TABLE toasttest(f1 text);
insert into toasttest values(repeat('1234567890',10000));
insert into toasttest values(repeat('1234567890',10000));
--
-- Ensure that some values are uncompressed, to test the faster substring
-- operation used in that case
--
alter table toasttest alter column f1 set storage external;
insert into toasttest values(repeat('1234567890',10000));
insert into toasttest values(repeat('1234567890',10000));
-- If the starting position is zero or less, then return from the start of the string
-- adjusting the length to be consistent with the "negative start" per SQL92.
SELECT substr(f1, -1, 5) from toasttest;
substr
--------
0
0
0
0
(4 rows)
-- If the length is less than zero, an ERROR is thrown.
SELECT substr(f1, 5, -1) from toasttest;
substr
--------
(4 rows)
-- If no third argument (length) is provided, the length to the end of the
-- string is assumed.
SELECT substr(f1, 99995) from toasttest;
substr
--------
567890
567890
567890
567890
(4 rows)
-- If start plus length is > string length, the result is truncated to
-- string length
SELECT substr(f1, 99995, 10) from toasttest;
substr
--------
567890
567890
567890
567890
(4 rows)
DROP TABLE toasttest;
--
-- test substr with toasted bytea values
--
CREATE TABLE toasttest(f1 bytea);
insert into toasttest values(decode(repeat('1234567890',10000),'escape'));
insert into toasttest values(decode(repeat('1234567890',10000),'escape'));
--
-- Ensure that some values are uncompressed, to test the faster substring
-- operation used in that case
--
alter table toasttest alter column f1 set storage external;
insert into toasttest values(decode(repeat('1234567890',10000),'escape'));
insert into toasttest values(decode(repeat('1234567890',10000),'escape'));
-- If the starting position is zero or less, then return from the start of the string
-- adjusting the length to be consistent with the "negative start" per SQL92.
SELECT substr(f1, -1, 5) from toasttest;
substr
--------
\x30
\x30
\x30
\x30
(4 rows)
-- If the length is less than zero, an ERROR is thrown.
SELECT substr(f1, 5, -1) from toasttest;
substr
--------
\x
\x
\x
\x
(4 rows)
ERROR: negative substring length not allowed
-- If no third argument (length) is provided, the length to the end of the
-- string is assumed.
SELECT substr(f1, 99995) from toasttest;
ERROR: syntax error at or near "ERROR"
LINE 1: ERROR: negative substring length not allowed
^
-- If start plus length is > string length, the result is truncated to
-- string length
SELECT substr(f1, 99995, 10) from toasttest;
substr
----------------
\x353637383930
\x353637383930
\x353637383930
\x353637383930
(4 rows)
DROP TABLE toasttest;
-----------------------------------------------------------------
--- retest with behavior_compat_options to 'pgformat_substr'
-----------------------------------------------------------------
set behavior_compat_options to 'pgformat_substr';
show behavior_compat_options;
behavior_compat_options
-------------------------
pgformat_substr
(1 row)
CREATE TABLE toasttest(f1 text);
insert into toasttest values(repeat('1234567890',10000));
insert into toasttest values(repeat('1234567890',10000));
--
-- Ensure that some values are uncompressed, to test the faster substring
-- operation used in that case
--
alter table toasttest alter column f1 set storage external;
insert into toasttest values(repeat('1234567890',10000));
insert into toasttest values(repeat('1234567890',10000));
-- If the starting position is zero or less, then return from the start of the string
-- adjusting the length to be consistent with the "negative start" per SQL92.
SELECT substr(f1, -1, 5) from toasttest;
substr
--------
123
123
123
123
(4 rows)
-- If the length is less than zero, an ERROR is thrown.
SELECT substr(f1, 5, -1) from toasttest;
ERROR: negative substring length not allowed
CONTEXT: referenced column: substr
-- If no third argument (length) is provided, the length to the end of the
-- string is assumed.
SELECT substr(f1, 99995) from toasttest;
substr
--------
567890
567890
567890
567890
(4 rows)
-- If start plus length is > string length, the result is truncated to
-- string length
SELECT substr(f1, 99995, 10) from toasttest;
substr
--------
567890
567890
567890
567890
(4 rows)
DROP TABLE toasttest;
--
-- test substr with toasted bytea values
--
CREATE TABLE toasttest(f1 bytea);
insert into toasttest values(decode(repeat('1234567890',10000),'escape'));
insert into toasttest values(decode(repeat('1234567890',10000),'escape'));
--
-- Ensure that some values are uncompressed, to test the faster substring
-- operation used in that case
--
alter table toasttest alter column f1 set storage external;
insert into toasttest values(decode(repeat('1234567890',10000),'escape'));
insert into toasttest values(decode(repeat('1234567890',10000),'escape'));
-- If the starting position is zero or less, then return from the start of the string
-- adjusting the length to be consistent with the "negative start" per SQL92.
SELECT substr(f1, -1, 5) from toasttest;
substr
--------
\x30
\x30
\x30
\x30
(4 rows)
-- If the length is less than zero, an ERROR is thrown.
SELECT substr(f1, 5, -1) from toasttest;
substr
--------
\x
\x
\x
\x
(4 rows)
ERROR: negative substring length not allowed
-- If no third argument (length) is provided, the length to the end of the
-- string is assumed.
SELECT substr(f1, 99995) from toasttest;
ERROR: syntax error at or near "ERROR"
LINE 1: ERROR: negative substring length not allowed
^
-- If start plus length is > string length, the result is truncated to
-- string length
SELECT substr(f1, 99995, 10) from toasttest;
substr
----------------
\x353637383930
\x353637383930
\x353637383930
\x353637383930
(4 rows)
DROP TABLE toasttest;
\c regression;
drop database IF EXISTS substr_pg_format;

View File

@ -915,7 +915,7 @@ test: subscription
test: fdw_audit
test: gs_global_config_audit
test: detail declare_multiple_variable
test: gs_dump_encrypt
test: gs_dump_encrypt substr
test: composite_datum_record mysql_function
test: join_test_alias

View File

@ -0,0 +1,118 @@
CREATE DATABASE substr_pg_format with dbcompatibility 'pg';
\c substr_pg_format
show behavior_compat_options;
CREATE TABLE toasttest(f1 text);
insert into toasttest values(repeat('1234567890',10000));
insert into toasttest values(repeat('1234567890',10000));
--
-- Ensure that some values are uncompressed, to test the faster substring
-- operation used in that case
--
alter table toasttest alter column f1 set storage external;
insert into toasttest values(repeat('1234567890',10000));
insert into toasttest values(repeat('1234567890',10000));
-- If the starting position is zero or less, then return from the start of the string
-- adjusting the length to be consistent with the "negative start" per SQL92.
SELECT substr(f1, -1, 5) from toasttest;
-- If the length is less than zero, an ERROR is thrown.
SELECT substr(f1, 5, -1) from toasttest;
-- If no third argument (length) is provided, the length to the end of the
-- string is assumed.
SELECT substr(f1, 99995) from toasttest;
-- If start plus length is > string length, the result is truncated to
-- string length
SELECT substr(f1, 99995, 10) from toasttest;
DROP TABLE toasttest;
--
-- test substr with toasted bytea values
--
CREATE TABLE toasttest(f1 bytea);
insert into toasttest values(decode(repeat('1234567890',10000),'escape'));
insert into toasttest values(decode(repeat('1234567890',10000),'escape'));
--
-- Ensure that some values are uncompressed, to test the faster substring
-- operation used in that case
--
alter table toasttest alter column f1 set storage external;
insert into toasttest values(decode(repeat('1234567890',10000),'escape'));
insert into toasttest values(decode(repeat('1234567890',10000),'escape'));
-- If the starting position is zero or less, then return from the start of the string
-- adjusting the length to be consistent with the "negative start" per SQL92.
SELECT substr(f1, -1, 5) from toasttest;
-- If the length is less than zero, an ERROR is thrown.
SELECT substr(f1, 5, -1) from toasttest;
ERROR: negative substring length not allowed
-- If no third argument (length) is provided, the length to the end of the
-- string is assumed.
SELECT substr(f1, 99995) from toasttest;
-- If start plus length is > string length, the result is truncated to
-- string length
SELECT substr(f1, 99995, 10) from toasttest;
DROP TABLE toasttest;
-----------------------------------------------------------------
--- retest with behavior_compat_options to 'pgformat_substr'
-----------------------------------------------------------------
set behavior_compat_options to 'pgformat_substr';
show behavior_compat_options;
CREATE TABLE toasttest(f1 text);
insert into toasttest values(repeat('1234567890',10000));
insert into toasttest values(repeat('1234567890',10000));
--
-- Ensure that some values are uncompressed, to test the faster substring
-- operation used in that case
--
alter table toasttest alter column f1 set storage external;
insert into toasttest values(repeat('1234567890',10000));
insert into toasttest values(repeat('1234567890',10000));
-- If the starting position is zero or less, then return from the start of the string
-- adjusting the length to be consistent with the "negative start" per SQL92.
SELECT substr(f1, -1, 5) from toasttest;
-- If the length is less than zero, an ERROR is thrown.
SELECT substr(f1, 5, -1) from toasttest;
-- If no third argument (length) is provided, the length to the end of the
-- string is assumed.
SELECT substr(f1, 99995) from toasttest;
-- If start plus length is > string length, the result is truncated to
-- string length
SELECT substr(f1, 99995, 10) from toasttest;
DROP TABLE toasttest;
--
-- test substr with toasted bytea values
--
CREATE TABLE toasttest(f1 bytea);
insert into toasttest values(decode(repeat('1234567890',10000),'escape'));
insert into toasttest values(decode(repeat('1234567890',10000),'escape'));
--
-- Ensure that some values are uncompressed, to test the faster substring
-- operation used in that case
--
alter table toasttest alter column f1 set storage external;
insert into toasttest values(decode(repeat('1234567890',10000),'escape'));
insert into toasttest values(decode(repeat('1234567890',10000),'escape'));
-- If the starting position is zero or less, then return from the start of the string
-- adjusting the length to be consistent with the "negative start" per SQL92.
SELECT substr(f1, -1, 5) from toasttest;
-- If the length is less than zero, an ERROR is thrown.
SELECT substr(f1, 5, -1) from toasttest;
ERROR: negative substring length not allowed
-- If no third argument (length) is provided, the length to the end of the
-- string is assumed.
SELECT substr(f1, 99995) from toasttest;
-- If start plus length is > string length, the result is truncated to
-- string length
SELECT substr(f1, 99995, 10) from toasttest;
DROP TABLE toasttest;
\c regression;
drop database IF EXISTS substr_pg_format;