diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c new file mode 100644 index 8eb9f83..6e42f1e *** a/src/bin/psql/tab-complete.c --- b/src/bin/psql/tab-complete.c *************** static const SchemaQuery Query_for_list_ *** 371,376 **** --- 371,381 ---- /* The bit masks for the following three functions come from * src/include/catalog/pg_trigger.h. + * + * If the server version is 9.3 or higher, we use the function + * pg_relation_is_updatable() to test foreign tables and views. + * This returns a bit mask based on the CmdType enumeration in + * src/include/nodes/nodes.h. */ static const SchemaQuery Query_for_list_of_insertables = { /* catname */ *************** static const SchemaQuery Query_for_list_ *** 387,392 **** --- 392,412 ---- /* qualresult */ NULL }; + static const SchemaQuery Query_for_list_of_insertables_93 = { + /* catname */ + "pg_catalog.pg_class c", + /* selcondition */ + "(c.relkind = 'r' OR " + "(c.relkind IN ('f', 'v') AND (pg_catalog.pg_relation_is_updatable(c.oid, true) & (1 << 3) <> 0)))", + /* viscondition */ + "pg_catalog.pg_table_is_visible(c.oid)", + /* namespace */ + "c.relnamespace", + /* result */ + "pg_catalog.quote_ident(c.relname)", + /* qualresult */ + NULL + }; static const SchemaQuery Query_for_list_of_deletables = { /* catname */ *************** static const SchemaQuery Query_for_list_ *** 403,408 **** --- 423,443 ---- /* qualresult */ NULL }; + static const SchemaQuery Query_for_list_of_deletables_93 = { + /* catname */ + "pg_catalog.pg_class c", + /* selcondition */ + "(c.relkind = 'r' OR " + "(c.relkind IN ('f', 'v') AND (pg_catalog.pg_relation_is_updatable(c.oid, true) & (1 << 4) <> 0)))", + /* viscondition */ + "pg_catalog.pg_table_is_visible(c.oid)", + /* namespace */ + "c.relnamespace", + /* result */ + "pg_catalog.quote_ident(c.relname)", + /* qualresult */ + NULL + }; static const SchemaQuery Query_for_list_of_updatables = { /* catname */ *************** static const SchemaQuery Query_for_list_ *** 419,424 **** --- 454,474 ---- /* qualresult */ NULL }; + static const SchemaQuery Query_for_list_of_updatables_93 = { + /* catname */ + "pg_catalog.pg_class c", + /* selcondition */ + "(c.relkind = 'r' OR " + "(c.relkind IN ('f', 'v') AND (pg_catalog.pg_relation_is_updatable(c.oid, true) & (1 << 2) <> 0)))", + /* viscondition */ + "pg_catalog.pg_table_is_visible(c.oid)", + /* namespace */ + "c.relnamespace", + /* result */ + "pg_catalog.quote_ident(c.relname)", + /* qualresult */ + NULL + }; static const SchemaQuery Query_for_list_of_relations = { /* catname */ *************** psql_completion(char *text, int start, i *** 2362,2368 **** /* Complete DELETE FROM with a list of tables */ else if (pg_strcasecmp(prev2_wd, "DELETE") == 0 && pg_strcasecmp(prev_wd, "FROM") == 0) ! COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_deletables, NULL); /* Complete DELETE FROM */ else if (pg_strcasecmp(prev3_wd, "DELETE") == 0 && pg_strcasecmp(prev2_wd, "FROM") == 0) --- 2412,2423 ---- /* Complete DELETE FROM with a list of tables */ else if (pg_strcasecmp(prev2_wd, "DELETE") == 0 && pg_strcasecmp(prev_wd, "FROM") == 0) ! { ! if (pset.sversion >= 90300) ! COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_deletables_93, NULL); ! else ! COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_deletables, NULL); ! } /* Complete DELETE FROM
*/ else if (pg_strcasecmp(prev3_wd, "DELETE") == 0 && pg_strcasecmp(prev2_wd, "FROM") == 0) *************** psql_completion(char *text, int start, i *** 2732,2738 **** /* Complete INSERT INTO with table names */ else if (pg_strcasecmp(prev2_wd, "INSERT") == 0 && pg_strcasecmp(prev_wd, "INTO") == 0) ! COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_insertables, NULL); /* Complete "INSERT INTO
(" with attribute names */ else if (pg_strcasecmp(prev4_wd, "INSERT") == 0 && pg_strcasecmp(prev3_wd, "INTO") == 0 && --- 2787,2798 ---- /* Complete INSERT INTO with table names */ else if (pg_strcasecmp(prev2_wd, "INSERT") == 0 && pg_strcasecmp(prev_wd, "INTO") == 0) ! { ! if (pset.sversion >= 90300) ! COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_insertables_93, NULL); ! else ! COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_insertables, NULL); ! } /* Complete "INSERT INTO
(" with attribute names */ else if (pg_strcasecmp(prev4_wd, "INSERT") == 0 && pg_strcasecmp(prev3_wd, "INTO") == 0 && *************** psql_completion(char *text, int start, i *** 3133,3139 **** /* UPDATE */ /* If prev. word is UPDATE suggest a list of tables */ else if (pg_strcasecmp(prev_wd, "UPDATE") == 0) ! COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables, NULL); /* Complete UPDATE
with "SET" */ else if (pg_strcasecmp(prev2_wd, "UPDATE") == 0) COMPLETE_WITH_CONST("SET"); --- 3193,3204 ---- /* UPDATE */ /* If prev. word is UPDATE suggest a list of tables */ else if (pg_strcasecmp(prev_wd, "UPDATE") == 0) ! { ! if (pset.sversion >= 90300) ! COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables_93, NULL); ! else ! COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_updatables, NULL); ! } /* Complete UPDATE
with "SET" */ else if (pg_strcasecmp(prev2_wd, "UPDATE") == 0) COMPLETE_WITH_CONST("SET");