3
3
*
4
4
* Copyright (c) 2000-2004, PostgreSQL Global Development Group
5
5
*
6
- * $PostgreSQL: pgsql/src/bin/psql/tab-complete.c,v 1.115 2004/09/01 00:10:01 momjian Exp $
6
+ * $PostgreSQL: pgsql/src/bin/psql/tab-complete.c,v 1.116 2004/09/22 04:25:16 neilc Exp $
7
7
*/
8
8
9
9
/*----------------------------------------------------------------------
@@ -386,6 +386,15 @@ static const SchemaQuery Query_for_list_of_views = {
386
386
" and pg_catalog.quote_ident(c1.relname)='%s'"\
387
387
" and pg_catalog.pg_table_is_visible(c2.oid)"
388
388
389
+ /* the silly-looking length condition is just to eat up the current word */
390
+ #define Query_for_list_of_tables_for_trigger \
391
+ "SELECT pg_catalog.quote_ident(relname) "\
392
+ " FROM pg_catalog.pg_class"\
393
+ " WHERE (%d = length('%s'))"\
394
+ " AND oid IN "\
395
+ " (SELECT tgrelid FROM pg_catalog.pg_trigger "\
396
+ " WHERE pg_catalog.quote_ident(tgname)='%s')"
397
+
389
398
/*
390
399
* This is a list of all "things" in Pgsql, which can show up after CREATE or
391
400
* DROP; and there is also a query to get a list of them.
@@ -637,11 +646,13 @@ psql_completion(char *text, int start, int end)
637
646
else if (!prev_wd )
638
647
COMPLETE_WITH_LIST (sql_commands );
639
648
640
- /* CREATE or DROP but not ALTER TABLE sth DROP */
649
+ /* CREATE or DROP but not ALTER( TABLE|DOMAIN|GROUP) sth DROP */
641
650
/* complete with something you can create or drop */
642
651
else if (pg_strcasecmp (prev_wd ,"CREATE" )== 0 ||
643
652
(pg_strcasecmp (prev_wd ,"DROP" )== 0 &&
644
- pg_strcasecmp (prev3_wd ,"TABLE" )!= 0 ))
653
+ pg_strcasecmp (prev3_wd ,"TABLE" )!= 0 &&
654
+ pg_strcasecmp (prev3_wd ,"DOMAIN" )!= 0 &&
655
+ pg_strcasecmp (prev3_wd ,"GROUP" )!= 0 ))
645
656
matches = completion_matches (text ,create_command_generator );
646
657
647
658
/* ALTER */
@@ -694,6 +705,22 @@ psql_completion(char *text, int start, int end)
694
705
COMPLETE_WITH_LIST (list_ALTERINDEX );
695
706
}
696
707
708
+ /* ALTER LANGUAGE <name> */
709
+ else if (pg_strcasecmp (prev3_wd ,"ALTER" )== 0 &&
710
+ pg_strcasecmp (prev2_wd ,"LANGUAGE" )== 0 )
711
+ COMPLETE_WITH_CONST ("RENAME TO" );
712
+
713
+ /* ALTER USER <name> */
714
+ else if (pg_strcasecmp (prev3_wd ,"ALTER" )== 0 &&
715
+ pg_strcasecmp (prev2_wd ,"USER" )== 0 )
716
+ {
717
+ static const char * const list_ALTERUSER []=
718
+ {"ENCRYPTED" ,"UNENCRYPTED" ,"CREATEDB" ,"NOCREATEDB" ,"CREATEUSER" ,
719
+ "NOCREATEUSER" ,"VALID UNTIL" ,"RENAME TO" ,"SET" ,"RESET" ,NULL };
720
+
721
+ COMPLETE_WITH_LIST (list_ALTERUSER );
722
+ }
723
+
697
724
/* ALTER DOMAIN <name> */
698
725
else if (pg_strcasecmp (prev3_wd ,"ALTER" )== 0 &&
699
726
pg_strcasecmp (prev2_wd ,"DOMAIN" )== 0 )
@@ -709,7 +736,7 @@ psql_completion(char *text, int start, int end)
709
736
pg_strcasecmp (prev_wd ,"DROP" )== 0 )
710
737
{
711
738
static const char * const list_ALTERDOMAIN2 []=
712
- {"CONSTRAINT" ,"DEFAULT" ,"NOT NULL" ,"OWNER TO" , NULL };
739
+ {"CONSTRAINT" ,"DEFAULT" ,"NOT NULL" ,NULL };
713
740
714
741
COMPLETE_WITH_LIST (list_ALTERDOMAIN2 );
715
742
}
@@ -723,11 +750,36 @@ psql_completion(char *text, int start, int end)
723
750
724
751
COMPLETE_WITH_LIST (list_ALTERDOMAIN3 );
725
752
}
753
+ /* ALTER SEQUENCE <name> */
754
+ else if (pg_strcasecmp (prev3_wd ,"ALTER" )== 0 &&
755
+ pg_strcasecmp (prev2_wd ,"SEQUENCE" )== 0 )
756
+ {
757
+ static const char * const list_ALTERSCHEMA []=
758
+ {"INCREMENT" ,"MINVALUE" ,"MAXVALUE" ,"RESTART" ,"NO" ,"CACHE" ,"CYCLE" ,NULL };
759
+
760
+ COMPLETE_WITH_LIST (list_ALTERSCHEMA );
761
+ }
762
+ /* ALTER SEQUENCE <name> NO */
763
+ else if (pg_strcasecmp (prev4_wd ,"ALTER" )== 0 &&
764
+ pg_strcasecmp (prev3_wd ,"SEQUENCE" )== 0 &&
765
+ pg_strcasecmp (prev_wd ,"NO" )== 0 )
766
+ {
767
+ static const char * const list_ALTERSCHEMA2 []=
768
+ {"MINVALUE" ,"MAXVALUE" ,"CYCLE" ,NULL };
769
+
770
+ COMPLETE_WITH_LIST (list_ALTERSCHEMA2 );
771
+ }
726
772
/* ALTER TRIGGER <name>, add ON */
727
773
else if (pg_strcasecmp (prev3_wd ,"ALTER" )== 0 &&
728
- pg_strcasecmp (prev2_wd ,"TRIGGER" )== 0 &&
729
- pg_strcasecmp (prev_wd ,"ON" )!= 0 )
774
+ pg_strcasecmp (prev2_wd ,"TRIGGER" )== 0 )
730
775
COMPLETE_WITH_CONST ("ON" );
776
+
777
+ else if (pg_strcasecmp (prev4_wd ,"ALTER" )== 0 &&
778
+ pg_strcasecmp (prev3_wd ,"TRIGGER" )== 0 )
779
+ {
780
+ completion_info_charp = prev2_wd ;
781
+ COMPLETE_WITH_QUERY (Query_for_list_of_tables_for_trigger );
782
+ }
731
783
732
784
/*
733
785
* If we have ALTER TRIGGER <sth> ON, then add the correct tablename
@@ -737,6 +789,11 @@ psql_completion(char *text, int start, int end)
737
789
pg_strcasecmp (prev_wd ,"ON" )== 0 )
738
790
COMPLETE_WITH_SCHEMA_QUERY (Query_for_list_of_tables ,NULL );
739
791
792
+ /* ALTER TRIGGER <name> ON <name> */
793
+ else if (pg_strcasecmp (prev4_wd ,"TRIGGER" )== 0 &&
794
+ pg_strcasecmp (prev2_wd ,"ON" )== 0 )
795
+ COMPLETE_WITH_CONST ("RENAME TO" );
796
+
740
797
/*
741
798
* If we detect ALTER TABLE <name>, suggest either ADD, DROP, ALTER,
742
799
* RENAME, CLUSTER ON or OWNER
@@ -756,6 +813,11 @@ psql_completion(char *text, int start, int end)
756
813
pg_strcasecmp (prev_wd ,"RENAME" )== 0 ))
757
814
COMPLETE_WITH_ATTR (prev2_wd );
758
815
816
+ /* ALTER TABLE xxx RENAME yyy */
817
+ else if (pg_strcasecmp (prev4_wd ,"TABLE" )== 0 &&
818
+ pg_strcasecmp (prev2_wd ,"RENAME" )== 0 )
819
+ COMPLETE_WITH_CONST ("TO" );
820
+
759
821
/* If we have TABLE <sth> DROP, provide COLUMN or CONSTRAINT */
760
822
else if (pg_strcasecmp (prev3_wd ,"TABLE" )== 0 &&
761
823
pg_strcasecmp (prev_wd ,"DROP" )== 0 )
@@ -770,6 +832,19 @@ psql_completion(char *text, int start, int end)
770
832
pg_strcasecmp (prev2_wd ,"DROP" )== 0 &&
771
833
pg_strcasecmp (prev_wd ,"COLUMN" )== 0 )
772
834
COMPLETE_WITH_ATTR (prev3_wd );
835
+ /* ALTER TABLE ALTER [COLUMN] <foo> */
836
+ else if ((pg_strcasecmp (prev3_wd ,"ALTER" )== 0 &&
837
+ pg_strcasecmp (prev2_wd ,"COLUMN" )== 0 )||
838
+ (pg_strcasecmp (prev4_wd ,"TABLE" )== 0 &&
839
+ pg_strcasecmp (prev2_wd ,"ALTER" )== 0 ))
840
+ {
841
+ /* DROP ... does not work well yet */
842
+ static const char * const list_COLUMNALTER []=
843
+ {"TYPE" ,"SET DEFAULT" ,"DROP DEFAULT" ,"SET NOT NULL" ,
844
+ "DROP NOT NULL" ,"SET STATISTICS" ,"SET STORAGE" ,NULL };
845
+
846
+ COMPLETE_WITH_LIST (list_COLUMNALTER );
847
+ }
773
848
else if (pg_strcasecmp (prev3_wd ,"TABLE" )== 0 &&
774
849
pg_strcasecmp (prev_wd ,"CLUSTER" )== 0 )
775
850
COMPLETE_WITH_CONST ("ON" );
@@ -817,12 +892,12 @@ psql_completion(char *text, int start, int end)
817
892
else if (pg_strcasecmp (prev3_wd ,"ALTER" )== 0 &&
818
893
pg_strcasecmp (prev2_wd ,"TYPE" )== 0 )
819
894
COMPLETE_WITH_CONST ("OWNER TO" );
820
- /* complete ALTER GROUP <foo>with ADD or DROP */
895
+ /* complete ALTER GROUP <foo> */
821
896
else if (pg_strcasecmp (prev3_wd ,"ALTER" )== 0 &&
822
897
pg_strcasecmp (prev2_wd ,"GROUP" )== 0 )
823
898
{
824
899
static const char * const list_ALTERGROUP []=
825
- {"ADD" ,"DROP" ,NULL };
900
+ {"ADD USER " ,"DROP USER" , "RENAME TO " ,NULL };
826
901
827
902
COMPLETE_WITH_LIST (list_ALTERGROUP );
828
903
}
@@ -926,12 +1001,43 @@ psql_completion(char *text, int start, int end)
926
1001
else if (pg_strcasecmp (prev2_wd ,"COPY" )== 0 ||
927
1002
pg_strcasecmp (prev2_wd ,"\\copy" )== 0 ||
928
1003
pg_strcasecmp (prev2_wd ,"BINARY" )== 0 )
929
- {
930
- static const char * const list_FROMTO []=
931
- {"FROM" ,"TO" ,NULL };
1004
+ {
1005
+ static const char * const list_FROMTO []=
1006
+ {"FROM" ,"TO" ,NULL };
1007
+
1008
+ COMPLETE_WITH_LIST (list_FROMTO );
1009
+ }
1010
+ /* If we have COPY|BINARY <sth> FROM|TO, complete with filename */
1011
+ else if ((pg_strcasecmp (prev3_wd ,"COPY" )== 0 ||
1012
+ pg_strcasecmp (prev3_wd ,"\\copy" )== 0 ||
1013
+ pg_strcasecmp (prev3_wd ,"BINARY" )== 0 )&&
1014
+ (pg_strcasecmp (prev_wd ,"FROM" )== 0 ||
1015
+ pg_strcasecmp (prev_wd ,"TO" )== 0 ))
1016
+ matches = completion_matches (text ,filename_completion_function );
932
1017
933
- COMPLETE_WITH_LIST (list_FROMTO );
934
- }
1018
+ /* Handle COPY|BINARY <sth> FROM|TO filename */
1019
+ else if ((pg_strcasecmp (prev4_wd ,"COPY" )== 0 ||
1020
+ pg_strcasecmp (prev4_wd ,"\\copy" )== 0 ||
1021
+ pg_strcasecmp (prev4_wd ,"BINARY" )== 0 )&&
1022
+ (pg_strcasecmp (prev2_wd ,"FROM" )== 0 ||
1023
+ pg_strcasecmp (prev2_wd ,"TO" )== 0 ))
1024
+ {
1025
+ static const char * const list_COPY []=
1026
+ {"BINARY" ,"OIDS" ,"DELIMETER" ,"NULL" ,"CSV" ,NULL };
1027
+
1028
+ COMPLETE_WITH_LIST (list_COPY );
1029
+ }
1030
+
1031
+ /* Handle COPY|BINARY <sth> FROM|TO filename CSV */
1032
+ else if (pg_strcasecmp (prev_wd ,"CSV" )== 0 &&
1033
+ (pg_strcasecmp (prev3_wd ,"FROM" )== 0 ||
1034
+ pg_strcasecmp (prev3_wd ,"TO" )== 0 ))
1035
+ {
1036
+ static const char * const list_CSV []=
1037
+ {"QUOTE" ,"ESCAPE" ,"FORCE QUOTE" ,NULL };
1038
+
1039
+ COMPLETE_WITH_LIST (list_CSV );
1040
+ }
935
1041
936
1042
/* CREATE INDEX */
937
1043
/* First off we complete CREATE UNIQUE with "INDEX" */
@@ -1353,7 +1459,9 @@ psql_completion(char *text, int start, int end)
1353
1459
COMPLETE_WITH_QUERY (Query_for_list_of_users );
1354
1460
/* Complete SET <var> with "TO" */
1355
1461
else if (pg_strcasecmp (prev2_wd ,"SET" )== 0 &&
1356
- pg_strcasecmp (prev4_wd ,"UPDATE" )!= 0 )
1462
+ pg_strcasecmp (prev4_wd ,"UPDATE" )!= 0 &&
1463
+ pg_strcasecmp (prev_wd ,"TABLESPACE" )!= 0 &&
1464
+ pg_strcasecmp (prev4_wd ,"DOMAIN" )!= 0 )
1357
1465
COMPLETE_WITH_CONST ("TO" );
1358
1466
/* Suggest possible variable values */
1359
1467
else if (pg_strcasecmp (prev3_wd ,"SET" )== 0 &&
@@ -1432,7 +1540,9 @@ psql_completion(char *text, int start, int end)
1432
1540
1433
1541
/* ... FROM ... */
1434
1542
/* TODO: also include SRF ? */
1435
- else if (pg_strcasecmp (prev_wd ,"FROM" )== 0 )
1543
+ else if (pg_strcasecmp (prev_wd ,"FROM" )== 0 &&
1544
+ pg_strcasecmp (prev3_wd ,"COPY" )!= 0 &&
1545
+ pg_strcasecmp (prev3_wd ,"\\copy" )!= 0 )
1436
1546
COMPLETE_WITH_SCHEMA_QUERY (Query_for_list_of_tsv ,NULL );
1437
1547
1438
1548