Fix substr compat with pg.
This commit is contained in:
@ -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);
|
||||
|
||||
|
||||
@ -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}
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@ -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 {
|
||||
|
||||
228
src/test/regress/expected/substr.out
Normal file
228
src/test/regress/expected/substr.out
Normal 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;
|
||||
@ -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
|
||||
|
||||
118
src/test/regress/sql/substr.sql
Normal file
118
src/test/regress/sql/substr.sql
Normal 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;
|
||||
Reference in New Issue
Block a user