Re: psql tab-completion improvements - Mailing list pgsql-patches

From Bruce Momjian
Subject Re: psql tab-completion improvements
Date
Msg-id 200409100132.i8A1WIM02993@candle.pha.pa.us
Whole thread Raw
In response to psql tab-completion improvements  ("Greg Sabino Mullane" <greg@turnstep.com>)
Responses Re: psql tab-completion improvements
Re: psql tab-completion improvements
List pgsql-patches
Is this for 8.0?  Seems it is fixes.

---------------------------------------------------------------------------

Greg Sabino Mullane wrote:
[ There is text before PGP section. ]
>
[ PGP not available, raw data follows ]
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
> NotDashEscaped: You need GnuPG to verify this message
>
>
> Some improvements for the tab-completion of psql. This should
> address all of the items in the todo list and adds some new
> things as well. Specifically:
>
> * Add support for ALTER SEQUENCE ...
> * Add "RENAME TO" for ALTER TRIGGER xx ON yy
> * Pick proper table for ALTER TRIGGER xx ON ...
> * Support for ALTER USER xxx ...
> * Fix ALTER GROUP xxx DROP ...
> * Fix ALTER DOMAIN xxx DROP ...
> * Remove "OWNER TO" from ALTER DOMAIN xx DROP ...
> * Fix ALTER DOMAIN xx SET DEFAULT ..
> * Prevent ALTER INDEX xxx SET TABLESPACE from using "TO"
> * Support for ALTER LANGUAGE xxx (RENAME TO)
> * More support for ALTER TABLE xxx ALTER COLUMN xxx ...
> * More support for COPY
>
> --
> Greg Sabino Mullane greg@turnstep.com
> PGP Key: 0x14964AC8 200408311930
>
>
>
>
> Index: tab-complete.c
> ===================================================================
> RCS file: /projects/cvsroot/pgsql-server/src/bin/psql/tab-complete.c,v
> retrieving revision 1.114
> diff -c -r1.114 tab-complete.c
> *** tab-complete.c    29 Aug 2004 05:06:54 -0000    1.114
> --- tab-complete.c    31 Aug 2004 23:25:07 -0000
> ***************
> *** 386,391 ****
> --- 386,400 ----
>   "       and pg_catalog.quote_ident(c1.relname)='%s'"\
>   "       and pg_catalog.pg_table_is_visible(c2.oid)"
>
> + /* the silly-looking length condition is just to eat up the current word */
> + #define Query_for_list_of_tables_for_trigger \
> + "SELECT pg_catalog.quote_ident(relname) "\
> + "  FROM pg_catalog.pg_class"\
> + " WHERE (%d = length('%s'))"\
> + "   AND oid IN "\
> + "       (SELECT tgrelid FROM pg_catalog.pg_trigger "\
> + "         WHERE pg_catalog.quote_ident(tgname)='%s')"
> +
>   /*
>    * This is a list of all "things" in Pgsql, which can show up after CREATE or
>    * DROP; and there is also a query to get a list of them.
> ***************
> *** 637,647 ****
>       else if (!prev_wd)
>           COMPLETE_WITH_LIST(sql_commands);
>
> ! /* CREATE or DROP but not ALTER TABLE sth DROP */
>       /* complete with something you can create or drop */
>       else if (pg_strcasecmp(prev_wd, "CREATE") == 0 ||
>                (pg_strcasecmp(prev_wd, "DROP") == 0 &&
> !               pg_strcasecmp(prev3_wd, "TABLE") != 0))
>           matches = completion_matches(text, create_command_generator);
>
>   /* ALTER */
> --- 646,658 ----
>       else if (!prev_wd)
>           COMPLETE_WITH_LIST(sql_commands);
>
> ! /* CREATE or DROP but not ALTER (TABLE|DOMAIN|GROUP) sth DROP */
>       /* complete with something you can create or drop */
>       else if (pg_strcasecmp(prev_wd, "CREATE") == 0 ||
>                (pg_strcasecmp(prev_wd, "DROP") == 0 &&
> !               pg_strcasecmp(prev3_wd, "TABLE") != 0 &&
> !               pg_strcasecmp(prev3_wd, "DOMAIN") != 0 &&
> !               pg_strcasecmp(prev3_wd, "GROUP") != 0))
>           matches = completion_matches(text, create_command_generator);
>
>   /* ALTER */
> ***************
> *** 694,699 ****
> --- 705,726 ----
>           COMPLETE_WITH_LIST(list_ALTERINDEX);
>       }
>
> +     /* ALTER LANGUAGE <name> */
> +     else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 &&
> +                      pg_strcasecmp(prev2_wd, "LANGUAGE") == 0)
> +             COMPLETE_WITH_CONST("RENAME TO");
> +
> +     /* ALTER USER <name> */
> +     else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 &&
> +              pg_strcasecmp(prev2_wd, "USER") == 0)
> +     {
> +         static const char *const list_ALTERUSER[] =
> +         {"ENCRYPTED", "UNENCRYPTED", "CREATEDB", "NOCREATEDB", "CREATEUSER",
> +          "NOCREATEUSER", "VALID UNTIL", "RENAME TO", "SET", "RESET", NULL};
> +
> +         COMPLETE_WITH_LIST(list_ALTERUSER);
> +     }
> +
>       /* ALTER DOMAIN <name> */
>       else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 &&
>                pg_strcasecmp(prev2_wd, "DOMAIN") == 0)
> ***************
> *** 709,715 ****
>                pg_strcasecmp(prev_wd, "DROP") == 0)
>       {
>           static const char *const list_ALTERDOMAIN2[] =
> !         {"CONSTRAINT", "DEFAULT", "NOT NULL", "OWNER TO", NULL};
>
>           COMPLETE_WITH_LIST(list_ALTERDOMAIN2);
>       }
> --- 736,742 ----
>                pg_strcasecmp(prev_wd, "DROP") == 0)
>       {
>           static const char *const list_ALTERDOMAIN2[] =
> !         {"CONSTRAINT", "DEFAULT", "NOT NULL", NULL};
>
>           COMPLETE_WITH_LIST(list_ALTERDOMAIN2);
>       }
> ***************
> *** 723,733 ****
>
>           COMPLETE_WITH_LIST(list_ALTERDOMAIN3);
>       }
>       /* ALTER TRIGGER <name>, add ON */
>       else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 &&
> !              pg_strcasecmp(prev2_wd, "TRIGGER") == 0 &&
> !              pg_strcasecmp(prev_wd, "ON") != 0)
> !         COMPLETE_WITH_CONST("ON");
>
>       /*
>        * If we have ALTER TRIGGER <sth> ON, then add the correct tablename
> --- 750,785 ----
>
>           COMPLETE_WITH_LIST(list_ALTERDOMAIN3);
>       }
> +     /* ALTER SEQUENCE <name> */
> +     else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 &&
> +                      pg_strcasecmp(prev2_wd, "SEQUENCE") == 0)
> +     {
> +             static const char *const list_ALTERSCHEMA[] =
> +             {"INCREMENT", "MINVALUE", "MAXVALUE", "RESTART", "NO", "CACHE", "CYCLE", NULL};
> +
> +             COMPLETE_WITH_LIST(list_ALTERSCHEMA);
> +     }
> +     /* ALTER SEQUENCE <name> NO */
> +     else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 &&
> +                      pg_strcasecmp(prev3_wd, "SEQUENCE") == 0 &&
> +                      pg_strcasecmp(prev_wd, "NO") == 0)
> +     {
> +             static const char *const list_ALTERSCHEMA2[] =
> +             {"MINVALUE", "MAXVALUE", "CYCLE", NULL};
> +
> +             COMPLETE_WITH_LIST(list_ALTERSCHEMA2);
> +     }
>       /* ALTER TRIGGER <name>, add ON */
>       else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 &&
> !                      pg_strcasecmp(prev2_wd, "TRIGGER") == 0)
> !             COMPLETE_WITH_CONST("ON");
> !
> !     else if (pg_strcasecmp(prev4_wd, "ALTER") == 0 &&
> !                      pg_strcasecmp(prev3_wd, "TRIGGER") == 0)
> !     {
> !             completion_info_charp = prev2_wd;
> !             COMPLETE_WITH_QUERY(Query_for_list_of_tables_for_trigger);
> !     }
>
>       /*
>        * If we have ALTER TRIGGER <sth> ON, then add the correct tablename
> ***************
> *** 737,742 ****
> --- 789,799 ----
>                pg_strcasecmp(prev_wd, "ON") == 0)
>           COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
>
> +     /* ALTER TRIGGER <name> ON <name> */
> +     else if (pg_strcasecmp(prev4_wd, "TRIGGER") == 0 &&
> +                      pg_strcasecmp(prev2_wd, "ON") == 0)
> +             COMPLETE_WITH_CONST("RENAME TO");
> +
>       /*
>        * If we detect ALTER TABLE <name>, suggest either ADD, DROP, ALTER,
>        * RENAME, CLUSTER ON or OWNER
> ***************
> *** 756,761 ****
> --- 813,823 ----
>                 pg_strcasecmp(prev_wd, "RENAME") == 0))
>           COMPLETE_WITH_ATTR(prev2_wd);
>
> +     /* ALTER TABLE xxx RENAME yyy */
> +     else if (pg_strcasecmp(prev4_wd, "TABLE") == 0 &&
> +                      pg_strcasecmp(prev2_wd, "RENAME") == 0)
> +         COMPLETE_WITH_CONST("TO");
> +
>       /* If we have TABLE <sth> DROP, provide COLUMN or CONSTRAINT */
>       else if (pg_strcasecmp(prev3_wd, "TABLE") == 0 &&
>                pg_strcasecmp(prev_wd, "DROP") == 0)
> ***************
> *** 770,775 ****
> --- 832,850 ----
>                pg_strcasecmp(prev2_wd, "DROP") == 0 &&
>                pg_strcasecmp(prev_wd, "COLUMN") == 0)
>           COMPLETE_WITH_ATTR(prev3_wd);
> +     /* ALTER TABLE ALTER [COLUMN] <foo> */
> +     else if ((pg_strcasecmp(prev3_wd, "ALTER") == 0 &&
> +                         pg_strcasecmp(prev2_wd, "COLUMN") == 0) ||
> +                      (pg_strcasecmp(prev4_wd, "TABLE") == 0 &&
> +                         pg_strcasecmp(prev2_wd, "ALTER") == 0))
> +     {
> +         /* DROP ... does not work well yet */
> +             static const char *const list_COLUMNALTER[] =
> +             {"TYPE", "SET DEFAULT", "DROP DEFAULT", "SET NOT NULL", "DROP NOT NULL",
> +              "SET STATISTICS", "SET STORAGE", NULL};
> +
> +             COMPLETE_WITH_LIST(list_COLUMNALTER);
> +     }
>       else if (pg_strcasecmp(prev3_wd, "TABLE") == 0 &&
>                pg_strcasecmp(prev_wd, "CLUSTER") == 0)
>           COMPLETE_WITH_CONST("ON");
> ***************
> *** 817,828 ****
>       else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 &&
>                pg_strcasecmp(prev2_wd, "TYPE") == 0)
>           COMPLETE_WITH_CONST("OWNER TO");
> !     /* complete ALTER GROUP <foo> with ADD or DROP */
>       else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 &&
>                pg_strcasecmp(prev2_wd, "GROUP") == 0)
>       {
>           static const char *const list_ALTERGROUP[] =
> !         {"ADD", "DROP", NULL};
>
>           COMPLETE_WITH_LIST(list_ALTERGROUP);
>       }
> --- 892,903 ----
>       else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 &&
>                pg_strcasecmp(prev2_wd, "TYPE") == 0)
>           COMPLETE_WITH_CONST("OWNER TO");
> !     /* complete ALTER GROUP <foo> */
>       else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 &&
>                pg_strcasecmp(prev2_wd, "GROUP") == 0)
>       {
>           static const char *const list_ALTERGROUP[] =
> !         {"ADD USER", "DROP USER", "RENAME TO", NULL};
>
>           COMPLETE_WITH_LIST(list_ALTERGROUP);
>       }
> ***************
> *** 926,937 ****
>       else if (pg_strcasecmp(prev2_wd, "COPY") == 0 ||
>                pg_strcasecmp(prev2_wd, "\\copy") == 0 ||
>                pg_strcasecmp(prev2_wd, "BINARY") == 0)
> !     {
> !         static const char *const list_FROMTO[] =
> !         {"FROM", "TO", NULL};
>
> !         COMPLETE_WITH_LIST(list_FROMTO);
> !     }
>
>   /* CREATE INDEX */
>       /* First off we complete CREATE UNIQUE with "INDEX" */
> --- 1001,1043 ----
>       else if (pg_strcasecmp(prev2_wd, "COPY") == 0 ||
>                pg_strcasecmp(prev2_wd, "\\copy") == 0 ||
>                pg_strcasecmp(prev2_wd, "BINARY") == 0)
> !         {
> !             static const char *const list_FROMTO[] =
> !             {"FROM", "TO", NULL};
> !
> !             COMPLETE_WITH_LIST(list_FROMTO);
> !         }
> !     /* If we have COPY|BINARY <sth> FROM|TO, complete with filename */
> !     else if ((pg_strcasecmp(prev3_wd, "COPY") == 0 ||
> !                         pg_strcasecmp(prev3_wd, "\\copy") == 0 ||
> !                         pg_strcasecmp(prev3_wd, "BINARY") == 0) &&
> !                      (pg_strcasecmp(prev_wd, "FROM") == 0 ||
> !                         pg_strcasecmp(prev_wd, "TO") == 0))
> !         matches = completion_matches(text, filename_completion_function);
>
> !     /* Handle COPY|BINARY <sth> FROM|TO filename */
> !     else if ((pg_strcasecmp(prev4_wd, "COPY") == 0 ||
> !                         pg_strcasecmp(prev4_wd, "\\copy") == 0 ||
> !                         pg_strcasecmp(prev4_wd, "BINARY") == 0) &&
> !                      (pg_strcasecmp(prev2_wd, "FROM") == 0 ||
> !                         pg_strcasecmp(prev2_wd, "TO") == 0))
> !         {
> !             static const char *const list_COPY[] =
> !             {"BINARY", "OIDS", "DELIMETER", "NULL", "CSV", NULL};
> !
> !             COMPLETE_WITH_LIST(list_COPY);
> !         }
> !
> !     /* Handle COPY|BINARY <sth> FROM|TO filename CSV */
> !     else if (pg_strcasecmp(prev_wd, "CSV") == 0 &&
> !                      (pg_strcasecmp(prev3_wd, "FROM") == 0 ||
> !                         pg_strcasecmp(prev3_wd, "TO") == 0))
> !         {
> !             static const char *const list_CSV[] =
> !             {"QUOTE", "ESCAPE", "FORCE QUOTE", NULL};
> !
> !             COMPLETE_WITH_LIST(list_CSV);
> !         }
>
>   /* CREATE INDEX */
>       /* First off we complete CREATE UNIQUE with "INDEX" */
> ***************
> *** 1353,1359 ****
>           COMPLETE_WITH_QUERY(Query_for_list_of_users);
>       /* Complete SET <var> with "TO" */
>       else if (pg_strcasecmp(prev2_wd, "SET") == 0 &&
> !              pg_strcasecmp(prev4_wd, "UPDATE") != 0)
>           COMPLETE_WITH_CONST("TO");
>       /* Suggest possible variable values */
>       else if (pg_strcasecmp(prev3_wd, "SET") == 0 &&
> --- 1459,1467 ----
>           COMPLETE_WITH_QUERY(Query_for_list_of_users);
>       /* Complete SET <var> with "TO" */
>       else if (pg_strcasecmp(prev2_wd, "SET") == 0 &&
> !                      pg_strcasecmp(prev4_wd, "UPDATE") != 0 &&
> !                      pg_strcasecmp(prev_wd, "TABLESPACE") != 0 &&
> !                      pg_strcasecmp(prev4_wd, "DOMAIN") != 0)
>           COMPLETE_WITH_CONST("TO");
>       /* Suggest possible variable values */
>       else if (pg_strcasecmp(prev3_wd, "SET") == 0 &&
> ***************
> *** 1432,1438 ****
>
>   /* ... FROM ... */
>   /* TODO: also include SRF ? */
> !     else if (pg_strcasecmp(prev_wd, "FROM") == 0)
>           COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsv, NULL);
>
>
> --- 1540,1548 ----
>
>   /* ... FROM ... */
>   /* TODO: also include SRF ? */
> !     else if (pg_strcasecmp(prev_wd, "FROM") == 0 &&
> !                      pg_strcasecmp(prev3_wd, "COPY") != 0 &&
> !                      pg_strcasecmp(prev3_wd, "\\copy") != 0)
>           COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsv, NULL);
>
>
>
>
> -----BEGIN PGP SIGNATURE-----
>
> iD8DBQFBNQrPvJuQZxSWSsgRAqU2AKDEoTixdsiLcpZOKpY4Na1UNZmmSgCcDsxQ
> 7gyOrB6e2Pvtt5KrecRVULA=
> =/xhb
> -----END PGP SIGNATURE-----
>
>
>
> ---------------------------(end of broadcast)---------------------------
> TIP 6: Have you searched our list archives?
>
>                http://archives.postgresql.org
>
[ Decrypting message... End of raw data. ]

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073

pgsql-patches by date:

Previous
From: "Laurent Ballester"
Date:
Subject: contrib/dbase
Next
From: "Greg Sabino Mullane"
Date:
Subject: Re: psql tab-completion improvements