]> granicus.if.org Git - postgresql/blob - src/backend/tcop/utility.c
Now that names are null terminated, no need to do all that NAMEDATALEN stuff.
[postgresql] / src / backend / tcop / utility.c
1 /*-------------------------------------------------------------------------
2  *
3  * utility.c--
4  *    Contains functions which control the execution of the POSTGRES utility
5  *    commands.  At one time acted as an interface between the Lisp and C
6  *    systems.
7  *
8  * Copyright (c) 1994, Regents of the University of California
9  *
10  *
11  * IDENTIFICATION
12  *    $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.20 1997/08/18 20:53:35 momjian Exp $
13  *
14  *-------------------------------------------------------------------------
15  */
16 #include "postgres.h"
17 #include "parser/dbcommands.h"
18 #include "access/xact.h"
19 #include "access/heapam.h"
20 #include "catalog/catalog.h"
21 #include "catalog/pg_type.h"
22
23 #include "commands/async.h"
24 #include "commands/cluster.h"
25 #include "commands/command.h"
26 #include "commands/copy.h"
27 #include "commands/creatinh.h"
28 #include "commands/sequence.h"
29 #include "commands/defrem.h"
30 #include "commands/purge.h"
31 #include "commands/rename.h"
32 #include "commands/view.h"
33 #include "commands/version.h"
34 #include "commands/vacuum.h"
35 #include "commands/recipe.h"
36 #include "commands/explain.h"
37
38 #include "nodes/parsenodes.h"
39 #include "../backend/parser/parse.h"
40 #include "utils/builtins.h"
41 #include "utils/acl.h"
42 #include "utils/palloc.h"
43 #include "rewrite/rewriteRemove.h"
44 #include "rewrite/rewriteDefine.h"
45 #include "tcop/tcopdebug.h"
46 #include "tcop/dest.h"
47 #include "tcop/variable.h"
48 #include "tcop/utility.h"
49 #include "fmgr.h"       /* For load_file() */
50 #include "storage/fd.h"
51
52 #ifndef NO_SECURITY
53 #include "miscadmin.h"
54 #include "utils/acl.h"
55 #include "utils/syscache.h"
56 #endif
57
58
59 /* ----------------
60  *      CHECK_IF_ABORTED() is used to avoid doing unnecessary
61  *      processing within an aborted transaction block.
62  * ----------------
63  */
64 #define CHECK_IF_ABORTED() \
65     if (IsAbortedTransactionBlockState()) { \
66         elog(NOTICE, "(transaction aborted): %s", \
67              "queries ignored until END"); \
68         commandTag = "*ABORT STATE*"; \
69         break; \
70     } \
71     
72 /* ----------------
73  *      general utility function invoker
74  * ----------------
75  */
76 void
77 ProcessUtility(Node *parsetree,
78                CommandDest dest)
79 {
80     char *commandTag = NULL;
81     char *relname;
82     char *relationName;
83     char *userName;
84     
85     userName = GetPgUserName();
86     
87     switch (nodeTag(parsetree)) {
88         /* ********************************
89          *      transactions
90          * ********************************
91          */
92     case T_TransactionStmt:
93         {
94             TransactionStmt *stmt = (TransactionStmt *)parsetree;
95             switch (stmt->command) {
96             case BEGIN_TRANS:
97                 commandTag = "BEGIN";
98                 CHECK_IF_ABORTED();
99                 BeginTransactionBlock();
100                 break;
101                 
102             case END_TRANS:
103                 commandTag = "END";
104                 EndTransactionBlock();
105                 break;
106                 
107             case ABORT_TRANS:
108                 commandTag = "ABORT";
109                 UserAbortTransactionBlock();
110                 break;
111             }
112         }
113         break;
114       
115         /* ********************************
116          *      portal manipulation
117          * ********************************
118          */
119     case T_ClosePortalStmt:
120         {
121             ClosePortalStmt *stmt = (ClosePortalStmt *)parsetree;
122
123             commandTag = "CLOSE";
124             CHECK_IF_ABORTED();
125         
126             PerformPortalClose(stmt->portalname, dest);
127         }
128         break;
129       
130     case T_FetchStmt:
131         {
132             FetchStmt *stmt = (FetchStmt *)parsetree;
133             char *portalName = stmt->portalname;
134             bool forward;
135             int count;
136
137             commandTag = "FETCH";
138             CHECK_IF_ABORTED();
139
140             forward = (bool)(stmt->direction == FORWARD);
141
142             /* parser ensures that count is >= 0 and 
143                'fetch ALL' -> 0 */
144                
145             count = stmt->howMany;
146             PerformPortalFetch(portalName, forward, count, commandTag, dest);
147         }
148         break;
149       
150         /* ********************************
151          *      relation and attribute manipulation
152          * ********************************
153          */
154     case T_CreateStmt:
155         commandTag = "CREATE";
156         CHECK_IF_ABORTED();
157       
158         DefineRelation((CreateStmt *)parsetree);
159         break;
160       
161     case T_DestroyStmt:
162         {
163             DestroyStmt *stmt = (DestroyStmt *)parsetree;
164             List *arg;
165             List *args = stmt->relNames;
166             Relation rel;
167
168             commandTag = "DROP";
169             CHECK_IF_ABORTED();
170
171             foreach (arg, args) {
172                 relname = strVal(lfirst(arg));
173                 if (IsSystemRelationName(relname))
174                     elog(WARN, "class \"%s\" is a system catalog",
175                          relname);
176                 rel = heap_openr (relname);
177                 if ( RelationIsValid (rel) )
178                 {
179                     if ( stmt->sequence && 
180                                 rel->rd_rel->relkind != RELKIND_SEQUENCE )
181                         elog (WARN, "Use DROP TABLE to drop table '%s'",
182                                 relname);
183                     if ( !(stmt->sequence) && 
184                                 rel->rd_rel->relkind == RELKIND_SEQUENCE )
185                         elog (WARN, "Use DROP SEQUENCE to drop sequence '%s'",
186                                 relname);
187                     heap_close (rel);
188                 }
189 #ifndef NO_SECURITY
190                 if (!pg_ownercheck(userName, relname, RELNAME))
191                     elog(WARN, "you do not own class \"%s\"",
192                          relname);
193 #endif
194             }
195             foreach (arg, args) {
196                 relname = strVal(lfirst(arg));
197                 RemoveRelation(relname);
198             }
199         }
200         break;
201       
202     case T_PurgeStmt:
203         {
204             PurgeStmt *stmt = (PurgeStmt *)parsetree;
205
206             commandTag = "PURGE";
207             CHECK_IF_ABORTED();
208             
209             RelationPurge(stmt->relname,
210                           stmt->beforeDate, /* absolute time string */
211                           stmt->afterDate); /* relative time string */
212         }
213         break;
214       
215     case T_CopyStmt:
216         {
217             CopyStmt *stmt = (CopyStmt *)parsetree;
218
219             commandTag = "COPY";
220             CHECK_IF_ABORTED();
221             
222             DoCopy(stmt->relname, 
223                    stmt->binary, 
224                    stmt->oids, 
225                    (bool)(stmt->direction == FROM), 
226                    (bool)(stmt->filename == NULL), 
227                       /* null filename means copy to/from stdout/stdin,
228                          rather than to/from a file.
229                          */
230                    stmt->filename, 
231                    stmt->delimiter);
232         }
233         break;
234       
235     case T_AddAttrStmt:
236         {
237             AddAttrStmt *stmt = (AddAttrStmt *)parsetree;
238
239             commandTag = "ADD";
240             CHECK_IF_ABORTED();
241         
242             /* owner checking done in PerformAddAttribute (now recursive) */
243             PerformAddAttribute(stmt->relname,
244                                 userName,
245                                 stmt->inh,
246                                 stmt->colDef);
247         }
248         break;
249       
250         /*
251          * schema
252          */
253     case T_RenameStmt:
254         {
255             RenameStmt *stmt = (RenameStmt *)parsetree;
256
257             commandTag = "RENAME";
258             CHECK_IF_ABORTED();
259         
260             relname = stmt->relname;
261             if (IsSystemRelationName(relname))
262                 elog(WARN, "class \"%s\" is a system catalog",
263                      relname);
264 #ifndef NO_SECURITY
265             if (!pg_ownercheck(userName, relname, RELNAME))
266                 elog(WARN, "you do not own class \"%s\"",
267                      relname);
268 #endif
269             
270             /* ----------------
271              *  XXX using len == 3 to tell the difference
272              *      between "rename rel to newrel" and
273              *      "rename att in rel to newatt" will not
274              *      work soon because "rename type/operator/rule"
275              *      stuff is being added. - cim 10/24/90
276              * ----------------
277              * [another piece of amuzing but useless anecdote -- ay]
278              */
279             if (stmt->column == NULL) {
280                 /* ----------------
281                  *      rename relation
282                  *
283                  *      Note: we also rename the "type" tuple
284                  *      corresponding to the relation.
285                  * ----------------
286                  */
287                 renamerel(relname, /* old name */
288                           stmt->newname); /* new name */
289                 TypeRename(relname, /* old name */
290                            stmt->newname); /* new name */
291             } else {
292                 /* ----------------
293                  *      rename attribute
294                  * ----------------
295                  */
296                 renameatt(relname, /* relname */
297                           stmt->column, /* old att name */
298                           stmt->newname, /* new att name */
299                           userName,
300                           stmt->inh); /* recursive? */
301             }
302         }
303         break;
304       
305     case T_ChangeACLStmt:
306         {
307             ChangeACLStmt *stmt = (ChangeACLStmt *)parsetree;
308             List *i;
309             AclItem *aip;
310             unsigned modechg;
311
312             commandTag = "CHANGE";
313             CHECK_IF_ABORTED();
314             
315             aip = stmt->aclitem;
316             modechg = stmt->modechg;
317 #ifndef NO_SECURITY
318             foreach (i, stmt->relNames) {
319                 relname = strVal(lfirst(i));
320                 if (!pg_ownercheck(userName, relname, RELNAME))
321                     elog(WARN, "you do not own class \"%s\"",
322                          relname);
323             }
324 #endif
325             foreach (i, stmt->relNames) {
326                 relname = strVal(lfirst(i));
327                 ChangeAcl(relname, aip, modechg);
328             }
329
330         }
331         break;
332       
333         /* ********************************
334          *      object creation / destruction
335          * ********************************
336          */
337     case T_DefineStmt:
338         {
339             DefineStmt *stmt = (DefineStmt *)parsetree;
340
341             commandTag = "CREATE";
342             CHECK_IF_ABORTED();
343
344             switch(stmt->defType) {
345             case OPERATOR:
346                 DefineOperator(stmt->defname, /* operator name */
347                                stmt->definition); /* rest */
348                 break;
349             case P_TYPE:
350                 {
351                     DefineType (stmt->defname, stmt->definition);
352                 }
353                 break;
354             case AGGREGATE:
355                 DefineAggregate(stmt->defname, /*aggregate name */
356                                 stmt->definition); /* rest */
357                 break;
358             }
359         }
360         break;
361       
362     case T_ViewStmt:            /* CREATE VIEW */
363         {
364             ViewStmt *stmt = (ViewStmt *)parsetree;
365
366             commandTag = "CREATE";
367             CHECK_IF_ABORTED();
368             DefineView (stmt->viewname, stmt->query); /* retrieve parsetree */
369         }
370         break;
371       
372     case T_ProcedureStmt:       /* CREATE FUNCTION */
373         commandTag = "CREATE";
374         CHECK_IF_ABORTED();
375         CreateFunction((ProcedureStmt *)parsetree, dest); /* everything */
376         break;
377       
378     case T_IndexStmt:           /* CREATE INDEX */
379         {
380             IndexStmt *stmt = (IndexStmt *)parsetree;
381
382             commandTag = "CREATE";
383             CHECK_IF_ABORTED();
384             /* XXX no support for ARCHIVE indices, yet */
385             DefineIndex(stmt->relname, /* relation name */
386                         stmt->idxname, /* index name */
387                         stmt->accessMethod, /* am name */
388                         stmt->indexParams, /* parameters */
389                         stmt->withClause,
390                         stmt->unique,
391                         (Expr*)stmt->whereClause,
392                         stmt->rangetable);
393         }
394         break;
395       
396     case T_RuleStmt:            /* CREATE RULE */
397         {
398             RuleStmt *stmt = (RuleStmt *)parsetree;
399             int aclcheck_result;
400
401 #ifndef NO_SECURITY
402             relname = stmt->object->relname;
403             aclcheck_result = pg_aclcheck(relname, userName, ACL_RU);
404             if(aclcheck_result != ACLCHECK_OK)
405                 elog(WARN, "%s: %s", relname, aclcheck_error_strings[aclcheck_result]); 
406 #endif
407             commandTag = "CREATE";
408             CHECK_IF_ABORTED();
409             DefineQueryRewrite(stmt);
410         }
411         break;
412
413     case T_CreateSeqStmt:
414         commandTag = "CREATE";
415         CHECK_IF_ABORTED();
416       
417         DefineSequence((CreateSeqStmt *)parsetree);
418         break;
419       
420     case T_ExtendStmt:
421         {
422             ExtendStmt *stmt = (ExtendStmt *)parsetree;
423
424             commandTag = "EXTEND";
425             CHECK_IF_ABORTED();
426         
427             ExtendIndex(stmt->idxname, /* index name */
428                         (Expr*)stmt->whereClause, /* where */
429                         stmt->rangetable);
430         }
431         break;
432       
433     case T_RemoveStmt:
434         {
435             RemoveStmt *stmt = (RemoveStmt *)parsetree;
436
437             commandTag = "DROP";
438             CHECK_IF_ABORTED();
439         
440             switch(stmt->removeType) {
441             case INDEX:
442                 relname = stmt->name;
443                 if (IsSystemRelationName(relname))
444                     elog(WARN, "class \"%s\" is a system catalog index",
445                          relname);
446 #ifndef NO_SECURITY
447                 if (!pg_ownercheck(userName, relname, RELNAME))
448                     elog(WARN, "%s: %s", relname, aclcheck_error_strings[ACLCHECK_NOT_OWNER]);
449 #endif
450                 RemoveIndex(relname);
451                 break;
452             case RULE:
453                 {
454                     char *rulename = stmt->name;
455                     int aclcheck_result;
456 #ifndef NO_SECURITY
457                 
458                     relationName = RewriteGetRuleEventRel(rulename);
459                     aclcheck_result = pg_aclcheck(relationName, userName, ACL_RU);
460                     if(aclcheck_result != ACLCHECK_OK) {
461                         elog(WARN, "%s: %s", relationName, aclcheck_error_strings[aclcheck_result]);
462                     }
463 #endif
464                     RemoveRewriteRule(rulename);
465                 }
466                 break;
467             case P_TYPE:
468 #ifndef NO_SECURITY
469                 /* XXX moved to remove.c */
470 #endif
471                 RemoveType(stmt->name);
472                 break;
473             case VIEW:
474                 {
475                     char *viewName = stmt->name;
476                     char *ruleName;
477
478 #ifndef NO_SECURITY
479                 
480                     ruleName = MakeRetrieveViewRuleName(viewName);
481                     relationName = RewriteGetRuleEventRel(ruleName);
482                     if (!pg_ownercheck(userName, relationName, RELNAME))
483                         elog(WARN, "%s: %s", relationName, aclcheck_error_strings[ACLCHECK_NOT_OWNER]);
484                     pfree(ruleName);
485 #endif
486                     RemoveView(viewName);
487                 }
488                 break;
489             }
490             break;
491         }
492         break;
493
494     case T_RemoveAggrStmt:
495         {
496             RemoveAggrStmt *stmt = (RemoveAggrStmt *)parsetree;
497             commandTag = "DROP";
498             CHECK_IF_ABORTED();
499             RemoveAggregate(stmt->aggname, stmt->aggtype);
500         }
501         break;
502       
503     case T_RemoveFuncStmt:
504         {
505             RemoveFuncStmt *stmt = (RemoveFuncStmt *)parsetree;
506             commandTag = "DROP";
507             CHECK_IF_ABORTED();
508             RemoveFunction(stmt->funcname,
509                            length(stmt->args),
510                            stmt->args);
511         }
512         break;
513       
514     case T_RemoveOperStmt:
515         {
516             RemoveOperStmt *stmt = (RemoveOperStmt *)parsetree;
517             char* type1 = (char*) NULL; 
518             char *type2 = (char*) NULL;
519                 
520             commandTag = "DROP";
521             CHECK_IF_ABORTED();
522
523             if (lfirst(stmt->args)!=NULL)
524                 type1 = strVal(lfirst(stmt->args));
525             if (lsecond(stmt->args)!=NULL)
526                 type2 = strVal(lsecond(stmt->args));
527             RemoveOperator(stmt->opname, type1, type2);
528         }
529         break;
530       
531     case T_VersionStmt:
532         {
533             elog(WARN, "CREATE VERSION is not currently implemented");
534         }
535         break;
536       
537     case T_CreatedbStmt:
538         {
539             CreatedbStmt *stmt = (CreatedbStmt *)parsetree;
540
541             commandTag = "CREATEDB";
542             CHECK_IF_ABORTED();
543             createdb(stmt->dbname);
544         }
545         break;
546       
547     case T_DestroydbStmt:
548         {
549             DestroydbStmt *stmt = (DestroydbStmt *)parsetree;
550
551             commandTag = "DESTROYDB";
552             CHECK_IF_ABORTED();
553             destroydb(stmt->dbname);
554         }
555         break;
556       
557         /* Query-level asynchronous notification */
558     case T_NotifyStmt:
559         {
560             NotifyStmt *stmt = (NotifyStmt *)parsetree;
561
562             commandTag = "NOTIFY";
563             CHECK_IF_ABORTED();
564
565             Async_Notify(stmt->relname);
566         }
567         break;
568       
569     case T_ListenStmt:
570         {
571             ListenStmt *stmt = (ListenStmt *)parsetree;
572
573             commandTag = "LISTEN";
574             CHECK_IF_ABORTED();
575
576             Async_Listen(stmt->relname,MasterPid);
577         }
578         break;
579       
580         /* ********************************
581          *      dynamic loader
582          * ********************************
583          */
584     case T_LoadStmt:
585         {
586             LoadStmt *stmt = (LoadStmt *)parsetree;
587             FILE *fp;
588             char *filename;
589
590             commandTag = "LOAD";
591             CHECK_IF_ABORTED();
592
593             filename = stmt->filename;
594             closeAllVfds();
595             if ((fp = AllocateFile(filename, "r")) == NULL)
596                 elog(WARN, "LOAD: could not open file %s", filename);
597             FreeFile(fp);
598             load_file(filename);
599         }
600         break;
601
602     case T_ClusterStmt:
603         {
604             ClusterStmt *stmt = (ClusterStmt *)parsetree;
605
606             commandTag = "CLUSTER";
607             CHECK_IF_ABORTED();
608
609             cluster(stmt->relname, stmt->indexname);
610         }
611         break;
612         
613     case T_VacuumStmt:
614         commandTag = "VACUUM";
615         CHECK_IF_ABORTED();
616         vacuum( ((VacuumStmt *) parsetree)->vacrel,
617                 ((VacuumStmt *) parsetree)->verbose,
618                 ((VacuumStmt *) parsetree)->analyze,
619                 ((VacuumStmt *) parsetree)->va_spec);
620         break;
621
622     case T_ExplainStmt:
623         {
624             ExplainStmt *stmt = (ExplainStmt *)parsetree;
625
626             commandTag = "EXPLAIN";
627             CHECK_IF_ABORTED();
628
629             ExplainQuery(stmt->query, stmt->verbose, dest);
630         }
631         break;
632         
633         /* ********************************
634            Tioga-related statements
635            *********************************/
636     case T_RecipeStmt:
637         {
638             RecipeStmt* stmt = (RecipeStmt*)parsetree;
639             commandTag="EXECUTE RECIPE";
640             CHECK_IF_ABORTED();
641             beginRecipe(stmt);
642         }
643         break;
644
645         /* ********************************
646          * set variable statements
647          *********************************/
648     case T_VariableSetStmt:
649         {
650             VariableSetStmt *n = (VariableSetStmt *) parsetree;
651             SetPGVariable(n->name, n->value);
652             commandTag = "SET VARIABLE";
653         }
654         break;
655       
656     case T_VariableShowStmt:
657         {
658             VariableShowStmt *n = (VariableShowStmt *) parsetree;
659             GetPGVariable(n->name);
660             commandTag = "SHOW VARIABLE";
661         }
662         break;
663       
664     case T_VariableResetStmt:
665         {
666             VariableResetStmt *n = (VariableResetStmt *) parsetree;
667             ResetPGVariable(n->name);
668             commandTag = "RESET VARIABLE";
669         }
670         break;
671       
672         /* ********************************
673          *      default
674          * ********************************
675          */
676     default:
677         elog(WARN, "ProcessUtility: command #%d unsupported",
678              nodeTag(parsetree));
679         break;
680     }
681     
682     /* ----------------
683      *  tell fe/be or whatever that we're done.
684      * ----------------
685      */
686     EndCommand(commandTag, dest);
687 }
688