While trying to add something useful into INSERT statement, I wrote more simple example, just to find out how it should work.
I think this might be helpful to people that also want to hack into that area.
Example is very simple, it adds keyword TEST into the definition of attribute list into CREATE INDEX statement, and in ComputeIndexAttrs it says using elog(WARNING ...) whether it found TEST keyword or not.
This example is not for production development, it just shows what part of code you should touch in order to modify grammar.
I think this might be helpful to people that also want to hack into that area.
Example is very simple, it adds keyword TEST into the definition of attribute list into CREATE INDEX statement, and in ComputeIndexAttrs it says using elog(WARNING ...) whether it found TEST keyword or not.
postgres=# create index ON mytable (i TEST 'value'); WARNING: Creating index for column i with TEST value CREATE INDEX postgres=# create index ON mytable (i); WARNING: TEST is empty CREATE INDEX
This example is not for production development, it just shows what part of code you should touch in order to modify grammar.
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c index c294c7c..138190e 100644 --- a/src/backend/commands/indexcmds.c +++ b/src/backend/commands/indexcmds.c @@ -1041,6 +1041,14 @@ ComputeIndexAttrs(IndexInfo *indexInfo, /* Simple index attribute */ HeapTuple atttuple; Form_pg_attribute attform; + + if (attribute->test) + { + elog(WARNING, "Creating index for column %s with TEST %s", attribute->name, attribute->test); + } else + { + elog(WARNING, "TEST is empty"); + } Assert(attribute->expr == NULL); atttuple = SearchSysCacheAttName(relId, attribute->name); diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index 20e38f0..155070c 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -2591,6 +2591,7 @@ _copyIndexElem(const IndexElem *from) COPY_NODE_FIELD(opclass); COPY_SCALAR_FIELD(ordering); COPY_SCALAR_FIELD(nulls_ordering); + COPY_STRING_FIELD(test); return newnode; } diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 18ec5f0..597ad57 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -316,7 +316,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); %type copy_file_name database_name access_method_clause access_method attr_name name cursor_name file_name - index_name opt_index_name cluster_index_specification + index_name opt_index_name cluster_index_specification opt_test %type func_name handler_name qual_Op qual_all_Op subquery_Op opt_class opt_inline_handler opt_validator validator_clause @@ -632,7 +632,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); STATEMENT STATISTICS STDIN STDOUT STORAGE STRICT_P STRIP_P SUBSTRING SYMMETRIC SYSID SYSTEM_P - TABLE TABLES TABLESAMPLE TABLESPACE TEMP TEMPLATE TEMPORARY TEXT_P THEN + TABLE TABLES TABLESAMPLE TABLESPACE TEMP TEMPLATE TEMPORARY TEST TEXT_P THEN TIME TIMESTAMP TO TRAILING TRANSACTION TRANSFORM TREAT TRIGGER TRIM TRUE_P TRUNCATE TRUSTED TYPE_P TYPES_P @@ -715,6 +715,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query); %left '(' ')' %left TYPECAST %left '.' + /* * These might seem to be low-precedence, but actually they are not part * of the arithmetic hierarchy at all in their use as JOIN operators. @@ -6707,7 +6708,7 @@ index_params: index_elem { $$ = list_make1($1); } * expressions in parens. For backwards-compatibility reasons, we allow * an expression that's just a function call to be written without parens. */ -index_elem: ColId opt_collate opt_class opt_asc_desc opt_nulls_order +index_elem: ColId opt_collate opt_class opt_asc_desc opt_nulls_order opt_test { $$ = makeNode(IndexElem); $$->name = $1; @@ -6717,8 +6718,9 @@ index_elem: ColId opt_collate opt_class opt_asc_desc opt_nulls_order $$->opclass = $3; $$->ordering = $4; $$->nulls_ordering = $5; + $$->test = $6; } - | func_expr_windowless opt_collate opt_class opt_asc_desc opt_nulls_order + | func_expr_windowless opt_collate opt_class opt_asc_desc opt_nulls_order opt_test { $$ = makeNode(IndexElem); $$->name = NULL; @@ -6728,8 +6730,9 @@ index_elem: ColId opt_collate opt_class opt_asc_desc opt_nulls_order $$->opclass = $3; $$->ordering = $4; $$->nulls_ordering = $5; + $$->test = $6; } - | '(' a_expr ')' opt_collate opt_class opt_asc_desc opt_nulls_order + | '(' a_expr ')' opt_collate opt_class opt_asc_desc opt_nulls_order opt_test { $$ = makeNode(IndexElem); $$->name = NULL; @@ -6739,6 +6742,7 @@ index_elem: ColId opt_collate opt_class opt_asc_desc opt_nulls_order $$->opclass = $5; $$->ordering = $6; $$->nulls_ordering = $7; + $$->test = $8; } ; @@ -6761,6 +6765,10 @@ opt_nulls_order: NULLS_LA FIRST_P { $$ = SORTBY_NULLS_FIRST; } | /*EMPTY*/ { $$ = SORTBY_NULLS_DEFAULT; } ; +opt_test: TEST Sconst { $$ = $2; } + | /*EMPTY*/ { $$ = NULL; } + ; + /***************************************************************************** * @@ -14159,6 +14167,7 @@ reserved_keyword: | SOME | SYMMETRIC | TABLE + | TEST | THEN | TO | TRAILING diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index 714cf15..54e3de8 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -638,6 +638,7 @@ typedef struct IndexElem List *opclass; /* name of desired opclass; NIL = default */ SortByDir ordering; /* ASC/DESC/default */ SortByNulls nulls_ordering; /* FIRST/LAST/default */ + char *test; } IndexElem; /* diff --git a/src/include/parser/kwlist.h b/src/include/parser/kwlist.h index 17ffef5..2b7f2fd 100644 --- a/src/include/parser/kwlist.h +++ b/src/include/parser/kwlist.h @@ -380,6 +380,7 @@ PG_KEYWORD("tablespace", TABLESPACE, UNRESERVED_KEYWORD) PG_KEYWORD("temp", TEMP, UNRESERVED_KEYWORD) PG_KEYWORD("template", TEMPLATE, UNRESERVED_KEYWORD) PG_KEYWORD("temporary", TEMPORARY, UNRESERVED_KEYWORD) +PG_KEYWORD("test", TEST, RESERVED_KEYWORD) PG_KEYWORD("text", TEXT_P, UNRESERVED_KEYWORD) PG_KEYWORD("then", THEN, RESERVED_KEYWORD) PG_KEYWORD("time", TIME, COL_NAME_KEYWORD)