From f80fb3050b22bbe74fa2ffcd733d9f8067db0cee Mon Sep 17 00:00:00 2001 From: chenxiaobin19 <1025221611@qq.com> Date: Thu, 29 Jul 2021 15:23:57 +0800 Subject: [PATCH] Correct help message and add syntax in tab-completion.cpp --- .../sgml/ref/create_client_master_key.sgmlin | 2 +- .../ref/create_column_encryption_key.sgmlin | 2 +- doc/src/sgml/ref/create_language.sgmlin | 332 ++++++++++++++++++ doc/src/sgml/ref/create_table.sgmlin | 19 +- src/bin/psql/tab-complete.cpp | 97 +++-- 5 files changed, 410 insertions(+), 42 deletions(-) create mode 100644 doc/src/sgml/ref/create_language.sgmlin diff --git a/doc/src/sgml/ref/create_client_master_key.sgmlin b/doc/src/sgml/ref/create_client_master_key.sgmlin index 9dd830de1..2bf091e66 100644 --- a/doc/src/sgml/ref/create_client_master_key.sgmlin +++ b/doc/src/sgml/ref/create_client_master_key.sgmlin @@ -10,7 +10,7 @@ -CREATE CLIENT MASTER KEY +CREATE CLIENT MASTER KEY client_master_key_name [WITH] ( ['KEY_STORE' , 'KEY_PATH' , 'ALGORITHM'] ); diff --git a/doc/src/sgml/ref/create_column_encryption_key.sgmlin b/doc/src/sgml/ref/create_column_encryption_key.sgmlin index 333a5339d..09a85d80b 100644 --- a/doc/src/sgml/ref/create_column_encryption_key.sgmlin +++ b/doc/src/sgml/ref/create_column_encryption_key.sgmlin @@ -10,7 +10,7 @@ -CREATE COLUMN ENCRYPTION KEY +CREATE COLUMN ENCRYPTION KEY column_encryption_key_name [WITH] ( ['CLIENT_MASTER_KEY' , 'ALGORITHM'] ); diff --git a/doc/src/sgml/ref/create_language.sgmlin b/doc/src/sgml/ref/create_language.sgmlin new file mode 100644 index 000000000..aeec4cc19 --- /dev/null +++ b/doc/src/sgml/ref/create_language.sgmlin @@ -0,0 +1,332 @@ + + + + + CREATE LANGUAGE + 7 + SQL - Language Statements + + + + CREATE LANGUAGE + define a new procedural language + + + + CREATE LANGUAGE + + + + +CREATE [ OR REPLACE ] [ PROCEDURAL ] LANGUAGE name; +CREATE [ OR REPLACE ] [ TRUSTED ] [ PROCEDURAL ] LANGUAGE name + HANDLER call_handler [ INLINE inline_handler ] [ VALIDATOR valfunction ]; + + + + + Description + + + CREATE LANGUAGE registers a new + procedural language with a PostgreSQL + database. Subsequently, functions and trigger procedures can be + defined in this new language. + + + + + As of PostgreSQL 9.1, most procedural + languages have been made into extensions, and should + therefore be installed with + not CREATE LANGUAGE. Direct use of + CREATE LANGUAGE should now be confined to + extension installation scripts. If you have a bare + language in your database, perhaps as a result of an upgrade, + you can convert it to an extension using + CREATE EXTENSION langname FROM + unpackaged. + + + + + CREATE LANGUAGE effectively associates the + language name with handler function(s) that are responsible for executing + functions written in the language. Refer to + for more information about language handlers. + + + + There are two forms of the CREATE LANGUAGE command. + In the first form, the user supplies just the name of the desired + language, and the PostgreSQL server consults + the pg_pltemplate + system catalog to determine the correct parameters. In the second form, + the user supplies the language parameters along with the language name. + The second form can be used to create a language that is not defined in + pg_pltemplate, but this approach is considered obsolescent. + + + + When the server finds an entry in the pg_pltemplate catalog + for the given language name, it will use the catalog data even if the + command includes language parameters. This behavior simplifies loading of + old dump files, which are likely to contain out-of-date information + about language support functions. + + + + Ordinarily, the user must have the + PostgreSQL superuser privilege to + register a new language. However, the owner of a database can register + a new language within that database if the language is listed in + the pg_pltemplate catalog and is marked + as allowed to be created by database owners (tmpldbacreate + is true). The default is that trusted languages can be created + by database owners, but this can be adjusted by superusers by modifying + the contents of pg_pltemplate. + The creator of a language becomes its owner and can later + drop it, rename it, or assign it to a new owner. + + + + CREATE OR REPLACE LANGUAGE will either create a + new language, or replace an existing definition. If the language + already exists, its parameters are updated according to the values + specified or taken from pg_pltemplate, + but the language's ownership and permissions settings do not change, + and any existing functions written in the language are assumed to still + be valid. In addition to the normal privilege requirements for creating + a language, the user must be superuser or owner of the existing language. + The REPLACE case is mainly meant to be used to + ensure that the language exists. If the language has a + pg_pltemplate entry then REPLACE + will not actually change anything about an existing definition, except in + the unusual case where the pg_pltemplate entry + has been modified since the language was created. + + + + + Parameters + + + + TRUSTED + + + TRUSTED specifies that the language does + not grant access to data that the user would not otherwise + have. If this key word is omitted + when registering the language, only users with the + PostgreSQL superuser privilege can + use this language to create new functions. + + + + + + PROCEDURAL + + + + This is a noise word. + + + + + + name + + + + The name of the new procedural language. + The name must be unique among the languages in the database. + + + + For backward compatibility, the name can be enclosed by single + quotes. + + + + + + HANDLER call_handler + + + call_handler is + the name of a previously registered function that will be + called to execute the procedural language's functions. The call + handler for a procedural language must be written in a compiled + language such as C with version 1 call convention and + registered with PostgreSQL as a + function taking no arguments and returning the + language_handler type, a placeholder type that is + simply used to identify the function as a call handler. + + + + + + INLINE inline_handler + + + inline_handler is the + name of a previously registered function that will be called + to execute an anonymous code block + ( command) + in this language. + If no inline_handler + function is specified, the language does not support anonymous code + blocks. + The handler function must take one argument of + type internal, which will be the DO command's + internal representation, and it will typically return + void. The return value of the handler is ignored. + + + + + + VALIDATOR valfunction + + + valfunction is the + name of a previously registered function that will be called + when a new function in the language is created, to validate the + new function. + If no + validator function is specified, then a new function will not + be checked when it is created. + The validator function must take one argument of + type oid, which will be the OID of the + to-be-created function, and will typically return void. + + + + A validator function would typically inspect the function body + for syntactical correctness, but it can also look at other + properties of the function, for example if the language cannot + handle certain argument types. To signal an error, the + validator function should use the ereport() + function. The return value of the function is ignored. + + + + + + + The TRUSTED option and the support function name(s) are + ignored if the server has an entry for the specified language + name in pg_pltemplate. + + + + + Notes + + + The program is a simple wrapper around + the CREATE LANGUAGE command. It eases + installation of procedural languages from the shell command line. + + + + Use , or better yet the program, to drop procedural languages. + + + + The system catalog pg_language (see ) records information about the + currently installed languages. Also, createlang + has an option to list the installed languages. + + + + To create functions in a procedural language, a user must have the + USAGE privilege for the language. By default, + USAGE is granted to PUBLIC (i.e., everyone) + for trusted languages. This can be revoked if desired. + + + + Procedural languages are local to individual databases. + However, a language can be installed into the template1 + database, which will cause it to be available automatically in + all subsequently-created databases. + + + + The call handler function, the inline handler function (if any), + and the validator function (if any) + must already exist if the server does not have an entry for the language + in pg_pltemplate. But when there is an entry, + the functions need not already exist; + they will be automatically defined if not present in the database. + (This might result in CREATE LANGUAGE failing, if the + shared library that implements the language is not available in + the installation.) + + + + In PostgreSQL versions before 7.3, it was + necessary to declare handler functions as returning the placeholder + type opaque, rather than language_handler. + To support loading + of old dump files, CREATE LANGUAGE will accept a function + declared as returning opaque, but it will issue a notice and + change the function's declared return type to language_handler. + + + + + Examples + + + The preferred way of creating any of the standard procedural languages + is just: + +CREATE LANGUAGE plperl; + + + + + For a language not known in the pg_pltemplate catalog, a + sequence such as this is needed: + +CREATE FUNCTION plsample_call_handler() RETURNS language_handler + AS '$libdir/plsample' + LANGUAGE C; +CREATE LANGUAGE plsample + HANDLER plsample_call_handler; + + + + + Compatibility + + + CREATE LANGUAGE is a + PostgreSQL extension. + + + + + See Also + + + + + + + + + + + + diff --git a/doc/src/sgml/ref/create_table.sgmlin b/doc/src/sgml/ref/create_table.sgmlin index c82ef2920..ba2fdfa48 100644 --- a/doc/src/sgml/ref/create_table.sgmlin +++ b/doc/src/sgml/ref/create_table.sgmlin @@ -18,11 +18,7 @@ CREATE [ [ GLOBAL | LOCAL ] { TEMPORARY | TEMP } | UNLOGGED ] TABLE [ IF NOT EXI [ WITH ( {storage_parameter = value} [, ... ] ) ] [ ON COMMIT { PRESERVE ROWS | DELETE ROWS | DROP } ] [ COMPRESS | NOCOMPRESS ] -[ TABLESPACE tablespace_name ] -[ DISTRIBUTE BY { REPLICATION | { HASH ( column_name [,...] ) | - RANGE ( column_name [,...] ) range_distribution_rules | - LIST ( column_name [,...] ) list_distribution_rules } } ] -[ TO { GROUP groupname | NODE ( nodename [, ... ] ) } ]; +[ TABLESPACE tablespace_name ]; where column_constraint can be: [ CONSTRAINT constraint_name ] @@ -52,19 +48,6 @@ where like_option can be: where index_parameters can be: [ WITH ( {storage_parameter = value} [, ... ] ) ] [ USING INDEX TABLESPACE tablespace_name ] -where range_distribution_rules can be: -[ ( SLICE name VALUES LESS THAN (expression | MAXVALUE [, ... ]) [DATANODE datanode_name] - [, ... ] ) | - ( SLICE name START (expression) END (expression) EVERY (expression) [DATANODE datanode_name] - [, ... ] ) | - SLICE REFERENCES table_name -] -where list_distribution_rules can be: -[ ( SLICE name VALUES (expression [, ... ]) [DATANODE datanode_name] - [, ... ] ) | - ( SLICE name VALUES (DEFAULT) [DATANODE datanode_name] ) | - SLICE REFERENCES table_name -] diff --git a/src/bin/psql/tab-complete.cpp b/src/bin/psql/tab-complete.cpp index 4ed6b588b..efdb08e7d 100644 --- a/src/bin/psql/tab-complete.cpp +++ b/src/bin/psql/tab-complete.cpp @@ -480,6 +480,21 @@ static const SchemaQuery Query_for_list_of_matviews = { NULL }; +static const SchemaQuery Query_for_list_of_constraints_with_schema = { + /* catname */ + "pg_catalog.pg_constraint c", + /* selcondition */ + "c.conrelid <> 0", + /* viscondition */ + "true", + /* namespace */ + "c.connamespace", + /* result */ + "pg_catalog.quote_ident(c.conname)", + /* qualresult */ + NULL +}; + /* * Queries to get lists of names of various kinds of things, possibly * restricted to names matching a partially entered name. In these queries, @@ -675,6 +690,8 @@ typedef struct { static const pgsql_thing_t words_after_create[] = { {"AGGREGATE", NULL, &Query_for_list_of_aggregates, 0}, + {"APP WORKLOAD GROUP", NULL, NULL, 0}, + {"APP WORKLOAD GROUP MAPPING", NULL, NULL, 0}, #ifdef PGXC {"BARRIER", NULL, NULL, 0}, /* Comes barrier name next, so skip it */ #endif @@ -898,7 +915,7 @@ static char** PsqlCompletion(const char *text, int start, int end) "COMMENT", "COMMIT", "COPY", "CREATE", "CURSOR", "DEALLOCATE", "DECLARE", "DELETE FROM", "DISCARD", "DO", "DROP", "END", "EXECUTE", "EXPLAIN", "FETCH", "GRANT", "INSERT", "LISTEN", "LOAD", "LOCK", "MOVE", "NOTIFY", "PREPARE", - "REASSIGN", "REFRESH MATERIALIZED VIEW", "REINDEX", "RELEASE", "RESET", "REVOKE", "ROLLBACK", + "REASSIGN", "REFRESH", "REINDEX", "RELEASE", "RESET", "REVOKE", "ROLLBACK", "SAVEPOINT", "SECURITY LABEL", "SELECT", "SET", "SHOW", "START", "TABLE", "TRUNCATE", "UNLISTEN", "UPDATE", "VACUUM", "VALUES", "WITH", NULL @@ -1063,12 +1080,12 @@ static char** PsqlCompletion(const char *text, int start, int end) */ else if (pg_strcasecmp(PREV_WD, "ALTER") == 0 && pg_strcasecmp(PREV3_WD, "TABLE") != 0) { static const char* const listAlter[] = { - "AGGREGATE", "COLLATION", "CONVERSION", "DATABASE", "DEFAULT PRIVILEGES", "DOMAIN", - "EXTENSION", "FOREIGN DATA WRAPPER", "FOREIGN TABLE", "FUNCTION", - "GROUP", "INDEX", "LANGUAGE", "LARGE OBJECT", "MATERIALIZED VIEW", "OPERATOR", - "POLICY", "PROCEDURE", "ROLE", "ROW LEVEL SECURITY POLICY", "RULE", "SCHEMA", - "SERVER", "SESSION", "SEQUENCE", "SYSTEM", "TABLE", "TABLESPACE", "TEXT SEARCH", "TRIGGER", - "TYPE", "USER", "USER MAPPING FOR", "VIEW", NULL + "AGGREGATE", "APP WORKLOAD GROUP", "APP WORKLOAD GROUP MAPPING", "COLLATION", "CONVERSION", + "DATABASE", "DEFAULT PRIVILEGES", "DOMAIN", "EXTENSION", "FOREIGN DATA WRAPPER", + "FOREIGN TABLE", "FUNCTION", "GROUP", "INDEX", "LANGUAGE", "LARGE OBJECT", + "MATERIALIZED VIEW", "OPERATOR", "POLICY", "PROCEDURE", "ROLE", "ROW LEVEL SECURITY POLICY", + "RULE", "SCHEMA", "SERVER", "SESSION", "SEQUENCE", "SYSTEM", "TABLE", "TABLESPACE", + "TEXT SEARCH", "TRIGGER", "TYPE", "USER", "USER MAPPING FOR", "VIEW", NULL }; COMPLETE_WITH_LIST(listAlter); @@ -1260,11 +1277,11 @@ static char** PsqlCompletion(const char *text, int start, int end) "INDEPENDENT", "INHERIT", "LOGIN", "MONADMIN", "NOAUDITADMIN", "NOCREATEDB", "NOCREATEROLE", "NOCREATEUSER", "NODE GROUP", "NOINDEPENDENT", "NOINHERIT", "NOLOGIN", "NOMONADMIN", "NOOPRADMIN", - "NOPERSISTENCE", "NOPOLADMIN", "NOREPLICATION", "NOSUPERUSER", + "NOPERSISTENCE", "NOPOLADMIN", "NOREPLICATION", "NOSYSADMIN", "NOUSEFT", "NOVCADMIN", "OPRADMIN", "PASSWORD", "PERM SPACE", "PERSISTENCE", "PGUSER", "POLADMIN", "RENAME TO", "REPLICATION", "RESET", "RESOURCE POOL", "SET", "SPILL SPACE", - "SUPERUSER", "SYSADMIN", "TEMP SPACE", "UNENCRYPTED", "USEFT", + "SYSADMIN", "TEMP SPACE", "UNENCRYPTED", "USEFT", "USER GROUP", "VALID", "VCADMIN", "WITH", NULL }; @@ -1292,11 +1309,11 @@ static char** PsqlCompletion(const char *text, int start, int end) "INDEPENDENT", "INHERIT", "LOGIN", "MONADMIN", "NOAUDITADMIN", "NOCREATEDB", "NOCREATEROLE", "NOCREATEUSER", "NODE GROUP", "NOINDEPENDENT", "NOINHERIT", "NOLOGIN", "NOMONADMIN", "NOOPRADMIN", - "NOPERSISTENCE", "NOPOLADMIN", "NOREPLICATION", "NOSUPERUSER", + "NOPERSISTENCE", "NOPOLADMIN", "NOREPLICATION", "NOSYSADMIN", "NOUSEFT", "NOVCADMIN", "OPRADMIN", "PASSWORD", "PERM SPACE", "PERSISTENCE", "PGUSER", "POLADMIN", "RENAME TO", "REPLICATION", "RESET", "RESOURCE POOL", "SET", "SPILL SPACE", - "SUPERUSER", "SYSADMIN", "TEMP SPACE", "UNENCRYPTED", "USEFT", + "SYSADMIN", "TEMP SPACE", "UNENCRYPTED", "USEFT", "USER GROUP", "VALID", "VCADMIN", NULL }; @@ -1920,10 +1937,16 @@ static char** PsqlCompletion(const char *text, int start, int end) COMPLETE_WITH_QUERY(Query_for_list_of_available_extensions); /* CREATE EXTENSION */ else if (pg_strcasecmp(PREV3_WD, "CREATE") == 0 && pg_strcasecmp(PREV2_WD, "EXTENSION") == 0) { - static const char* const listCreateExtension[] = {"WITH SCHEMA", "VERSION", "FROM", NULL}; + static const char* const listCreateExtension[] = {"WITH", "SCHEMA", "VERSION", "FROM", NULL}; COMPLETE_WITH_LIST(listCreateExtension); } + else if (pg_strcasecmp(PREV4_WD, "CREATE") == 0 && pg_strcasecmp(PREV3_WD, "EXTENSION") == 0 && + pg_strcasecmp(PREV_WD, "WITH") == 0) { + static const char* const listCreateExtensionWith[] = {"SCHEMA", "VERSION", "FROM", NULL}; + COMPLETE_WITH_LIST(listCreateExtensionWith); + } + /* CREATE FOREIGN */ else if (pg_strcasecmp(PREV2_WD, "CREATE") == 0 && pg_strcasecmp(PREV_WD, "FOREIGN") == 0) { static const char* const listCreateForeign[] = {"DATA WRAPPER", "TABLE", NULL}; @@ -2286,10 +2309,10 @@ static char** PsqlCompletion(const char *text, int start, int end) "IN GROUP", "IN ROLE", "INDEPENDENT", "INHERIT", "LOGIN", "MONADMIN", "NOAUDITADMIN", "NOCREATEDB", "NOCREATEROLE", "NOCREATEUSER", "NODE GROUP", "NOINDEPENDENT", "NOINHERIT", "NOLOGIN", "NOMONADMIN", "NOOPRADMIN", - "NOPERSISTENCE", "NOPOLADMIN", "NOREPLICATION", "NOSUPERUSER", "NOSYSADMIN", + "NOPERSISTENCE", "NOPOLADMIN", "NOREPLICATION", "NOSYSADMIN", "NOUSEFT", "NOVCADMIN", "OPRADMIN", "PASSWORD", "PERM SPACE", "PERSISTENCE", "PGUSER", "POLADMIN", "PROFILE", "PROFILE DEFAULT", "REPLICATION", - "RESOURCE POOL", "ROLE", "SPILL SPACE", "SUPERUSER", "SYSADMIN", "SYSID", + "RESOURCE POOL", "ROLE", "SPILL SPACE", "SYSADMIN", "SYSID", "TEMP SPACE", "UNENCRYPTED", "USEFT", "USER", "USER GROUP", "VALID", "VCADMIN", "WITH", NULL }; @@ -2319,10 +2342,10 @@ static char** PsqlCompletion(const char *text, int start, int end) "IN GROUP", "IN ROLE", "INDEPENDENT", "INHERIT", "LOGIN", "MONADMIN", "NOAUDITADMIN", "NOCREATEDB", "NOCREATEROLE", "NOCREATEUSER", "NODE GROUP", "NOINDEPENDENT", "NOINHERIT", "NOLOGIN", "NOMONADMIN", "NOOPRADMIN", - "NOPERSISTENCE", "NOPOLADMIN", "NOREPLICATION", "NOSUPERUSER", "NOSYSADMIN", + "NOPERSISTENCE", "NOPOLADMIN", "NOREPLICATION", "NOSYSADMIN", "NOUSEFT", "NOVCADMIN", "OPRADMIN", "PASSWORD", "PERM SPACE", "PERSISTENCE", "PGUSER", "POLADMIN", "PROFILE", "PROFILE DEFAULT", "REPLICATION", - "RESOURCE POOL", "ROLE", "SPILL SPACE", "SUPERUSER", "SYSADMIN", "SYSID", + "RESOURCE POOL", "ROLE", "SPILL SPACE", "SYSADMIN", "SYSID", "TEMP SPACE", "UNENCRYPTED", "USEFT", "USER", "USER GROUP", "VALID", "VCADMIN", NULL }; @@ -2394,7 +2417,9 @@ static char** PsqlCompletion(const char *text, int start, int end) /* CURSOR */ else if (pg_strcasecmp(PREV2_WD, "CURSOR") == 0) { - static const char* const listDeclareCursor[] = {"BINARY", "NO SCROLL","WITH HOLD", "WITHOUT HOLD", "FOR", NULL}; + static const char* const listDeclareCursor[] = { + "BINARY", "SCROLL", "NO SCROLL","INSENSITIVE","FOR", NULL + }; COMPLETE_WITH_LIST(listDeclareCursor); } @@ -2658,7 +2683,11 @@ static char** PsqlCompletion(const char *text, int start, int end) " UNION SELECT 'LARGE OBJECT'" " UNION SELECT 'SCHEMA'" " UNION SELECT 'TABLESPACE'" - " UNION SELECT 'TYPE'"); + " UNION SELECT 'TYPE'" + " UNION SELECT 'TABLE'" + " UNION SELECT 'DIRECTORY'" + " UNION SELECT 'NODE GROUP'" + " UNION SELECT 'DATA SOURCE'"); else if ((pg_strcasecmp(PREV4_WD, "GRANT") == 0 || pg_strcasecmp(PREV4_WD, "REVOKE") == 0) && pg_strcasecmp(PREV2_WD, "ON") == 0 && pg_strcasecmp(PREV_WD, "FOREIGN") == 0) { static const char* const listPrivilegeForeign[] = {"DATA WRAPPER", "SERVER", NULL}; @@ -2683,6 +2712,8 @@ static char** PsqlCompletion(const char *text, int start, int end) COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces); else if (pg_strcasecmp(PREV_WD, "TYPE") == 0) COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_datatypes, NULL); + else if (pg_strcasecmp(PREV_WD, "DATA") == 0) + COMPLETE_WITH_CONST("SOURCE"); else if (pg_strcasecmp(PREV4_WD, "GRANT") == 0) COMPLETE_WITH_CONST("TO"); else @@ -2773,8 +2804,11 @@ static char** PsqlCompletion(const char *text, int start, int end) /* Complete LOCK [TABLE] with "IN" */ else if ((pg_strcasecmp(PREV2_WD, "LOCK") == 0 && pg_strcasecmp(PREV_WD, "TABLE") != 0) || - (pg_strcasecmp(PREV2_WD, "TABLE") == 0 && pg_strcasecmp(PREV3_WD, "LOCK") == 0)) - COMPLETE_WITH_CONST("IN"); + (pg_strcasecmp(PREV2_WD, "TABLE") == 0 && pg_strcasecmp(PREV3_WD, "LOCK") == 0)) { + static const char* const lockTableList[] = {"IN", "NOWAIT", NULL}; + + COMPLETE_WITH_LIST(lockTableList); + } /* Complete LOCK [TABLE]
IN with a lock mode */ else if (pg_strcasecmp(PREV_WD, "IN") == 0 && (pg_strcasecmp(PREV3_WD, "LOCK") == 0 || @@ -2790,6 +2824,20 @@ static char** PsqlCompletion(const char *text, int start, int end) COMPLETE_WITH_LIST(lockModes); } + else if ((pg_strcasecmp(PREV_WD, "ACCESS") == 0 || pg_strcasecmp(PREV_WD, "ROW") == 0) && + pg_strcasecmp(PREV2_WD, "IN") == 0 && (pg_strcasecmp(PREV4_WD, "LOCK") == 0 || + (pg_strcasecmp(PREV4_WD, "TABLE") == 0 && pg_strcasecmp(PREV5_WD, "LOCK") == 0))) { + static const char* const lockModesAccess[] = {"SHARE MODE", "EXCLUSIVE MODE", NULL}; + COMPLETE_WITH_LIST(lockModesAccess); + } + + else if (pg_strcasecmp(PREV_WD, "SHARE") == 0&& pg_strcasecmp(PREV2_WD, "IN") == 0 && + (pg_strcasecmp(PREV4_WD, "LOCK") == 0 || (pg_strcasecmp(PREV4_WD, "TABLE") == 0 && + pg_strcasecmp(PREV5_WD, "LOCK") == 0))) { + static const char* const lockModesAccess[] = {"UPDATE EXCLUSIVE MODE", "ROW EXCLUSIVE MODE", "MODE", NULL}; + COMPLETE_WITH_LIST(lockModesAccess); + } + /* NOTIFY */ else if (pg_strcasecmp(PREV_WD, "NOTIFY") == 0) COMPLETE_WITH_QUERY("SELECT pg_catalog.quote_ident(channel) FROM pg_catalog.pg_listening_channels() AS channel " @@ -2838,8 +2886,10 @@ static char** PsqlCompletion(const char *text, int start, int end) COMPLETE_WITH_QUERY(Query_for_list_of_roles); /* REFRESH MATERIALIZED VIEW */ - else if (pg_strcasecmp(PREV_WD, "REFRESH") == 0) - COMPLETE_WITH_CONST("MATERIALIZED VIEW"); + else if (pg_strcasecmp(PREV_WD, "REFRESH") == 0) { + static const char* const refreshObject[] = {"MATERIALIZED VIEW", "INCREMENTAL MATERIALIZED VIEW", NULL}; + COMPLETE_WITH_LIST(refreshObject); + } else if (pg_strcasecmp(PREV2_WD, "REFRESH") == 0 && pg_strcasecmp(PREV_WD, "MATERIALIZED") == 0) COMPLETE_WITH_CONST("VIEW"); else if (pg_strcasecmp(PREV3_WD, "REFRESH") == 0 && pg_strcasecmp(PREV2_WD, "MATERIALIZED") == 0 && @@ -2948,6 +2998,9 @@ static char** PsqlCompletion(const char *text, int start, int end) COMPLETE_WITH_LIST(myList); } + else if (pg_strcasecmp(PREV2_WD, "SET") == 0 && pg_strcasecmp(PREV_WD, "CONSTRAINTS") == 0) { + COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_constraints_with_schema, " UNION SELECT 'ALL'"); + } /* Complete SET CONSTRAINTS with DEFERRED|IMMEDIATE */ else if (pg_strcasecmp(PREV3_WD, "SET") == 0 && pg_strcasecmp(PREV2_WD, "CONSTRAINTS") == 0) { static const char* const constraintList[] = {"DEFERRED", "IMMEDIATE", NULL};