Add ignore keyword feature.

This commit is contained in:
totaj
2024-06-07 18:20:35 +08:00
committed by yaoxin
parent 3956405d29
commit 92307c5590
11 changed files with 177 additions and 4 deletions

View File

@ -92,6 +92,7 @@ bbox_dump_count|int|1,20|NULL|NULL|
bbox_dump_path|string|0,0|NULL|NULL|
b_format_behavior_compat_options|string|0,0|NULL|NULL|
behavior_compat_options|string|0,0|NULL|NULL|
disable_keyword_options|string|0,0|NULL|NULL|
plsql_compile_check_options|string|0,0|NULL|NULL|
bgwriter_delay|int|10,10000|ms|NULL|
bgwriter_lru_maxpages|int|0,1000|NULL|NULL|

View File

@ -25,6 +25,7 @@
#include "parser/gramparse.h"
#include "parser/parser.h"
#include "utils/guc.h"
extern void resetOperatorPlusFlag();
@ -799,3 +800,42 @@ char** get_next_snippet(
return query_string_single;
}
const struct ignore_keyword_opt_data ignore_keywords[] = {
{"interval", INTERVAL}
};
#define INGORE_KEYWORDS_LEN (sizeof(ignore_keywords) / sizeof(struct ignore_keyword_opt_data))
/*
* @Description: Avoid hooks, privides public interface, this can select ignore_keywords_list based on database
* compatibility to find ignore_keywords.
* @Param [IN] item: keyword
* @return token: token value for import item in ignore_keywords_list, if not in ignore_keywords_list, reutrn -1.
*/
int16 semtc_get_ignore_keyword_token(const char *item)
{
const struct ignore_keyword_opt_data *ignore_keywords_list = ignore_keywords;
int ignore_keywords_length = (int)INGORE_KEYWORDS_LEN;
for (int i = 0; i < ignore_keywords_length; i++) {
if (strcmp(item, ignore_keywords_list[i].option_name) == 0) {
return ignore_keywords_list[i].token;
}
}
return -1;
}
bool semtc_is_token_in_ignore_keyword_list(int token, bool isPlpgsqlKeyword)
{
ListCell *cell = NULL;
List *keyword_list = isPlpgsqlKeyword ? NULL : u_sess->utils_cxt.ignore_keyword_list;
foreach(cell, keyword_list)
{
int ignore_token = lfirst_int(cell);
if (token == ignore_token) {
return true;
}
}
return false;
}

View File

@ -1128,8 +1128,9 @@ other .
yyextra->is_hint_str = false;
bool isPlpgsqlKeyword = yyextra->isPlpgsqlKeyWord;
if (kwnum >= 0)
bool need_ignore = (!isPlpgsqlKeyword && kwnum >= 0) ?
semtc_is_token_in_ignore_keyword_list(yyextra->keyword_tokens[kwnum], false) : false;
if (kwnum >= 0 && !need_ignore)
{
yylval->keyword = GetScanKeyword(kwnum, yyextra->keywordlist);
uint16 token = yyextra->keyword_tokens[kwnum];

View File

@ -192,6 +192,8 @@ static bool check_snapshot_separator(char** newval, void** extra, GucSource sour
static bool check_sql_ignore_strategy(char** newval, void** extra, GucSource source);
static void assign_sql_ignore_strategy(const char* newval, void* extra);
static void strategy_assign_vector_targetlist(int newval, void* extra);
static bool check_disable_keyword_options(char **newval, void **extra, GucSource source);
static void assign_disable_keyword_options(const char *newval, void *extra);
static void InitSqlConfigureNamesBool();
static void InitSqlConfigureNamesInt();
@ -2893,6 +2895,18 @@ static void InitSqlConfigureNamesString()
check_behavior_compat_options,
assign_behavior_compat_options,
NULL},
{{"disable_keyword_options",
PGC_USERSET,
NODE_ALL,
COMPAT_OPTIONS,
gettext_noop("compatibility keyword options"),
NULL,
GUC_LIST_INPUT | GUC_REPORT},
&u_sess->attr.attr_sql.disable_keyword_string,
"",
check_disable_keyword_options,
assign_disable_keyword_options,
NULL},
{{"plsql_compile_check_options",
PGC_USERSET,
NODE_SINGLENODE,
@ -3665,6 +3679,73 @@ static void assign_behavior_compat_options(const char* newval, void* extra)
u_sess->utils_cxt.behavior_compat_flags = result;
}
static bool check_disable_keyword_options(char **newval, void **extra, GucSource source)
{
char *rawstring = NULL;
List *elemlist = NULL;
ListCell *cell = NULL;
/* Need a modifiable copy of string */
rawstring = pstrdup(*newval);
/* Parse string into list of identifiers */
if (!SplitIdentifierString(rawstring, ',', &elemlist)) {
/* syntax error in list */
GUC_check_errdetail("invalid paramater for disable keyword information.");
pfree(rawstring);
list_free(elemlist);
return false;
}
MemoryContext old_context = MemoryContextSwitchTo(SESS_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_CBB));
foreach(cell, elemlist)
{
const char *item = (const char *)lfirst(cell);
int token = semtc_get_ignore_keyword_token(item);
if (token < 0) {
GUC_check_errdetail("invalid disable keyword \"%s\"", item);
MemoryContextSwitchTo(old_context);
pfree(rawstring);
list_free(elemlist);
return false;
}
}
MemoryContextSwitchTo(old_context);
pfree(rawstring);
list_free(elemlist);
return true;
}
static void assign_disable_keyword_options(const char *newval, void *extra)
{
char *rawstring = NULL;
List *elemlist = NULL;
ListCell *cell = NULL;
List* result = NULL;
rawstring = pstrdup(newval);
(void)SplitIdentifierString(rawstring, ',', &elemlist);
list_free_ext(u_sess->utils_cxt.ignore_keyword_list);
MemoryContext old_context = MemoryContextSwitchTo(SESS_GET_MEM_CXT_GROUP(MEMORY_CONTEXT_CBB));
foreach(cell, elemlist)
{
const char *item = (const char *)lfirst(cell);
int token = semtc_get_ignore_keyword_token(item);
if (token >= 0) {
result = lappend_int(result, token);
}
}
MemoryContextSwitchTo(old_context);
pfree(rawstring);
list_free(elemlist);
u_sess->utils_cxt.ignore_keyword_list = result;
}
/*
* check_behavior_compat_options: GUC check_hook for behavior compat options
*/

View File

@ -478,6 +478,7 @@ static void knl_u_utils_init(knl_u_utils_context* utils_cxt)
utils_cxt->spi_printtupDR = (DestReceiver*)palloc0(sizeof(DestReceiver));
InitSpiPrinttupDR(utils_cxt->spi_printtupDR);
utils_cxt->ignore_keyword_list = NIL;
}
static void knl_u_security_init(knl_u_security_context* sec_cxt) {

View File

@ -196,6 +196,7 @@ typedef struct knl_session_attr_sql {
char* b_format_behavior_compat_string;
char* behavior_compat_string;
char* plsql_compile_behavior_compat_string;
char* disable_keyword_string;
char* connection_info;
char* retry_errcode_list;
char* sql_ignore_strategy_string;

View File

@ -696,6 +696,7 @@ typedef struct knl_u_utils_context {
/* var in tsrank.cpp */
float tsrankWs[TSRANK_WEIGHTS_LEN];
List* ignore_keyword_list;
} knl_u_utils_context;
typedef struct knl_u_security_context {

View File

@ -153,6 +153,11 @@ struct config_enum_entry {
bool hidden;
};
struct ignore_keyword_opt_data {
const char* option_name;
uint16 token;
};
/*
* Signatures for per-variable check/assign/show hook functions
*/
@ -555,6 +560,8 @@ extern char* SetVariableExprGetConfigOption(SetVariableExpr* set);
#ifdef ENABLE_MULTIPLE_NODES
extern const char* show_nodegroup_mode(void);
#endif
extern int16 semtc_get_ignore_keyword_token(const char* item);
bool semtc_is_token_in_ignore_keyword_list(int token, bool isPlpgsqlKeyword = false);
extern THR_LOCAL GucContext currentGucContext;

View File

@ -0,0 +1,29 @@
create schema ignore_keyword_list;
set current_schema to 'ignore_keyword_list';
select 1 interval; --error
ERROR: syntax error at or near "interval"
LINE 1: select 1 interval;
^
set disable_keyword_options = 'interval';
select 1 interval; --ok
interval
----------
1
(1 row)
set disable_keyword_options = 'intervalxx';
ERROR: invalid value for parameter "disable_keyword_options": "intervalxx"
DETAIL: invalid disable keyword "intervalxx"
set disable_keyword_options = 'interval,interval';
select 1 interval; --ok
interval
----------
1
(1 row)
reset disable_keyword_options;
select 1 interval; --error
ERROR: syntax error at or near "interval"
LINE 1: select 1 interval;
^
drop schema ignore_keyword_list cascade;

View File

@ -478,5 +478,5 @@ test: alter_table_modify alter_table_modify_ustore alter_table_modify_ltt alter_
test: accept_empty_str not_accept_empty_str pg_empty_str accept_empty_copy not_accept_empty_copy
#test: gin/cgin
test: cgin_select
test: gin_select
test: cgin_select ignore_keyword_list
test: gin_select

View File

@ -0,0 +1,11 @@
create schema ignore_keyword_list;
set current_schema to 'ignore_keyword_list';
select 1 interval; --error
set disable_keyword_options = 'interval';
select 1 interval; --ok
set disable_keyword_options = 'intervalxx';
set disable_keyword_options = 'interval,interval';
select 1 interval; --ok
reset disable_keyword_options;
select 1 interval; --error
drop schema ignore_keyword_list cascade;