postgresql/src/backend/tcop/utility.c

2562 lines
54 KiB
C
Raw Normal View History

/*-------------------------------------------------------------------------
*
* utility.c
* Contains functions which control the execution of the POSTGRES utility
* commands. At one time acted as an interface between the Lisp and C
* systems.
*
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.286 2007/09/03 18:46:30 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
1999-07-16 07:00:38 +02:00
#include "access/twophase.h"
#include "access/xact.h"
#include "catalog/catalog.h"
#include "catalog/namespace.h"
#include "catalog/toasting.h"
2003-06-27 16:45:32 +02:00
#include "commands/alter.h"
#include "commands/async.h"
#include "commands/cluster.h"
#include "commands/comment.h"
#include "commands/conversioncmds.h"
#include "commands/copy.h"
#include "commands/dbcommands.h"
#include "commands/defrem.h"
#include "commands/discard.h"
#include "commands/explain.h"
#include "commands/lockcmds.h"
#include "commands/portalcmds.h"
#include "commands/prepare.h"
#include "commands/proclang.h"
#include "commands/schemacmds.h"
1999-07-16 07:00:38 +02:00
#include "commands/sequence.h"
#include "commands/tablecmds.h"
#include "commands/tablespace.h"
1999-07-16 07:00:38 +02:00
#include "commands/trigger.h"
2002-12-06 06:00:34 +01:00
#include "commands/typecmds.h"
#include "commands/user.h"
1999-07-16 07:00:38 +02:00
#include "commands/vacuum.h"
#include "commands/view.h"
#include "miscadmin.h"
#include "parser/parse_utilcmd.h"
#include "postmaster/bgwriter.h"
#include "rewrite/rewriteDefine.h"
1999-07-16 07:00:38 +02:00
#include "rewrite/rewriteRemove.h"
#include "storage/fd.h"
#include "tcop/pquery.h"
1996-11-11 05:54:54 +01:00
#include "tcop/utility.h"
#include "utils/acl.h"
#include "utils/guc.h"
#include "utils/syscache.h"
/*
* Error-checking support for DROP commands
*/
struct msgstrings
2001-03-22 05:01:46 +01:00
{
char kind;
int nonexistent_code;
const char *nonexistent_msg;
const char *skipping_msg;
const char *nota_msg;
const char *drophint_msg;
};
static const struct msgstrings msgstringarray[] = {
2003-08-04 02:43:34 +02:00
{RELKIND_RELATION,
ERRCODE_UNDEFINED_TABLE,
gettext_noop("table \"%s\" does not exist"),
gettext_noop("table \"%s\" does not exist, skipping"),
2003-08-04 02:43:34 +02:00
gettext_noop("\"%s\" is not a table"),
gettext_noop("Use DROP TABLE to remove a table.")},
{RELKIND_SEQUENCE,
ERRCODE_UNDEFINED_TABLE,
gettext_noop("sequence \"%s\" does not exist"),
gettext_noop("sequence \"%s\" does not exist, skipping"),
2003-08-04 02:43:34 +02:00
gettext_noop("\"%s\" is not a sequence"),
gettext_noop("Use DROP SEQUENCE to remove a sequence.")},
{RELKIND_VIEW,
ERRCODE_UNDEFINED_TABLE,
gettext_noop("view \"%s\" does not exist"),
gettext_noop("view \"%s\" does not exist, skipping"),
2003-08-04 02:43:34 +02:00
gettext_noop("\"%s\" is not a view"),
gettext_noop("Use DROP VIEW to remove a view.")},
{RELKIND_INDEX,
ERRCODE_UNDEFINED_OBJECT,
gettext_noop("index \"%s\" does not exist"),
gettext_noop("index \"%s\" does not exist, skipping"),
2003-08-04 02:43:34 +02:00
gettext_noop("\"%s\" is not an index"),
gettext_noop("Use DROP INDEX to remove an index.")},
{RELKIND_COMPOSITE_TYPE,
ERRCODE_UNDEFINED_OBJECT,
gettext_noop("type \"%s\" does not exist"),
gettext_noop("type \"%s\" does not exist, skipping"),
2003-08-04 02:43:34 +02:00
gettext_noop("\"%s\" is not a type"),
gettext_noop("Use DROP TYPE to remove a type.")},
{'\0', 0, NULL, NULL, NULL}
};
/*
* Emit the right error message for a "DROP" command issued on a
* relation of the wrong type
*/
static void
DropErrorMsgWrongType(char *relname, char wrongkind, char rightkind)
{
const struct msgstrings *rentry;
const struct msgstrings *wentry;
for (rentry = msgstringarray; rentry->kind != '\0'; rentry++)
if (rentry->kind == rightkind)
break;
Assert(rentry->kind != '\0');
for (wentry = msgstringarray; wentry->kind != '\0'; wentry++)
if (wentry->kind == wrongkind)
break;
/* wrongkind could be something we don't have in our table... */
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg(rentry->nota_msg, relname),
(wentry->kind != '\0') ? errhint(wentry->drophint_msg) : 0));
}
/*
* Emit the right error message for a "DROP" command issued on a
* non-existent relation
*/
static void
DropErrorMsgNonExistent(RangeVar *rel, char rightkind, bool missing_ok)
{
const struct msgstrings *rentry;
for (rentry = msgstringarray; rentry->kind != '\0'; rentry++)
{
if (rentry->kind == rightkind)
{
if (!missing_ok)
{
ereport(ERROR,
(errcode(rentry->nonexistent_code),
errmsg(rentry->nonexistent_msg, rel->relname)));
}
else
{
ereport(NOTICE, (errmsg(rentry->skipping_msg, rel->relname)));
break;
}
}
}
Assert(rentry->kind != '\0'); /* Should be impossible */
}
/*
* returns false if missing_ok is true and the object does not exist,
* true if object exists and permissions are OK,
* errors otherwise
*
*/
static bool
CheckDropPermissions(RangeVar *rel, char rightkind, bool missing_ok)
{
Oid relOid;
HeapTuple tuple;
Form_pg_class classform;
relOid = RangeVarGetRelid(rel, true);
if (!OidIsValid(relOid))
{
DropErrorMsgNonExistent(rel, rightkind, missing_ok);
return false;
}
tuple = SearchSysCache(RELOID,
ObjectIdGetDatum(relOid),
0, 0, 0);
if (!HeapTupleIsValid(tuple))
elog(ERROR, "cache lookup failed for relation %u", relOid);
classform = (Form_pg_class) GETSTRUCT(tuple);
if (classform->relkind != rightkind)
DropErrorMsgWrongType(rel->relname, classform->relkind,
rightkind);
/* Allow DROP to either table owner or schema owner */
if (!pg_class_ownercheck(relOid, GetUserId()) &&
!pg_namespace_ownercheck(classform->relnamespace, GetUserId()))
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
rel->relname);
if (!allowSystemTableMods && IsSystemClass(classform))
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("permission denied: \"%s\" is a system catalog",
rel->relname)));
ReleaseSysCache(tuple);
return true;
}
/*
* Verify user has ownership of specified relation, else ereport.
*
* If noCatalogs is true then we also deny access to system catalogs,
* except when allowSystemTableMods is true.
*/
void
CheckRelationOwnership(RangeVar *rel, bool noCatalogs)
{
Oid relOid;
HeapTuple tuple;
relOid = RangeVarGetRelid(rel, false);
tuple = SearchSysCache(RELOID,
ObjectIdGetDatum(relOid),
0, 0, 0);
2003-08-04 02:43:34 +02:00
if (!HeapTupleIsValid(tuple)) /* should not happen */
elog(ERROR, "cache lookup failed for relation %u", relOid);
if (!pg_class_ownercheck(relOid, GetUserId()))
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
rel->relname);
if (noCatalogs)
{
if (!allowSystemTableMods &&
IsSystemClass((Form_pg_class) GETSTRUCT(tuple)))
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
2005-10-15 04:49:52 +02:00
errmsg("permission denied: \"%s\" is a system catalog",
rel->relname)));
}
ReleaseSysCache(tuple);
}
/*
* CommandIsReadOnly: is an executable query read-only?
*
* This is a much stricter test than we apply for XactReadOnly mode;
* the query must be *in truth* read-only, because the caller wishes
* not to do CommandCounterIncrement for it.
*
* Note: currently no need to support Query nodes here
*/
bool
CommandIsReadOnly(Node *parsetree)
{
if (IsA(parsetree, PlannedStmt))
{
PlannedStmt *stmt = (PlannedStmt *) parsetree;
switch (stmt->commandType)
{
case CMD_SELECT:
if (stmt->intoClause != NULL)
return false; /* SELECT INTO */
else if (stmt->rowMarks != NIL)
return false; /* SELECT FOR UPDATE/SHARE */
else
return true;
case CMD_UPDATE:
case CMD_INSERT:
case CMD_DELETE:
return false;
default:
elog(WARNING, "unrecognized commandType: %d",
(int) stmt->commandType);
break;
}
}
/* For now, treat all utility commands as read/write */
return false;
}
/*
* check_xact_readonly: is a utility command read-only?
*
* Here we use the loose rules of XactReadOnly mode: no permanent effects
* on the database are allowed.
*/
static void
check_xact_readonly(Node *parsetree)
{
if (!XactReadOnly)
return;
/*
2005-10-15 04:49:52 +02:00
* Note: Commands that need to do more complicated checking are handled
* elsewhere.
*/
switch (nodeTag(parsetree))
{
case T_AlterDatabaseStmt:
case T_AlterDatabaseSetStmt:
case T_AlterDomainStmt:
case T_AlterFunctionStmt:
case T_AlterRoleStmt:
case T_AlterRoleSetStmt:
case T_AlterObjectSchemaStmt:
case T_AlterOwnerStmt:
case T_AlterSeqStmt:
case T_AlterTableStmt:
case T_RenameStmt:
case T_CommentStmt:
case T_DefineStmt:
case T_CreateCastStmt:
case T_CreateConversionStmt:
case T_CreatedbStmt:
case T_CreateDomainStmt:
case T_CreateFunctionStmt:
case T_CreateRoleStmt:
case T_IndexStmt:
case T_CreatePLangStmt:
case T_CreateOpClassStmt:
case T_CreateOpFamilyStmt:
case T_AlterOpFamilyStmt:
case T_RuleStmt:
case T_CreateSchemaStmt:
case T_CreateSeqStmt:
case T_CreateStmt:
case T_CreateTableSpaceStmt:
case T_CreateTrigStmt:
case T_CompositeTypeStmt:
case T_CreateEnumStmt:
case T_ViewStmt:
case T_DropCastStmt:
case T_DropStmt:
case T_DropdbStmt:
case T_DropTableSpaceStmt:
case T_RemoveFuncStmt:
case T_DropRoleStmt:
case T_DropPLangStmt:
case T_RemoveOpClassStmt:
case T_RemoveOpFamilyStmt:
case T_DropPropertyStmt:
case T_GrantStmt:
case T_GrantRoleStmt:
case T_TruncateStmt:
case T_DropOwnedStmt:
case T_ReassignOwnedStmt:
case T_AlterTSDictionaryStmt:
case T_AlterTSConfigurationStmt:
ereport(ERROR,
(errcode(ERRCODE_READ_ONLY_SQL_TRANSACTION),
errmsg("transaction is read-only")));
break;
default:
/* do nothing */
break;
}
}
/*
* ProcessUtility
* general utility function invoker
*
* parsetree: the parse tree for the utility statement
* queryString: original source text of command (NULL if not available)
* params: parameters to use during execution
* isTopLevel: true if executing a "top level" (interactively issued) command
* dest: where to send results
* completionTag: points to a buffer of size COMPLETION_TAG_BUFSIZE
* in which to store a command completion status string.
*
* completionTag is only set nonempty if we want to return a nondefault status.
*
* completionTag may be NULL if caller doesn't want a status string.
*/
void
ProcessUtility(Node *parsetree,
const char *queryString,
ParamListInfo params,
bool isTopLevel,
DestReceiver *dest,
char *completionTag)
{
check_xact_readonly(parsetree);
if (completionTag)
completionTag[0] = '\0';
switch (nodeTag(parsetree))
{
/*
* ******************** transactions ********************
*/
case T_TransactionStmt:
{
TransactionStmt *stmt = (TransactionStmt *) parsetree;
switch (stmt->kind)
{
2004-08-29 07:07:03 +02:00
/*
2005-10-15 04:49:52 +02:00
* START TRANSACTION, as defined by SQL99: Identical
* to BEGIN. Same code for both.
2004-08-29 07:07:03 +02:00
*/
case TRANS_STMT_BEGIN:
case TRANS_STMT_START:
{
ListCell *lc;
BeginTransactionBlock();
foreach(lc, stmt->options)
{
DefElem *item = (DefElem *) lfirst(lc);
if (strcmp(item->defname, "transaction_isolation") == 0)
SetPGVariable("transaction_isolation",
list_make1(item->arg),
true);
else if (strcmp(item->defname, "transaction_read_only") == 0)
SetPGVariable("transaction_read_only",
list_make1(item->arg),
true);
}
}
break;
case TRANS_STMT_COMMIT:
if (!EndTransactionBlock())
{
/* report unsuccessful commit in completionTag */
if (completionTag)
strcpy(completionTag, "ROLLBACK");
}
break;
case TRANS_STMT_PREPARE:
if (!PrepareTransactionBlock(stmt->gid))
{
/* report unsuccessful commit in completionTag */
if (completionTag)
strcpy(completionTag, "ROLLBACK");
}
break;
case TRANS_STMT_COMMIT_PREPARED:
PreventTransactionChain(isTopLevel, "COMMIT PREPARED");
FinishPreparedTransaction(stmt->gid, true);
break;
case TRANS_STMT_ROLLBACK_PREPARED:
PreventTransactionChain(isTopLevel, "ROLLBACK PREPARED");
FinishPreparedTransaction(stmt->gid, false);
break;
case TRANS_STMT_ROLLBACK:
UserAbortTransactionBlock();
break;
case TRANS_STMT_SAVEPOINT:
{
2004-08-29 07:07:03 +02:00
ListCell *cell;
char *name = NULL;
RequireTransactionChain(isTopLevel, "SAVEPOINT");
2004-08-29 07:07:03 +02:00
foreach(cell, stmt->options)
{
2004-08-29 07:07:03 +02:00
DefElem *elem = lfirst(cell);
if (strcmp(elem->defname, "savepoint_name") == 0)
name = strVal(elem->arg);
}
Assert(PointerIsValid(name));
DefineSavepoint(name);
}
break;
case TRANS_STMT_RELEASE:
RequireTransactionChain(isTopLevel, "RELEASE SAVEPOINT");
ReleaseSavepoint(stmt->options);
break;
case TRANS_STMT_ROLLBACK_TO:
RequireTransactionChain(isTopLevel, "ROLLBACK TO SAVEPOINT");
RollbackToSavepoint(stmt->options);
2004-08-29 07:07:03 +02:00
/*
2004-08-29 07:07:03 +02:00
* CommitTransactionCommand is in charge of
* re-defining the savepoint again
*/
break;
}
}
break;
/*
* Portal (cursor) manipulation
*
* Note: DECLARE CURSOR is processed mostly as a SELECT, and
* therefore what we will get here is a PlannedStmt not a bare
* DeclareCursorStmt.
*/
case T_PlannedStmt:
{
PlannedStmt *stmt = (PlannedStmt *) parsetree;
if (stmt->utilityStmt == NULL ||
!IsA(stmt->utilityStmt, DeclareCursorStmt))
elog(ERROR, "non-DECLARE CURSOR PlannedStmt passed to ProcessUtility");
PerformCursorOpen(stmt, params, queryString, isTopLevel);
}
break;
case T_ClosePortalStmt:
{
ClosePortalStmt *stmt = (ClosePortalStmt *) parsetree;
PerformPortalClose(stmt->portalname);
}
break;
case T_FetchStmt:
PerformPortalFetch((FetchStmt *) parsetree, dest,
completionTag);
break;
/*
* relation and attribute manipulation
*/
case T_CreateSchemaStmt:
CreateSchemaCommand((CreateSchemaStmt *) parsetree,
queryString);
break;
case T_CreateStmt:
{
List *stmts;
ListCell *l;
Oid relOid;
/* Run parse analysis ... */
stmts = transformCreateStmt((CreateStmt *) parsetree,
queryString);
/* ... and do it */
foreach(l, stmts)
{
Node *stmt = (Node *) lfirst(l);
if (IsA(stmt, CreateStmt))
{
/* Create the table itself */
relOid = DefineRelation((CreateStmt *) stmt,
RELKIND_RELATION);
/*
* Let AlterTableCreateToastTable decide if this one
* needs a secondary relation too.
*/
CommandCounterIncrement();
AlterTableCreateToastTable(relOid);
}
else
{
/* Recurse for anything else */
ProcessUtility(stmt,
queryString,
params,
false,
None_Receiver,
NULL);
}
/* Need CCI between commands */
if (lnext(l) != NULL)
CommandCounterIncrement();
}
}
break;
case T_CreateTableSpaceStmt:
PreventTransactionChain(isTopLevel, "CREATE TABLESPACE");
CreateTableSpace((CreateTableSpaceStmt *) parsetree);
break;
case T_DropTableSpaceStmt:
PreventTransactionChain(isTopLevel, "DROP TABLESPACE");
DropTableSpace((DropTableSpaceStmt *) parsetree);
break;
case T_DropStmt:
{
DropStmt *stmt = (DropStmt *) parsetree;
ListCell *arg;
foreach(arg, stmt->objects)
{
2002-09-04 22:31:48 +02:00
List *names = (List *) lfirst(arg);
RangeVar *rel;
2001-03-22 05:01:46 +01:00
switch (stmt->removeType)
{
2003-06-27 16:45:32 +02:00
case OBJECT_TABLE:
rel = makeRangeVarFromNameList(names);
if (CheckDropPermissions(rel, RELKIND_RELATION,
stmt->missing_ok))
RemoveRelation(rel, stmt->behavior);
break;
2003-06-27 16:45:32 +02:00
case OBJECT_SEQUENCE:
rel = makeRangeVarFromNameList(names);
if (CheckDropPermissions(rel, RELKIND_SEQUENCE,
stmt->missing_ok))
RemoveRelation(rel, stmt->behavior);
break;
2003-06-27 16:45:32 +02:00
case OBJECT_VIEW:
rel = makeRangeVarFromNameList(names);
if (CheckDropPermissions(rel, RELKIND_VIEW,
stmt->missing_ok))
RemoveView(rel, stmt->behavior);
break;
2003-06-27 16:45:32 +02:00
case OBJECT_INDEX:
rel = makeRangeVarFromNameList(names);
if (CheckDropPermissions(rel, RELKIND_INDEX,
stmt->missing_ok))
RemoveIndex(rel, stmt->behavior);
break;
2003-06-27 16:45:32 +02:00
case OBJECT_TYPE:
/* RemoveType does its own permissions checks */
RemoveType(names, stmt->behavior,
stmt->missing_ok);
break;
2003-06-27 16:45:32 +02:00
case OBJECT_DOMAIN:
/* RemoveDomain does its own permissions checks */
RemoveDomain(names, stmt->behavior,
stmt->missing_ok);
break;
2003-06-27 16:45:32 +02:00
case OBJECT_CONVERSION:
DropConversionCommand(names, stmt->behavior,
stmt->missing_ok);
break;
2003-06-27 16:45:32 +02:00
case OBJECT_SCHEMA:
/* RemoveSchema does its own permissions checks */
RemoveSchema(names, stmt->behavior,
stmt->missing_ok);
break;
2003-06-27 16:45:32 +02:00
case OBJECT_TSPARSER:
RemoveTSParser(names, stmt->behavior,
stmt->missing_ok);
break;
case OBJECT_TSDICTIONARY:
RemoveTSDictionary(names, stmt->behavior,
stmt->missing_ok);
break;
case OBJECT_TSTEMPLATE:
RemoveTSTemplate(names, stmt->behavior,
stmt->missing_ok);
break;
case OBJECT_TSCONFIGURATION:
RemoveTSConfiguration(names, stmt->behavior,
stmt->missing_ok);
break;
2003-06-27 16:45:32 +02:00
default:
elog(ERROR, "unrecognized drop object type: %d",
(int) stmt->removeType);
break;
}
/*
2005-10-15 04:49:52 +02:00
* We used to need to do CommandCounterIncrement() here,
* but now it's done inside performDeletion().
*/
}
}
break;
case T_TruncateStmt:
ExecuteTruncate((TruncateStmt *) parsetree);
break;
case T_CommentStmt:
CommentObject((CommentStmt *) parsetree);
break;
case T_CopyStmt:
{
uint64 processed;
processed = DoCopy((CopyStmt *) parsetree, queryString);
if (completionTag)
snprintf(completionTag, COMPLETION_TAG_BUFSIZE,
"COPY " UINT64_FORMAT, processed);
}
break;
case T_PrepareStmt:
PrepareQuery((PrepareStmt *) parsetree, queryString);
break;
case T_ExecuteStmt:
ExecuteQuery((ExecuteStmt *) parsetree, queryString, params,
dest, completionTag);
break;
case T_DeallocateStmt:
DeallocateQuery((DeallocateStmt *) parsetree);
break;
/*
* schema
*/
case T_RenameStmt:
2003-06-27 16:45:32 +02:00
ExecRenameStmt((RenameStmt *) parsetree);
break;
case T_AlterObjectSchemaStmt:
ExecAlterObjectSchemaStmt((AlterObjectSchemaStmt *) parsetree);
break;
case T_AlterOwnerStmt:
ExecAlterOwnerStmt((AlterOwnerStmt *) parsetree);
break;
case T_AlterTableStmt:
{
List *stmts;
ListCell *l;
/* Run parse analysis ... */
stmts = transformAlterTableStmt((AlterTableStmt *) parsetree,
queryString);
/* ... and do it */
foreach(l, stmts)
{
Node *stmt = (Node *) lfirst(l);
if (IsA(stmt, AlterTableStmt))
{
/* Do the table alteration proper */
AlterTable((AlterTableStmt *) stmt);
}
else
{
/* Recurse for anything else */
ProcessUtility(stmt,
queryString,
params,
false,
None_Receiver,
NULL);
}
/* Need CCI between commands */
if (lnext(l) != NULL)
CommandCounterIncrement();
}
}
break;
2002-12-06 06:00:34 +01:00
case T_AlterDomainStmt:
{
AlterDomainStmt *stmt = (AlterDomainStmt *) parsetree;
/*
* Some or all of these functions are recursive to cover
* inherited things, so permission checks are done there.
*/
switch (stmt->subtype)
{
case 'T': /* ALTER DOMAIN DEFAULT */
2002-12-06 06:00:34 +01:00
/*
2005-10-15 04:49:52 +02:00
* Recursively alter column default for table and, if
* requested, for descendants
2002-12-06 06:00:34 +01:00
*/
AlterDomainDefault(stmt->typename,
stmt->def);
break;
case 'N': /* ALTER DOMAIN DROP NOT NULL */
2002-12-06 06:00:34 +01:00
AlterDomainNotNull(stmt->typename,
false);
break;
case 'O': /* ALTER DOMAIN SET NOT NULL */
2002-12-06 06:00:34 +01:00
AlterDomainNotNull(stmt->typename,
true);
break;
case 'C': /* ADD CONSTRAINT */
AlterDomainAddConstraint(stmt->typename,
stmt->def);
break;
case 'X': /* DROP CONSTRAINT */
AlterDomainDropConstraint(stmt->typename,
stmt->name,
stmt->behavior);
break;
default: /* oops */
elog(ERROR, "unrecognized alter domain type: %d",
(int) stmt->subtype);
2002-12-06 06:00:34 +01:00
break;
}
}
break;
case T_GrantStmt:
ExecuteGrantStmt((GrantStmt *) parsetree);
break;
case T_GrantRoleStmt:
GrantRole((GrantRoleStmt *) parsetree);
break;
/*
* **************** object creation / destruction *****************
*/
case T_DefineStmt:
{
DefineStmt *stmt = (DefineStmt *) parsetree;
switch (stmt->kind)
{
2003-06-27 16:45:32 +02:00
case OBJECT_AGGREGATE:
DefineAggregate(stmt->defnames, stmt->args,
stmt->oldstyle, stmt->definition);
break;
2003-06-27 16:45:32 +02:00
case OBJECT_OPERATOR:
Assert(stmt->args == NIL);
DefineOperator(stmt->defnames, stmt->definition);
break;
2003-06-27 16:45:32 +02:00
case OBJECT_TYPE:
Assert(stmt->args == NIL);
DefineType(stmt->defnames, stmt->definition);
break;
case OBJECT_TSPARSER:
Assert(stmt->args == NIL);
DefineTSParser(stmt->defnames, stmt->definition);
break;
case OBJECT_TSDICTIONARY:
Assert(stmt->args == NIL);
DefineTSDictionary(stmt->defnames, stmt->definition);
break;
case OBJECT_TSTEMPLATE:
Assert(stmt->args == NIL);
DefineTSTemplate(stmt->defnames, stmt->definition);
break;
case OBJECT_TSCONFIGURATION:
Assert(stmt->args == NIL);
DefineTSConfiguration(stmt->defnames, stmt->definition);
break;
2003-06-27 16:45:32 +02:00
default:
elog(ERROR, "unrecognized define stmt type: %d",
(int) stmt->kind);
break;
}
}
break;
case T_CompositeTypeStmt: /* CREATE TYPE (composite) */
{
2002-09-04 22:31:48 +02:00
CompositeTypeStmt *stmt = (CompositeTypeStmt *) parsetree;
DefineCompositeType(stmt->typevar, stmt->coldeflist);
}
break;
case T_CreateEnumStmt: /* CREATE TYPE (enum) */
DefineEnum((CreateEnumStmt *) parsetree);
break;
case T_ViewStmt: /* CREATE VIEW */
DefineView((ViewStmt *) parsetree, queryString);
break;
2002-09-04 22:31:48 +02:00
case T_CreateFunctionStmt: /* CREATE FUNCTION */
CreateFunction((CreateFunctionStmt *) parsetree);
break;
2005-10-15 04:49:52 +02:00
case T_AlterFunctionStmt: /* ALTER FUNCTION */
AlterFunction((AlterFunctionStmt *) parsetree);
break;
case T_IndexStmt: /* CREATE INDEX */
{
IndexStmt *stmt = (IndexStmt *) parsetree;
if (stmt->concurrent)
PreventTransactionChain(isTopLevel,
"CREATE INDEX CONCURRENTLY");
CheckRelationOwnership(stmt->relation, true);
/* Run parse analysis ... */
stmt = transformIndexStmt(stmt, queryString);
/* ... and do it */
2002-09-04 22:31:48 +02:00
DefineIndex(stmt->relation, /* relation */
stmt->idxname, /* index name */
2005-10-15 04:49:52 +02:00
InvalidOid, /* no predefined OID */
2002-09-04 22:31:48 +02:00
stmt->accessMethod, /* am name */
stmt->tableSpace,
2002-09-04 22:31:48 +02:00
stmt->indexParams, /* parameters */
(Expr *) stmt->whereClause,
stmt->options,
stmt->src_options,
stmt->unique,
stmt->primary,
stmt->isconstraint,
2006-10-04 02:30:14 +02:00
false, /* is_alter_table */
true, /* check_rights */
false, /* skip_build */
false, /* quiet */
stmt->concurrent); /* concurrent */
}
break;
case T_RuleStmt: /* CREATE RULE */
DefineRule((RuleStmt *) parsetree, queryString);
break;
case T_CreateSeqStmt:
DefineSequence((CreateSeqStmt *) parsetree);
break;
case T_AlterSeqStmt:
AlterSequence((AlterSeqStmt *) parsetree);
break;
case T_RemoveFuncStmt:
{
RemoveFuncStmt *stmt = (RemoveFuncStmt *) parsetree;
switch (stmt->kind)
{
case OBJECT_FUNCTION:
RemoveFunction(stmt);
break;
case OBJECT_AGGREGATE:
RemoveAggregate(stmt);
break;
case OBJECT_OPERATOR:
RemoveOperator(stmt);
break;
default:
elog(ERROR, "unrecognized object type: %d",
(int) stmt->kind);
break;
}
}
break;
case T_CreatedbStmt:
PreventTransactionChain(isTopLevel, "CREATE DATABASE");
createdb((CreatedbStmt *) parsetree);
break;
case T_AlterDatabaseStmt:
AlterDatabase((AlterDatabaseStmt *) parsetree);
break;
case T_AlterDatabaseSetStmt:
AlterDatabaseSet((AlterDatabaseSetStmt *) parsetree);
break;
case T_DropdbStmt:
{
DropdbStmt *stmt = (DropdbStmt *) parsetree;
PreventTransactionChain(isTopLevel, "DROP DATABASE");
2005-11-22 16:24:18 +01:00
dropdb(stmt->dbname, stmt->missing_ok);
}
break;
/* Query-level asynchronous notification */
case T_NotifyStmt:
{
NotifyStmt *stmt = (NotifyStmt *) parsetree;
Async_Notify(stmt->relation->relname);
}
break;
case T_ListenStmt:
{
ListenStmt *stmt = (ListenStmt *) parsetree;
Async_Listen(stmt->relation->relname);
}
break;
case T_UnlistenStmt:
{
UnlistenStmt *stmt = (UnlistenStmt *) parsetree;
Async_Unlisten(stmt->relation->relname);
}
break;
case T_LoadStmt:
{
LoadStmt *stmt = (LoadStmt *) parsetree;
1999-05-25 18:15:34 +02:00
closeAllVfds(); /* probably not necessary... */
/* Allowed names are restricted if you're not superuser */
load_file(stmt->filename, !superuser());
}
break;
case T_ClusterStmt:
cluster((ClusterStmt *) parsetree, isTopLevel);
break;
case T_VacuumStmt:
vacuum((VacuumStmt *) parsetree, NIL, NULL, isTopLevel);
break;
case T_ExplainStmt:
ExplainQuery((ExplainStmt *) parsetree, queryString, params, dest);
break;
case T_VariableSetStmt:
ExecSetVariableStmt((VariableSetStmt *) parsetree);
break;
case T_VariableShowStmt:
{
VariableShowStmt *n = (VariableShowStmt *) parsetree;
GetPGVariable(n->name, dest);
}
break;
case T_DiscardStmt:
DiscardCommand((DiscardStmt *) parsetree, isTopLevel);
break;
case T_CreateTrigStmt:
CreateTrigger((CreateTrigStmt *) parsetree, InvalidOid);
break;
case T_DropPropertyStmt:
{
DropPropertyStmt *stmt = (DropPropertyStmt *) parsetree;
2002-09-04 22:31:48 +02:00
Oid relId;
relId = RangeVarGetRelid(stmt->relation, false);
switch (stmt->removeType)
{
2003-06-27 16:45:32 +02:00
case OBJECT_RULE:
/* RemoveRewriteRule checks permissions */
RemoveRewriteRule(relId, stmt->property,
stmt->behavior, stmt->missing_ok);
break;
2003-06-27 16:45:32 +02:00
case OBJECT_TRIGGER:
/* DropTrigger checks permissions */
DropTrigger(relId, stmt->property,
stmt->behavior, stmt->missing_ok);
break;
2003-06-27 16:45:32 +02:00
default:
elog(ERROR, "unrecognized object type: %d",
(int) stmt->removeType);
break;
}
}
break;
case T_CreatePLangStmt:
CreateProceduralLanguage((CreatePLangStmt *) parsetree);
break;
case T_DropPLangStmt:
DropProceduralLanguage((DropPLangStmt *) parsetree);
break;
/*
* ******************************** DOMAIN statements ****
*/
case T_CreateDomainStmt:
DefineDomain((CreateDomainStmt *) parsetree);
break;
/*
* ******************************** ROLE statements ****
*/
case T_CreateRoleStmt:
CreateRole((CreateRoleStmt *) parsetree);
break;
case T_AlterRoleStmt:
AlterRole((AlterRoleStmt *) parsetree);
break;
case T_AlterRoleSetStmt:
AlterRoleSet((AlterRoleSetStmt *) parsetree);
break;
case T_DropRoleStmt:
DropRole((DropRoleStmt *) parsetree);
break;
case T_DropOwnedStmt:
DropOwnedObjects((DropOwnedStmt *) parsetree);
break;
case T_ReassignOwnedStmt:
ReassignOwnedObjects((ReassignOwnedStmt *) parsetree);
break;
case T_LockStmt:
LockTableCommand((LockStmt *) parsetree);
break;
case T_ConstraintsSetStmt:
AfterTriggerSetState((ConstraintsSetStmt *) parsetree);
break;
case T_CheckPointStmt:
if (!superuser())
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("must be superuser to do CHECKPOINT")));
RequestCheckpoint(CHECKPOINT_IMMEDIATE | CHECKPOINT_FORCE | CHECKPOINT_WAIT);
break;
2000-02-18 10:30:20 +01:00
case T_ReindexStmt:
{
ReindexStmt *stmt = (ReindexStmt *) parsetree;
switch (stmt->kind)
2000-02-18 10:30:20 +01:00
{
2003-06-27 16:45:32 +02:00
case OBJECT_INDEX:
ReindexIndex(stmt->relation);
2000-02-18 10:30:20 +01:00
break;
2003-06-27 16:45:32 +02:00
case OBJECT_TABLE:
ReindexTable(stmt->relation);
2000-02-18 10:30:20 +01:00
break;
2003-06-27 16:45:32 +02:00
case OBJECT_DATABASE:
/*
* This cannot run inside a user transaction block;
* if we were inside a transaction, then its commit-
* and start-transaction-command calls would not have
* the intended effect!
*/
PreventTransactionChain(isTopLevel,
"REINDEX DATABASE");
ReindexDatabase(stmt->name,
stmt->do_system, stmt->do_user);
2000-02-18 10:30:20 +01:00
break;
2003-06-27 16:45:32 +02:00
default:
elog(ERROR, "unrecognized object type: %d",
(int) stmt->kind);
break;
2000-02-18 10:30:20 +01:00
}
break;
}
break;
case T_CreateConversionStmt:
CreateConversionCommand((CreateConversionStmt *) parsetree);
break;
case T_CreateCastStmt:
CreateCast((CreateCastStmt *) parsetree);
break;
case T_DropCastStmt:
DropCast((DropCastStmt *) parsetree);
break;
case T_CreateOpClassStmt:
DefineOpClass((CreateOpClassStmt *) parsetree);
break;
case T_CreateOpFamilyStmt:
DefineOpFamily((CreateOpFamilyStmt *) parsetree);
break;
case T_AlterOpFamilyStmt:
AlterOpFamily((AlterOpFamilyStmt *) parsetree);
break;
case T_RemoveOpClassStmt:
RemoveOpClass((RemoveOpClassStmt *) parsetree);
break;
case T_RemoveOpFamilyStmt:
RemoveOpFamily((RemoveOpFamilyStmt *) parsetree);
break;
case T_AlterTSDictionaryStmt:
AlterTSDictionary((AlterTSDictionaryStmt *) parsetree);
break;
case T_AlterTSConfigurationStmt:
AlterTSConfiguration((AlterTSConfigurationStmt *) parsetree);
break;
default:
elog(ERROR, "unrecognized node type: %d",
(int) nodeTag(parsetree));
break;
}
}
/*
* UtilityReturnsTuples
* Return "true" if this utility statement will send output to the
* destination.
*
* Generally, there should be a case here for each case in ProcessUtility
* where "dest" is passed on.
*/
bool
UtilityReturnsTuples(Node *parsetree)
{
switch (nodeTag(parsetree))
{
case T_FetchStmt:
{
2003-08-04 02:43:34 +02:00
FetchStmt *stmt = (FetchStmt *) parsetree;
Portal portal;
if (stmt->ismove)
return false;
portal = GetPortalByName(stmt->portalname);
if (!PortalIsValid(portal))
2003-08-04 02:43:34 +02:00
return false; /* not our business to raise error */
return portal->tupDesc ? true : false;
}
case T_ExecuteStmt:
{
ExecuteStmt *stmt = (ExecuteStmt *) parsetree;
PreparedStatement *entry;
if (stmt->into)
return false;
entry = FetchPreparedStatement(stmt->name, false);
if (!entry)
2003-08-04 02:43:34 +02:00
return false; /* not our business to raise error */
if (entry->plansource->resultDesc)
return true;
return false;
}
case T_ExplainStmt:
return true;
case T_VariableShowStmt:
return true;
default:
return false;
}
}
/*
* UtilityTupleDescriptor
* Fetch the actual output tuple descriptor for a utility statement
* for which UtilityReturnsTuples() previously returned "true".
*
* The returned descriptor is created in (or copied into) the current memory
* context.
*/
TupleDesc
UtilityTupleDescriptor(Node *parsetree)
{
switch (nodeTag(parsetree))
{
case T_FetchStmt:
{
2003-08-04 02:43:34 +02:00
FetchStmt *stmt = (FetchStmt *) parsetree;
Portal portal;
if (stmt->ismove)
return NULL;
portal = GetPortalByName(stmt->portalname);
if (!PortalIsValid(portal))
2003-08-04 02:43:34 +02:00
return NULL; /* not our business to raise error */
return CreateTupleDescCopy(portal->tupDesc);
}
case T_ExecuteStmt:
{
ExecuteStmt *stmt = (ExecuteStmt *) parsetree;
PreparedStatement *entry;
if (stmt->into)
return NULL;
entry = FetchPreparedStatement(stmt->name, false);
if (!entry)
2003-08-04 02:43:34 +02:00
return NULL; /* not our business to raise error */
return FetchPreparedStatementResultDesc(entry);
}
case T_ExplainStmt:
return ExplainResultDesc((ExplainStmt *) parsetree);
case T_VariableShowStmt:
{
VariableShowStmt *n = (VariableShowStmt *) parsetree;
return GetPGVariableResultDesc(n->name);
}
default:
return NULL;
}
}
/*
* QueryReturnsTuples
* Return "true" if this Query will send output to the destination.
*/
#ifdef NOT_USED
bool
QueryReturnsTuples(Query *parsetree)
{
switch (parsetree->commandType)
{
case CMD_SELECT:
/* returns tuples ... unless it's DECLARE CURSOR or SELECT INTO */
if (parsetree->utilityStmt == NULL &&
parsetree->intoClause == NULL)
return true;
break;
case CMD_INSERT:
case CMD_UPDATE:
case CMD_DELETE:
/* the forms with RETURNING return tuples */
if (parsetree->returningList)
return true;
break;
case CMD_UTILITY:
return UtilityReturnsTuples(parsetree->utilityStmt);
case CMD_UNKNOWN:
case CMD_NOTHING:
/* probably shouldn't get here */
break;
}
return false; /* default */
}
#endif
/*
* CreateCommandTag
* utility to get a string representation of the command operation,
* given either a raw (un-analyzed) parsetree or a planned query.
*
* This must handle all command types, but since the vast majority
* of 'em are utility commands, it seems sensible to keep it here.
*
* NB: all result strings must be shorter than COMPLETION_TAG_BUFSIZE.
* Also, the result must point at a true constant (permanent storage).
*/
const char *
CreateCommandTag(Node *parsetree)
{
const char *tag;
switch (nodeTag(parsetree))
{
/* raw plannable queries */
case T_InsertStmt:
tag = "INSERT";
break;
case T_DeleteStmt:
tag = "DELETE";
break;
case T_UpdateStmt:
tag = "UPDATE";
break;
case T_SelectStmt:
tag = "SELECT";
break;
/* utility statements --- same whether raw or cooked */
case T_TransactionStmt:
{
TransactionStmt *stmt = (TransactionStmt *) parsetree;
switch (stmt->kind)
{
case TRANS_STMT_BEGIN:
tag = "BEGIN";
break;
case TRANS_STMT_START:
tag = "START TRANSACTION";
break;
case TRANS_STMT_COMMIT:
tag = "COMMIT";
break;
case TRANS_STMT_ROLLBACK:
case TRANS_STMT_ROLLBACK_TO:
tag = "ROLLBACK";
break;
case TRANS_STMT_SAVEPOINT:
tag = "SAVEPOINT";
break;
case TRANS_STMT_RELEASE:
tag = "RELEASE";
break;
case TRANS_STMT_PREPARE:
tag = "PREPARE TRANSACTION";
break;
case TRANS_STMT_COMMIT_PREPARED:
tag = "COMMIT PREPARED";
break;
case TRANS_STMT_ROLLBACK_PREPARED:
tag = "ROLLBACK PREPARED";
break;
default:
tag = "???";
break;
}
}
break;
case T_DeclareCursorStmt:
tag = "DECLARE CURSOR";
break;
case T_ClosePortalStmt:
{
ClosePortalStmt *stmt = (ClosePortalStmt *) parsetree;
if (stmt->portalname == NULL)
tag = "CLOSE CURSOR ALL";
else
tag = "CLOSE CURSOR";
}
break;
case T_FetchStmt:
{
FetchStmt *stmt = (FetchStmt *) parsetree;
tag = (stmt->ismove) ? "MOVE" : "FETCH";
}
break;
case T_CreateDomainStmt:
tag = "CREATE DOMAIN";
break;
case T_CreateSchemaStmt:
tag = "CREATE SCHEMA";
break;
case T_CreateStmt:
tag = "CREATE TABLE";
break;
case T_CreateTableSpaceStmt:
tag = "CREATE TABLESPACE";
break;
case T_DropTableSpaceStmt:
tag = "DROP TABLESPACE";
break;
case T_DropStmt:
switch (((DropStmt *) parsetree)->removeType)
{
2003-06-27 16:45:32 +02:00
case OBJECT_TABLE:
tag = "DROP TABLE";
break;
2003-06-27 16:45:32 +02:00
case OBJECT_SEQUENCE:
tag = "DROP SEQUENCE";
break;
2003-06-27 16:45:32 +02:00
case OBJECT_VIEW:
tag = "DROP VIEW";
break;
2003-06-27 16:45:32 +02:00
case OBJECT_INDEX:
tag = "DROP INDEX";
break;
2003-06-27 16:45:32 +02:00
case OBJECT_TYPE:
tag = "DROP TYPE";
break;
2003-06-27 16:45:32 +02:00
case OBJECT_DOMAIN:
tag = "DROP DOMAIN";
break;
2003-06-27 16:45:32 +02:00
case OBJECT_CONVERSION:
tag = "DROP CONVERSION";
break;
2003-06-27 16:45:32 +02:00
case OBJECT_SCHEMA:
tag = "DROP SCHEMA";
break;
case OBJECT_TSPARSER:
tag = "DROP TEXT SEARCH PARSER";
break;
case OBJECT_TSDICTIONARY:
tag = "DROP TEXT SEARCH DICTIONARY";
break;
case OBJECT_TSTEMPLATE:
tag = "DROP TEXT SEARCH TEMPLATE";
break;
case OBJECT_TSCONFIGURATION:
tag = "DROP TEXT SEARCH CONFIGURATION";
break;
default:
tag = "???";
}
break;
case T_TruncateStmt:
tag = "TRUNCATE TABLE";
break;
case T_CommentStmt:
tag = "COMMENT";
break;
case T_CopyStmt:
tag = "COPY";
break;
case T_RenameStmt:
2003-06-27 16:45:32 +02:00
switch (((RenameStmt *) parsetree)->renameType)
{
case OBJECT_AGGREGATE:
tag = "ALTER AGGREGATE";
break;
case OBJECT_CONVERSION:
tag = "ALTER CONVERSION";
break;
case OBJECT_DATABASE:
tag = "ALTER DATABASE";
break;
case OBJECT_FUNCTION:
tag = "ALTER FUNCTION";
break;
case OBJECT_INDEX:
tag = "ALTER INDEX";
break;
2003-06-27 16:45:32 +02:00
case OBJECT_LANGUAGE:
tag = "ALTER LANGUAGE";
break;
case OBJECT_OPCLASS:
tag = "ALTER OPERATOR CLASS";
break;
case OBJECT_OPFAMILY:
tag = "ALTER OPERATOR FAMILY";
break;
case OBJECT_ROLE:
tag = "ALTER ROLE";
break;
2003-06-27 16:45:32 +02:00
case OBJECT_SCHEMA:
tag = "ALTER SCHEMA";
break;
case OBJECT_SEQUENCE:
tag = "ALTER SEQUENCE";
break;
case OBJECT_COLUMN:
case OBJECT_TABLE:
tag = "ALTER TABLE";
break;
case OBJECT_TABLESPACE:
tag = "ALTER TABLESPACE";
break;
2003-06-27 16:45:32 +02:00
case OBJECT_TRIGGER:
tag = "ALTER TRIGGER";
break;
case OBJECT_VIEW:
tag = "ALTER VIEW";
break;
case OBJECT_TSPARSER:
tag = "ALTER TEXT SEARCH PARSER";
break;
case OBJECT_TSDICTIONARY:
tag = "ALTER TEXT SEARCH DICTIONARY";
break;
case OBJECT_TSTEMPLATE:
tag = "ALTER TEXT SEARCH TEMPLATE";
break;
case OBJECT_TSCONFIGURATION:
tag = "ALTER TEXT SEARCH CONFIGURATION";
break;
2003-06-27 16:45:32 +02:00
default:
tag = "???";
break;
2003-06-27 16:45:32 +02:00
}
break;
case T_AlterObjectSchemaStmt:
2005-10-15 04:49:52 +02:00
switch (((AlterObjectSchemaStmt *) parsetree)->objectType)
{
case OBJECT_AGGREGATE:
2005-10-15 04:49:52 +02:00
tag = "ALTER AGGREGATE";
break;
case OBJECT_DOMAIN:
2005-10-15 04:49:52 +02:00
tag = "ALTER DOMAIN";
break;
case OBJECT_FUNCTION:
2005-10-15 04:49:52 +02:00
tag = "ALTER FUNCTION";
break;
case OBJECT_SEQUENCE:
2005-10-15 04:49:52 +02:00
tag = "ALTER SEQUENCE";
break;
case OBJECT_TABLE:
2005-10-15 04:49:52 +02:00
tag = "ALTER TABLE";
break;
case OBJECT_TYPE:
2005-10-15 04:49:52 +02:00
tag = "ALTER TYPE";
break;
case OBJECT_TSPARSER:
tag = "ALTER TEXT SEARCH PARSER";
break;
case OBJECT_TSDICTIONARY:
tag = "ALTER TEXT SEARCH DICTIONARY";
break;
case OBJECT_TSTEMPLATE:
tag = "ALTER TEXT SEARCH TEMPLATE";
break;
case OBJECT_TSCONFIGURATION:
tag = "ALTER TEXT SEARCH CONFIGURATION";
break;
default:
tag = "???";
break;
2005-10-15 04:49:52 +02:00
}
break;
case T_AlterOwnerStmt:
switch (((AlterOwnerStmt *) parsetree)->objectType)
{
case OBJECT_AGGREGATE:
tag = "ALTER AGGREGATE";
break;
case OBJECT_CONVERSION:
tag = "ALTER CONVERSION";
break;
case OBJECT_DATABASE:
tag = "ALTER DATABASE";
break;
case OBJECT_DOMAIN:
tag = "ALTER DOMAIN";
break;
case OBJECT_FUNCTION:
tag = "ALTER FUNCTION";
break;
case OBJECT_LANGUAGE:
tag = "ALTER LANGUAGE";
break;
case OBJECT_OPERATOR:
tag = "ALTER OPERATOR";
break;
case OBJECT_OPCLASS:
tag = "ALTER OPERATOR CLASS";
break;
case OBJECT_OPFAMILY:
tag = "ALTER OPERATOR FAMILY";
break;
case OBJECT_SCHEMA:
tag = "ALTER SCHEMA";
break;
case OBJECT_TABLESPACE:
tag = "ALTER TABLESPACE";
break;
case OBJECT_TYPE:
tag = "ALTER TYPE";
break;
case OBJECT_TSCONFIGURATION:
tag = "ALTER TEXT SEARCH CONFIGURATION";
break;
case OBJECT_TSDICTIONARY:
tag = "ALTER TEXT SEARCH DICTIONARY";
break;
default:
tag = "???";
break;
}
break;
case T_AlterTableStmt:
{
AlterTableStmt *stmt = (AlterTableStmt *) parsetree;
2004-08-29 07:07:03 +02:00
/*
* We might be supporting ALTER INDEX here, so set the
* completion tag appropriately. Catch all other
2004-08-29 07:07:03 +02:00
* possibilities with ALTER TABLE
*/
2004-08-29 07:07:03 +02:00
if (stmt->relkind == OBJECT_INDEX)
tag = "ALTER INDEX";
else
tag = "ALTER TABLE";
}
break;
case T_AlterDomainStmt:
tag = "ALTER DOMAIN";
break;
case T_AlterFunctionStmt:
tag = "ALTER FUNCTION";
break;
case T_GrantStmt:
{
GrantStmt *stmt = (GrantStmt *) parsetree;
tag = (stmt->is_grant) ? "GRANT" : "REVOKE";
}
break;
case T_GrantRoleStmt:
{
2005-10-15 04:49:52 +02:00
GrantRoleStmt *stmt = (GrantRoleStmt *) parsetree;
tag = (stmt->is_grant) ? "GRANT ROLE" : "REVOKE ROLE";
}
break;
case T_DefineStmt:
switch (((DefineStmt *) parsetree)->kind)
{
2003-06-27 16:45:32 +02:00
case OBJECT_AGGREGATE:
tag = "CREATE AGGREGATE";
break;
2003-06-27 16:45:32 +02:00
case OBJECT_OPERATOR:
tag = "CREATE OPERATOR";
break;
2003-06-27 16:45:32 +02:00
case OBJECT_TYPE:
tag = "CREATE TYPE";
break;
case OBJECT_TSPARSER:
tag = "CREATE TEXT SEARCH PARSER";
break;
case OBJECT_TSDICTIONARY:
tag = "CREATE TEXT SEARCH DICTIONARY";
break;
case OBJECT_TSTEMPLATE:
tag = "CREATE TEXT SEARCH TEMPLATE";
break;
case OBJECT_TSCONFIGURATION:
tag = "CREATE TEXT SEARCH CONFIGURATION";
break;
default:
tag = "???";
}
break;
case T_CompositeTypeStmt:
tag = "CREATE TYPE";
break;
case T_CreateEnumStmt:
tag = "CREATE TYPE";
break;
case T_ViewStmt:
tag = "CREATE VIEW";
break;
case T_CreateFunctionStmt:
tag = "CREATE FUNCTION";
break;
case T_IndexStmt:
tag = "CREATE INDEX";
break;
case T_RuleStmt:
tag = "CREATE RULE";
break;
case T_CreateSeqStmt:
tag = "CREATE SEQUENCE";
break;
case T_AlterSeqStmt:
tag = "ALTER SEQUENCE";
break;
case T_RemoveFuncStmt:
switch (((RemoveFuncStmt *) parsetree)->kind)
{
case OBJECT_FUNCTION:
tag = "DROP FUNCTION";
break;
case OBJECT_AGGREGATE:
tag = "DROP AGGREGATE";
break;
case OBJECT_OPERATOR:
tag = "DROP OPERATOR";
break;
default:
tag = "???";
}
break;
case T_CreatedbStmt:
tag = "CREATE DATABASE";
break;
case T_AlterDatabaseStmt:
tag = "ALTER DATABASE";
break;
case T_AlterDatabaseSetStmt:
tag = "ALTER DATABASE";
break;
case T_DropdbStmt:
tag = "DROP DATABASE";
break;
case T_NotifyStmt:
tag = "NOTIFY";
break;
case T_ListenStmt:
tag = "LISTEN";
break;
case T_UnlistenStmt:
tag = "UNLISTEN";
break;
case T_LoadStmt:
tag = "LOAD";
break;
case T_ClusterStmt:
tag = "CLUSTER";
break;
case T_VacuumStmt:
if (((VacuumStmt *) parsetree)->vacuum)
tag = "VACUUM";
else
tag = "ANALYZE";
break;
case T_ExplainStmt:
tag = "EXPLAIN";
break;
case T_VariableSetStmt:
switch (((VariableSetStmt *) parsetree)->kind)
{
case VAR_SET_VALUE:
case VAR_SET_CURRENT:
case VAR_SET_DEFAULT:
case VAR_SET_MULTI:
tag = "SET";
break;
case VAR_RESET:
case VAR_RESET_ALL:
tag = "RESET";
break;
default:
tag = "???";
}
break;
case T_VariableShowStmt:
tag = "SHOW";
break;
case T_DiscardStmt:
switch (((DiscardStmt *) parsetree)->target)
{
case DISCARD_ALL:
tag = "DISCARD ALL";
break;
case DISCARD_PLANS:
tag = "DISCARD PLANS";
break;
case DISCARD_TEMP:
tag = "DISCARD TEMP";
break;
default:
tag = "???";
}
break;
case T_CreateTrigStmt:
tag = "CREATE TRIGGER";
break;
case T_DropPropertyStmt:
switch (((DropPropertyStmt *) parsetree)->removeType)
{
2003-06-27 16:45:32 +02:00
case OBJECT_TRIGGER:
tag = "DROP TRIGGER";
break;
2003-06-27 16:45:32 +02:00
case OBJECT_RULE:
tag = "DROP RULE";
break;
default:
tag = "???";
}
break;
case T_CreatePLangStmt:
tag = "CREATE LANGUAGE";
break;
case T_DropPLangStmt:
tag = "DROP LANGUAGE";
break;
case T_CreateRoleStmt:
tag = "CREATE ROLE";
break;
case T_AlterRoleStmt:
tag = "ALTER ROLE";
break;
case T_AlterRoleSetStmt:
tag = "ALTER ROLE";
break;
case T_DropRoleStmt:
tag = "DROP ROLE";
break;
case T_DropOwnedStmt:
tag = "DROP OWNED";
break;
case T_ReassignOwnedStmt:
tag = "REASSIGN OWNED";
break;
case T_LockStmt:
tag = "LOCK TABLE";
break;
case T_ConstraintsSetStmt:
tag = "SET CONSTRAINTS";
break;
case T_CheckPointStmt:
tag = "CHECKPOINT";
break;
case T_ReindexStmt:
tag = "REINDEX";
break;
case T_CreateConversionStmt:
tag = "CREATE CONVERSION";
break;
case T_CreateCastStmt:
tag = "CREATE CAST";
break;
case T_DropCastStmt:
tag = "DROP CAST";
break;
case T_CreateOpClassStmt:
tag = "CREATE OPERATOR CLASS";
break;
case T_CreateOpFamilyStmt:
tag = "CREATE OPERATOR FAMILY";
break;
case T_AlterOpFamilyStmt:
tag = "ALTER OPERATOR FAMILY";
break;
case T_RemoveOpClassStmt:
tag = "DROP OPERATOR CLASS";
break;
case T_RemoveOpFamilyStmt:
tag = "DROP OPERATOR FAMILY";
break;
case T_AlterTSDictionaryStmt:
tag = "ALTER TEXT SEARCH DICTIONARY";
break;
case T_AlterTSConfigurationStmt:
tag = "ALTER TEXT SEARCH CONFIGURATION";
break;
case T_PrepareStmt:
tag = "PREPARE";
break;
case T_ExecuteStmt:
tag = "EXECUTE";
break;
case T_DeallocateStmt:
{
DeallocateStmt *stmt = (DeallocateStmt *) parsetree;
if (stmt->name == NULL)
tag = "DEALLOCATE ALL";
else
tag = "DEALLOCATE";
}
break;
/* already-planned queries */
case T_PlannedStmt:
{
PlannedStmt *stmt = (PlannedStmt *) parsetree;
Clean up logging for extended-query-protocol operations, as per my recent proposal. Parameter logging works even for binary-format parameters, and logging overhead is avoided when disabled. log_statement = all output for the src/test/examples/testlibpq3.c example now looks like LOG: statement: execute <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: statement: execute <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' and log_min_duration_statement = 0 results in LOG: duration: 2.431 ms parse <unnamed>: SELECT * FROM test1 WHERE t = $1 LOG: duration: 2.335 ms bind <unnamed> to <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: duration: 0.394 ms execute <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: duration: 1.251 ms parse <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 LOG: duration: 0.566 ms bind <unnamed> to <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' LOG: duration: 0.173 ms execute <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' (This example demonstrates the folly of ignoring parse/bind steps for duration logging purposes, BTW.) Along the way, create a less ad-hoc mechanism for determining which commands are logged by log_statement = mod and log_statement = ddl. The former coding was actually missing quite a few things that look like ddl to me, and it did not handle EXECUTE or extended query protocol correctly at all. This commit does not do anything about the question of whether log_duration should be removed or made less redundant with log_min_duration_statement.
2006-09-08 00:52:01 +02:00
switch (stmt->commandType)
{
case CMD_SELECT:
/*
* We take a little extra care here so that the result
* will be useful for complaints about read-only
* statements
*/
if (stmt->utilityStmt != NULL)
{
Assert(IsA(stmt->utilityStmt, DeclareCursorStmt));
tag = "DECLARE CURSOR";
}
else if (stmt->intoClause != NULL)
tag = "SELECT INTO";
else if (stmt->rowMarks != NIL)
{
if (((RowMarkClause *) linitial(stmt->rowMarks))->forUpdate)
tag = "SELECT FOR UPDATE";
else
tag = "SELECT FOR SHARE";
}
else
tag = "SELECT";
break;
case CMD_UPDATE:
tag = "UPDATE";
break;
case CMD_INSERT:
tag = "INSERT";
break;
case CMD_DELETE:
tag = "DELETE";
break;
default:
elog(WARNING, "unrecognized commandType: %d",
(int) stmt->commandType);
tag = "???";
break;
}
}
break;
2005-10-15 04:49:52 +02:00
/* parsed-and-rewritten-but-not-planned queries */
case T_Query:
{
Query *stmt = (Query *) parsetree;
switch (stmt->commandType)
{
case CMD_SELECT:
/*
* We take a little extra care here so that the result
* will be useful for complaints about read-only
* statements
*/
if (stmt->utilityStmt != NULL)
{
Assert(IsA(stmt->utilityStmt, DeclareCursorStmt));
tag = "DECLARE CURSOR";
}
else if (stmt->intoClause != NULL)
tag = "SELECT INTO";
else if (stmt->rowMarks != NIL)
{
if (((RowMarkClause *) linitial(stmt->rowMarks))->forUpdate)
tag = "SELECT FOR UPDATE";
else
tag = "SELECT FOR SHARE";
}
else
tag = "SELECT";
break;
case CMD_UPDATE:
tag = "UPDATE";
break;
case CMD_INSERT:
tag = "INSERT";
break;
case CMD_DELETE:
tag = "DELETE";
break;
case CMD_UTILITY:
tag = CreateCommandTag(stmt->utilityStmt);
break;
default:
elog(WARNING, "unrecognized commandType: %d",
(int) stmt->commandType);
tag = "???";
break;
}
}
break;
default:
elog(WARNING, "unrecognized node type: %d",
(int) nodeTag(parsetree));
tag = "???";
break;
}
return tag;
}
Clean up logging for extended-query-protocol operations, as per my recent proposal. Parameter logging works even for binary-format parameters, and logging overhead is avoided when disabled. log_statement = all output for the src/test/examples/testlibpq3.c example now looks like LOG: statement: execute <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: statement: execute <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' and log_min_duration_statement = 0 results in LOG: duration: 2.431 ms parse <unnamed>: SELECT * FROM test1 WHERE t = $1 LOG: duration: 2.335 ms bind <unnamed> to <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: duration: 0.394 ms execute <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: duration: 1.251 ms parse <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 LOG: duration: 0.566 ms bind <unnamed> to <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' LOG: duration: 0.173 ms execute <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' (This example demonstrates the folly of ignoring parse/bind steps for duration logging purposes, BTW.) Along the way, create a less ad-hoc mechanism for determining which commands are logged by log_statement = mod and log_statement = ddl. The former coding was actually missing quite a few things that look like ddl to me, and it did not handle EXECUTE or extended query protocol correctly at all. This commit does not do anything about the question of whether log_duration should be removed or made less redundant with log_min_duration_statement.
2006-09-08 00:52:01 +02:00
/*
* GetCommandLogLevel
* utility to get the minimum log_statement level for a command,
* given either a raw (un-analyzed) parsetree or a planned query.
Clean up logging for extended-query-protocol operations, as per my recent proposal. Parameter logging works even for binary-format parameters, and logging overhead is avoided when disabled. log_statement = all output for the src/test/examples/testlibpq3.c example now looks like LOG: statement: execute <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: statement: execute <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' and log_min_duration_statement = 0 results in LOG: duration: 2.431 ms parse <unnamed>: SELECT * FROM test1 WHERE t = $1 LOG: duration: 2.335 ms bind <unnamed> to <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: duration: 0.394 ms execute <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: duration: 1.251 ms parse <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 LOG: duration: 0.566 ms bind <unnamed> to <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' LOG: duration: 0.173 ms execute <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' (This example demonstrates the folly of ignoring parse/bind steps for duration logging purposes, BTW.) Along the way, create a less ad-hoc mechanism for determining which commands are logged by log_statement = mod and log_statement = ddl. The former coding was actually missing quite a few things that look like ddl to me, and it did not handle EXECUTE or extended query protocol correctly at all. This commit does not do anything about the question of whether log_duration should be removed or made less redundant with log_min_duration_statement.
2006-09-08 00:52:01 +02:00
*
* This must handle all command types, but since the vast majority
Clean up logging for extended-query-protocol operations, as per my recent proposal. Parameter logging works even for binary-format parameters, and logging overhead is avoided when disabled. log_statement = all output for the src/test/examples/testlibpq3.c example now looks like LOG: statement: execute <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: statement: execute <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' and log_min_duration_statement = 0 results in LOG: duration: 2.431 ms parse <unnamed>: SELECT * FROM test1 WHERE t = $1 LOG: duration: 2.335 ms bind <unnamed> to <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: duration: 0.394 ms execute <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: duration: 1.251 ms parse <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 LOG: duration: 0.566 ms bind <unnamed> to <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' LOG: duration: 0.173 ms execute <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' (This example demonstrates the folly of ignoring parse/bind steps for duration logging purposes, BTW.) Along the way, create a less ad-hoc mechanism for determining which commands are logged by log_statement = mod and log_statement = ddl. The former coding was actually missing quite a few things that look like ddl to me, and it did not handle EXECUTE or extended query protocol correctly at all. This commit does not do anything about the question of whether log_duration should be removed or made less redundant with log_min_duration_statement.
2006-09-08 00:52:01 +02:00
* of 'em are utility commands, it seems sensible to keep it here.
*/
LogStmtLevel
GetCommandLogLevel(Node *parsetree)
{
LogStmtLevel lev;
switch (nodeTag(parsetree))
{
/* raw plannable queries */
Clean up logging for extended-query-protocol operations, as per my recent proposal. Parameter logging works even for binary-format parameters, and logging overhead is avoided when disabled. log_statement = all output for the src/test/examples/testlibpq3.c example now looks like LOG: statement: execute <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: statement: execute <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' and log_min_duration_statement = 0 results in LOG: duration: 2.431 ms parse <unnamed>: SELECT * FROM test1 WHERE t = $1 LOG: duration: 2.335 ms bind <unnamed> to <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: duration: 0.394 ms execute <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: duration: 1.251 ms parse <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 LOG: duration: 0.566 ms bind <unnamed> to <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' LOG: duration: 0.173 ms execute <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' (This example demonstrates the folly of ignoring parse/bind steps for duration logging purposes, BTW.) Along the way, create a less ad-hoc mechanism for determining which commands are logged by log_statement = mod and log_statement = ddl. The former coding was actually missing quite a few things that look like ddl to me, and it did not handle EXECUTE or extended query protocol correctly at all. This commit does not do anything about the question of whether log_duration should be removed or made less redundant with log_min_duration_statement.
2006-09-08 00:52:01 +02:00
case T_InsertStmt:
case T_DeleteStmt:
case T_UpdateStmt:
lev = LOGSTMT_MOD;
break;
case T_SelectStmt:
if (((SelectStmt *) parsetree)->intoClause)
2006-10-04 02:30:14 +02:00
lev = LOGSTMT_DDL; /* CREATE AS, SELECT INTO */
Clean up logging for extended-query-protocol operations, as per my recent proposal. Parameter logging works even for binary-format parameters, and logging overhead is avoided when disabled. log_statement = all output for the src/test/examples/testlibpq3.c example now looks like LOG: statement: execute <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: statement: execute <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' and log_min_duration_statement = 0 results in LOG: duration: 2.431 ms parse <unnamed>: SELECT * FROM test1 WHERE t = $1 LOG: duration: 2.335 ms bind <unnamed> to <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: duration: 0.394 ms execute <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: duration: 1.251 ms parse <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 LOG: duration: 0.566 ms bind <unnamed> to <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' LOG: duration: 0.173 ms execute <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' (This example demonstrates the folly of ignoring parse/bind steps for duration logging purposes, BTW.) Along the way, create a less ad-hoc mechanism for determining which commands are logged by log_statement = mod and log_statement = ddl. The former coding was actually missing quite a few things that look like ddl to me, and it did not handle EXECUTE or extended query protocol correctly at all. This commit does not do anything about the question of whether log_duration should be removed or made less redundant with log_min_duration_statement.
2006-09-08 00:52:01 +02:00
else
lev = LOGSTMT_ALL;
break;
/* utility statements --- same whether raw or cooked */
Clean up logging for extended-query-protocol operations, as per my recent proposal. Parameter logging works even for binary-format parameters, and logging overhead is avoided when disabled. log_statement = all output for the src/test/examples/testlibpq3.c example now looks like LOG: statement: execute <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: statement: execute <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' and log_min_duration_statement = 0 results in LOG: duration: 2.431 ms parse <unnamed>: SELECT * FROM test1 WHERE t = $1 LOG: duration: 2.335 ms bind <unnamed> to <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: duration: 0.394 ms execute <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: duration: 1.251 ms parse <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 LOG: duration: 0.566 ms bind <unnamed> to <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' LOG: duration: 0.173 ms execute <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' (This example demonstrates the folly of ignoring parse/bind steps for duration logging purposes, BTW.) Along the way, create a less ad-hoc mechanism for determining which commands are logged by log_statement = mod and log_statement = ddl. The former coding was actually missing quite a few things that look like ddl to me, and it did not handle EXECUTE or extended query protocol correctly at all. This commit does not do anything about the question of whether log_duration should be removed or made less redundant with log_min_duration_statement.
2006-09-08 00:52:01 +02:00
case T_TransactionStmt:
lev = LOGSTMT_ALL;
break;
case T_DeclareCursorStmt:
lev = LOGSTMT_ALL;
break;
case T_ClosePortalStmt:
lev = LOGSTMT_ALL;
break;
case T_FetchStmt:
lev = LOGSTMT_ALL;
break;
case T_CreateDomainStmt:
lev = LOGSTMT_DDL;
break;
case T_CreateSchemaStmt:
lev = LOGSTMT_DDL;
break;
case T_CreateStmt:
lev = LOGSTMT_DDL;
break;
case T_CreateTableSpaceStmt:
lev = LOGSTMT_DDL;
break;
case T_DropTableSpaceStmt:
lev = LOGSTMT_DDL;
break;
case T_DropStmt:
lev = LOGSTMT_DDL;
break;
case T_TruncateStmt:
lev = LOGSTMT_MOD;
break;
case T_CommentStmt:
lev = LOGSTMT_DDL;
break;
case T_CopyStmt:
if (((CopyStmt *) parsetree)->is_from)
lev = LOGSTMT_MOD;
else
lev = LOGSTMT_ALL;
break;
case T_RenameStmt:
lev = LOGSTMT_DDL;
break;
case T_AlterObjectSchemaStmt:
lev = LOGSTMT_DDL;
break;
case T_AlterOwnerStmt:
lev = LOGSTMT_DDL;
break;
case T_AlterTableStmt:
lev = LOGSTMT_DDL;
break;
case T_AlterDomainStmt:
lev = LOGSTMT_DDL;
break;
case T_AlterFunctionStmt:
lev = LOGSTMT_DDL;
break;
case T_GrantStmt:
lev = LOGSTMT_DDL;
break;
case T_GrantRoleStmt:
lev = LOGSTMT_DDL;
break;
case T_DefineStmt:
lev = LOGSTMT_DDL;
break;
case T_CompositeTypeStmt:
lev = LOGSTMT_DDL;
break;
case T_CreateEnumStmt:
lev = LOGSTMT_DDL;
break;
Clean up logging for extended-query-protocol operations, as per my recent proposal. Parameter logging works even for binary-format parameters, and logging overhead is avoided when disabled. log_statement = all output for the src/test/examples/testlibpq3.c example now looks like LOG: statement: execute <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: statement: execute <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' and log_min_duration_statement = 0 results in LOG: duration: 2.431 ms parse <unnamed>: SELECT * FROM test1 WHERE t = $1 LOG: duration: 2.335 ms bind <unnamed> to <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: duration: 0.394 ms execute <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: duration: 1.251 ms parse <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 LOG: duration: 0.566 ms bind <unnamed> to <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' LOG: duration: 0.173 ms execute <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' (This example demonstrates the folly of ignoring parse/bind steps for duration logging purposes, BTW.) Along the way, create a less ad-hoc mechanism for determining which commands are logged by log_statement = mod and log_statement = ddl. The former coding was actually missing quite a few things that look like ddl to me, and it did not handle EXECUTE or extended query protocol correctly at all. This commit does not do anything about the question of whether log_duration should be removed or made less redundant with log_min_duration_statement.
2006-09-08 00:52:01 +02:00
case T_ViewStmt:
lev = LOGSTMT_DDL;
break;
case T_CreateFunctionStmt:
lev = LOGSTMT_DDL;
break;
case T_IndexStmt:
lev = LOGSTMT_DDL;
break;
case T_RuleStmt:
lev = LOGSTMT_DDL;
break;
case T_CreateSeqStmt:
lev = LOGSTMT_DDL;
break;
case T_AlterSeqStmt:
lev = LOGSTMT_DDL;
break;
case T_RemoveFuncStmt:
lev = LOGSTMT_DDL;
break;
case T_CreatedbStmt:
lev = LOGSTMT_DDL;
break;
case T_AlterDatabaseStmt:
lev = LOGSTMT_DDL;
break;
case T_AlterDatabaseSetStmt:
lev = LOGSTMT_DDL;
break;
case T_DropdbStmt:
lev = LOGSTMT_DDL;
break;
case T_NotifyStmt:
lev = LOGSTMT_ALL;
break;
case T_ListenStmt:
lev = LOGSTMT_ALL;
break;
case T_UnlistenStmt:
lev = LOGSTMT_ALL;
break;
case T_LoadStmt:
lev = LOGSTMT_ALL;
break;
case T_ClusterStmt:
lev = LOGSTMT_DDL;
break;
case T_VacuumStmt:
lev = LOGSTMT_ALL;
break;
case T_ExplainStmt:
{
2006-10-04 02:30:14 +02:00
ExplainStmt *stmt = (ExplainStmt *) parsetree;
Clean up logging for extended-query-protocol operations, as per my recent proposal. Parameter logging works even for binary-format parameters, and logging overhead is avoided when disabled. log_statement = all output for the src/test/examples/testlibpq3.c example now looks like LOG: statement: execute <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: statement: execute <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' and log_min_duration_statement = 0 results in LOG: duration: 2.431 ms parse <unnamed>: SELECT * FROM test1 WHERE t = $1 LOG: duration: 2.335 ms bind <unnamed> to <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: duration: 0.394 ms execute <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: duration: 1.251 ms parse <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 LOG: duration: 0.566 ms bind <unnamed> to <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' LOG: duration: 0.173 ms execute <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' (This example demonstrates the folly of ignoring parse/bind steps for duration logging purposes, BTW.) Along the way, create a less ad-hoc mechanism for determining which commands are logged by log_statement = mod and log_statement = ddl. The former coding was actually missing quite a few things that look like ddl to me, and it did not handle EXECUTE or extended query protocol correctly at all. This commit does not do anything about the question of whether log_duration should be removed or made less redundant with log_min_duration_statement.
2006-09-08 00:52:01 +02:00
/* Look through an EXPLAIN ANALYZE to the contained stmt */
if (stmt->analyze)
return GetCommandLogLevel(stmt->query);
Clean up logging for extended-query-protocol operations, as per my recent proposal. Parameter logging works even for binary-format parameters, and logging overhead is avoided when disabled. log_statement = all output for the src/test/examples/testlibpq3.c example now looks like LOG: statement: execute <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: statement: execute <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' and log_min_duration_statement = 0 results in LOG: duration: 2.431 ms parse <unnamed>: SELECT * FROM test1 WHERE t = $1 LOG: duration: 2.335 ms bind <unnamed> to <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: duration: 0.394 ms execute <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: duration: 1.251 ms parse <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 LOG: duration: 0.566 ms bind <unnamed> to <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' LOG: duration: 0.173 ms execute <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' (This example demonstrates the folly of ignoring parse/bind steps for duration logging purposes, BTW.) Along the way, create a less ad-hoc mechanism for determining which commands are logged by log_statement = mod and log_statement = ddl. The former coding was actually missing quite a few things that look like ddl to me, and it did not handle EXECUTE or extended query protocol correctly at all. This commit does not do anything about the question of whether log_duration should be removed or made less redundant with log_min_duration_statement.
2006-09-08 00:52:01 +02:00
/* Plain EXPLAIN isn't so interesting */
lev = LOGSTMT_ALL;
}
break;
case T_VariableSetStmt:
lev = LOGSTMT_ALL;
break;
case T_VariableShowStmt:
lev = LOGSTMT_ALL;
break;
case T_CreateTrigStmt:
lev = LOGSTMT_DDL;
break;
case T_DropPropertyStmt:
lev = LOGSTMT_DDL;
break;
case T_CreatePLangStmt:
lev = LOGSTMT_DDL;
break;
case T_DropPLangStmt:
lev = LOGSTMT_DDL;
break;
case T_CreateRoleStmt:
lev = LOGSTMT_DDL;
break;
case T_AlterRoleStmt:
lev = LOGSTMT_DDL;
break;
case T_AlterRoleSetStmt:
lev = LOGSTMT_DDL;
break;
case T_DropRoleStmt:
lev = LOGSTMT_DDL;
break;
case T_DropOwnedStmt:
lev = LOGSTMT_DDL;
break;
case T_ReassignOwnedStmt:
lev = LOGSTMT_DDL;
break;
case T_LockStmt:
lev = LOGSTMT_ALL;
break;
case T_ConstraintsSetStmt:
lev = LOGSTMT_ALL;
break;
case T_CheckPointStmt:
lev = LOGSTMT_ALL;
break;
case T_ReindexStmt:
2006-10-04 02:30:14 +02:00
lev = LOGSTMT_ALL; /* should this be DDL? */
Clean up logging for extended-query-protocol operations, as per my recent proposal. Parameter logging works even for binary-format parameters, and logging overhead is avoided when disabled. log_statement = all output for the src/test/examples/testlibpq3.c example now looks like LOG: statement: execute <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: statement: execute <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' and log_min_duration_statement = 0 results in LOG: duration: 2.431 ms parse <unnamed>: SELECT * FROM test1 WHERE t = $1 LOG: duration: 2.335 ms bind <unnamed> to <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: duration: 0.394 ms execute <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: duration: 1.251 ms parse <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 LOG: duration: 0.566 ms bind <unnamed> to <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' LOG: duration: 0.173 ms execute <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' (This example demonstrates the folly of ignoring parse/bind steps for duration logging purposes, BTW.) Along the way, create a less ad-hoc mechanism for determining which commands are logged by log_statement = mod and log_statement = ddl. The former coding was actually missing quite a few things that look like ddl to me, and it did not handle EXECUTE or extended query protocol correctly at all. This commit does not do anything about the question of whether log_duration should be removed or made less redundant with log_min_duration_statement.
2006-09-08 00:52:01 +02:00
break;
case T_CreateConversionStmt:
lev = LOGSTMT_DDL;
break;
case T_CreateCastStmt:
lev = LOGSTMT_DDL;
break;
case T_DropCastStmt:
lev = LOGSTMT_DDL;
break;
case T_CreateOpClassStmt:
lev = LOGSTMT_DDL;
break;
case T_CreateOpFamilyStmt:
lev = LOGSTMT_DDL;
break;
case T_AlterOpFamilyStmt:
lev = LOGSTMT_DDL;
break;
Clean up logging for extended-query-protocol operations, as per my recent proposal. Parameter logging works even for binary-format parameters, and logging overhead is avoided when disabled. log_statement = all output for the src/test/examples/testlibpq3.c example now looks like LOG: statement: execute <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: statement: execute <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' and log_min_duration_statement = 0 results in LOG: duration: 2.431 ms parse <unnamed>: SELECT * FROM test1 WHERE t = $1 LOG: duration: 2.335 ms bind <unnamed> to <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: duration: 0.394 ms execute <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: duration: 1.251 ms parse <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 LOG: duration: 0.566 ms bind <unnamed> to <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' LOG: duration: 0.173 ms execute <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' (This example demonstrates the folly of ignoring parse/bind steps for duration logging purposes, BTW.) Along the way, create a less ad-hoc mechanism for determining which commands are logged by log_statement = mod and log_statement = ddl. The former coding was actually missing quite a few things that look like ddl to me, and it did not handle EXECUTE or extended query protocol correctly at all. This commit does not do anything about the question of whether log_duration should be removed or made less redundant with log_min_duration_statement.
2006-09-08 00:52:01 +02:00
case T_RemoveOpClassStmt:
lev = LOGSTMT_DDL;
break;
case T_RemoveOpFamilyStmt:
lev = LOGSTMT_DDL;
Clean up logging for extended-query-protocol operations, as per my recent proposal. Parameter logging works even for binary-format parameters, and logging overhead is avoided when disabled. log_statement = all output for the src/test/examples/testlibpq3.c example now looks like LOG: statement: execute <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: statement: execute <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' and log_min_duration_statement = 0 results in LOG: duration: 2.431 ms parse <unnamed>: SELECT * FROM test1 WHERE t = $1 LOG: duration: 2.335 ms bind <unnamed> to <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: duration: 0.394 ms execute <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: duration: 1.251 ms parse <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 LOG: duration: 0.566 ms bind <unnamed> to <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' LOG: duration: 0.173 ms execute <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' (This example demonstrates the folly of ignoring parse/bind steps for duration logging purposes, BTW.) Along the way, create a less ad-hoc mechanism for determining which commands are logged by log_statement = mod and log_statement = ddl. The former coding was actually missing quite a few things that look like ddl to me, and it did not handle EXECUTE or extended query protocol correctly at all. This commit does not do anything about the question of whether log_duration should be removed or made less redundant with log_min_duration_statement.
2006-09-08 00:52:01 +02:00
break;
case T_AlterTSDictionaryStmt:
lev = LOGSTMT_DDL;
break;
case T_AlterTSConfigurationStmt:
lev = LOGSTMT_DDL;
break;
Clean up logging for extended-query-protocol operations, as per my recent proposal. Parameter logging works even for binary-format parameters, and logging overhead is avoided when disabled. log_statement = all output for the src/test/examples/testlibpq3.c example now looks like LOG: statement: execute <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: statement: execute <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' and log_min_duration_statement = 0 results in LOG: duration: 2.431 ms parse <unnamed>: SELECT * FROM test1 WHERE t = $1 LOG: duration: 2.335 ms bind <unnamed> to <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: duration: 0.394 ms execute <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: duration: 1.251 ms parse <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 LOG: duration: 0.566 ms bind <unnamed> to <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' LOG: duration: 0.173 ms execute <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' (This example demonstrates the folly of ignoring parse/bind steps for duration logging purposes, BTW.) Along the way, create a less ad-hoc mechanism for determining which commands are logged by log_statement = mod and log_statement = ddl. The former coding was actually missing quite a few things that look like ddl to me, and it did not handle EXECUTE or extended query protocol correctly at all. This commit does not do anything about the question of whether log_duration should be removed or made less redundant with log_min_duration_statement.
2006-09-08 00:52:01 +02:00
case T_PrepareStmt:
{
2006-10-04 02:30:14 +02:00
PrepareStmt *stmt = (PrepareStmt *) parsetree;
Clean up logging for extended-query-protocol operations, as per my recent proposal. Parameter logging works even for binary-format parameters, and logging overhead is avoided when disabled. log_statement = all output for the src/test/examples/testlibpq3.c example now looks like LOG: statement: execute <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: statement: execute <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' and log_min_duration_statement = 0 results in LOG: duration: 2.431 ms parse <unnamed>: SELECT * FROM test1 WHERE t = $1 LOG: duration: 2.335 ms bind <unnamed> to <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: duration: 0.394 ms execute <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: duration: 1.251 ms parse <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 LOG: duration: 0.566 ms bind <unnamed> to <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' LOG: duration: 0.173 ms execute <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' (This example demonstrates the folly of ignoring parse/bind steps for duration logging purposes, BTW.) Along the way, create a less ad-hoc mechanism for determining which commands are logged by log_statement = mod and log_statement = ddl. The former coding was actually missing quite a few things that look like ddl to me, and it did not handle EXECUTE or extended query protocol correctly at all. This commit does not do anything about the question of whether log_duration should be removed or made less redundant with log_min_duration_statement.
2006-09-08 00:52:01 +02:00
/* Look through a PREPARE to the contained stmt */
lev = GetCommandLogLevel(stmt->query);
Clean up logging for extended-query-protocol operations, as per my recent proposal. Parameter logging works even for binary-format parameters, and logging overhead is avoided when disabled. log_statement = all output for the src/test/examples/testlibpq3.c example now looks like LOG: statement: execute <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: statement: execute <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' and log_min_duration_statement = 0 results in LOG: duration: 2.431 ms parse <unnamed>: SELECT * FROM test1 WHERE t = $1 LOG: duration: 2.335 ms bind <unnamed> to <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: duration: 0.394 ms execute <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: duration: 1.251 ms parse <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 LOG: duration: 0.566 ms bind <unnamed> to <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' LOG: duration: 0.173 ms execute <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' (This example demonstrates the folly of ignoring parse/bind steps for duration logging purposes, BTW.) Along the way, create a less ad-hoc mechanism for determining which commands are logged by log_statement = mod and log_statement = ddl. The former coding was actually missing quite a few things that look like ddl to me, and it did not handle EXECUTE or extended query protocol correctly at all. This commit does not do anything about the question of whether log_duration should be removed or made less redundant with log_min_duration_statement.
2006-09-08 00:52:01 +02:00
}
break;
case T_ExecuteStmt:
{
2006-10-04 02:30:14 +02:00
ExecuteStmt *stmt = (ExecuteStmt *) parsetree;
PreparedStatement *ps;
Clean up logging for extended-query-protocol operations, as per my recent proposal. Parameter logging works even for binary-format parameters, and logging overhead is avoided when disabled. log_statement = all output for the src/test/examples/testlibpq3.c example now looks like LOG: statement: execute <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: statement: execute <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' and log_min_duration_statement = 0 results in LOG: duration: 2.431 ms parse <unnamed>: SELECT * FROM test1 WHERE t = $1 LOG: duration: 2.335 ms bind <unnamed> to <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: duration: 0.394 ms execute <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: duration: 1.251 ms parse <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 LOG: duration: 0.566 ms bind <unnamed> to <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' LOG: duration: 0.173 ms execute <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' (This example demonstrates the folly of ignoring parse/bind steps for duration logging purposes, BTW.) Along the way, create a less ad-hoc mechanism for determining which commands are logged by log_statement = mod and log_statement = ddl. The former coding was actually missing quite a few things that look like ddl to me, and it did not handle EXECUTE or extended query protocol correctly at all. This commit does not do anything about the question of whether log_duration should be removed or made less redundant with log_min_duration_statement.
2006-09-08 00:52:01 +02:00
/* Look through an EXECUTE to the referenced stmt */
ps = FetchPreparedStatement(stmt->name, false);
if (ps)
lev = GetCommandLogLevel(ps->plansource->raw_parse_tree);
else
lev = LOGSTMT_ALL;
Clean up logging for extended-query-protocol operations, as per my recent proposal. Parameter logging works even for binary-format parameters, and logging overhead is avoided when disabled. log_statement = all output for the src/test/examples/testlibpq3.c example now looks like LOG: statement: execute <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: statement: execute <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' and log_min_duration_statement = 0 results in LOG: duration: 2.431 ms parse <unnamed>: SELECT * FROM test1 WHERE t = $1 LOG: duration: 2.335 ms bind <unnamed> to <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: duration: 0.394 ms execute <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: duration: 1.251 ms parse <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 LOG: duration: 0.566 ms bind <unnamed> to <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' LOG: duration: 0.173 ms execute <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' (This example demonstrates the folly of ignoring parse/bind steps for duration logging purposes, BTW.) Along the way, create a less ad-hoc mechanism for determining which commands are logged by log_statement = mod and log_statement = ddl. The former coding was actually missing quite a few things that look like ddl to me, and it did not handle EXECUTE or extended query protocol correctly at all. This commit does not do anything about the question of whether log_duration should be removed or made less redundant with log_min_duration_statement.
2006-09-08 00:52:01 +02:00
}
break;
case T_DeallocateStmt:
lev = LOGSTMT_ALL;
break;
/* already-planned queries */
case T_PlannedStmt:
{
PlannedStmt *stmt = (PlannedStmt *) parsetree;
2006-10-04 02:30:14 +02:00
switch (stmt->commandType)
{
case CMD_SELECT:
if (stmt->intoClause != NULL)
lev = LOGSTMT_DDL; /* CREATE AS, SELECT INTO */
else
lev = LOGSTMT_ALL; /* SELECT or DECLARE CURSOR */
break;
Clean up logging for extended-query-protocol operations, as per my recent proposal. Parameter logging works even for binary-format parameters, and logging overhead is avoided when disabled. log_statement = all output for the src/test/examples/testlibpq3.c example now looks like LOG: statement: execute <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: statement: execute <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' and log_min_duration_statement = 0 results in LOG: duration: 2.431 ms parse <unnamed>: SELECT * FROM test1 WHERE t = $1 LOG: duration: 2.335 ms bind <unnamed> to <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: duration: 0.394 ms execute <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: duration: 1.251 ms parse <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 LOG: duration: 0.566 ms bind <unnamed> to <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' LOG: duration: 0.173 ms execute <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' (This example demonstrates the folly of ignoring parse/bind steps for duration logging purposes, BTW.) Along the way, create a less ad-hoc mechanism for determining which commands are logged by log_statement = mod and log_statement = ddl. The former coding was actually missing quite a few things that look like ddl to me, and it did not handle EXECUTE or extended query protocol correctly at all. This commit does not do anything about the question of whether log_duration should be removed or made less redundant with log_min_duration_statement.
2006-09-08 00:52:01 +02:00
case CMD_UPDATE:
case CMD_INSERT:
case CMD_DELETE:
lev = LOGSTMT_MOD;
break;
default:
elog(WARNING, "unrecognized commandType: %d",
(int) stmt->commandType);
lev = LOGSTMT_ALL;
break;
}
}
Clean up logging for extended-query-protocol operations, as per my recent proposal. Parameter logging works even for binary-format parameters, and logging overhead is avoided when disabled. log_statement = all output for the src/test/examples/testlibpq3.c example now looks like LOG: statement: execute <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: statement: execute <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' and log_min_duration_statement = 0 results in LOG: duration: 2.431 ms parse <unnamed>: SELECT * FROM test1 WHERE t = $1 LOG: duration: 2.335 ms bind <unnamed> to <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: duration: 0.394 ms execute <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: duration: 1.251 ms parse <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 LOG: duration: 0.566 ms bind <unnamed> to <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' LOG: duration: 0.173 ms execute <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' (This example demonstrates the folly of ignoring parse/bind steps for duration logging purposes, BTW.) Along the way, create a less ad-hoc mechanism for determining which commands are logged by log_statement = mod and log_statement = ddl. The former coding was actually missing quite a few things that look like ddl to me, and it did not handle EXECUTE or extended query protocol correctly at all. This commit does not do anything about the question of whether log_duration should be removed or made less redundant with log_min_duration_statement.
2006-09-08 00:52:01 +02:00
break;
/* parsed-and-rewritten-but-not-planned queries */
case T_Query:
{
Query *stmt = (Query *) parsetree;
Clean up logging for extended-query-protocol operations, as per my recent proposal. Parameter logging works even for binary-format parameters, and logging overhead is avoided when disabled. log_statement = all output for the src/test/examples/testlibpq3.c example now looks like LOG: statement: execute <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: statement: execute <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' and log_min_duration_statement = 0 results in LOG: duration: 2.431 ms parse <unnamed>: SELECT * FROM test1 WHERE t = $1 LOG: duration: 2.335 ms bind <unnamed> to <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: duration: 0.394 ms execute <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: duration: 1.251 ms parse <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 LOG: duration: 0.566 ms bind <unnamed> to <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' LOG: duration: 0.173 ms execute <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' (This example demonstrates the folly of ignoring parse/bind steps for duration logging purposes, BTW.) Along the way, create a less ad-hoc mechanism for determining which commands are logged by log_statement = mod and log_statement = ddl. The former coding was actually missing quite a few things that look like ddl to me, and it did not handle EXECUTE or extended query protocol correctly at all. This commit does not do anything about the question of whether log_duration should be removed or made less redundant with log_min_duration_statement.
2006-09-08 00:52:01 +02:00
switch (stmt->commandType)
{
case CMD_SELECT:
if (stmt->intoClause != NULL)
lev = LOGSTMT_DDL; /* CREATE AS, SELECT INTO */
else
lev = LOGSTMT_ALL; /* SELECT or DECLARE CURSOR */
break;
Clean up logging for extended-query-protocol operations, as per my recent proposal. Parameter logging works even for binary-format parameters, and logging overhead is avoided when disabled. log_statement = all output for the src/test/examples/testlibpq3.c example now looks like LOG: statement: execute <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: statement: execute <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' and log_min_duration_statement = 0 results in LOG: duration: 2.431 ms parse <unnamed>: SELECT * FROM test1 WHERE t = $1 LOG: duration: 2.335 ms bind <unnamed> to <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: duration: 0.394 ms execute <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: duration: 1.251 ms parse <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 LOG: duration: 0.566 ms bind <unnamed> to <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' LOG: duration: 0.173 ms execute <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' (This example demonstrates the folly of ignoring parse/bind steps for duration logging purposes, BTW.) Along the way, create a less ad-hoc mechanism for determining which commands are logged by log_statement = mod and log_statement = ddl. The former coding was actually missing quite a few things that look like ddl to me, and it did not handle EXECUTE or extended query protocol correctly at all. This commit does not do anything about the question of whether log_duration should be removed or made less redundant with log_min_duration_statement.
2006-09-08 00:52:01 +02:00
case CMD_UPDATE:
case CMD_INSERT:
case CMD_DELETE:
lev = LOGSTMT_MOD;
break;
Clean up logging for extended-query-protocol operations, as per my recent proposal. Parameter logging works even for binary-format parameters, and logging overhead is avoided when disabled. log_statement = all output for the src/test/examples/testlibpq3.c example now looks like LOG: statement: execute <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: statement: execute <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' and log_min_duration_statement = 0 results in LOG: duration: 2.431 ms parse <unnamed>: SELECT * FROM test1 WHERE t = $1 LOG: duration: 2.335 ms bind <unnamed> to <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: duration: 0.394 ms execute <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: duration: 1.251 ms parse <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 LOG: duration: 0.566 ms bind <unnamed> to <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' LOG: duration: 0.173 ms execute <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' (This example demonstrates the folly of ignoring parse/bind steps for duration logging purposes, BTW.) Along the way, create a less ad-hoc mechanism for determining which commands are logged by log_statement = mod and log_statement = ddl. The former coding was actually missing quite a few things that look like ddl to me, and it did not handle EXECUTE or extended query protocol correctly at all. This commit does not do anything about the question of whether log_duration should be removed or made less redundant with log_min_duration_statement.
2006-09-08 00:52:01 +02:00
case CMD_UTILITY:
lev = GetCommandLogLevel(stmt->utilityStmt);
break;
Clean up logging for extended-query-protocol operations, as per my recent proposal. Parameter logging works even for binary-format parameters, and logging overhead is avoided when disabled. log_statement = all output for the src/test/examples/testlibpq3.c example now looks like LOG: statement: execute <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: statement: execute <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' and log_min_duration_statement = 0 results in LOG: duration: 2.431 ms parse <unnamed>: SELECT * FROM test1 WHERE t = $1 LOG: duration: 2.335 ms bind <unnamed> to <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: duration: 0.394 ms execute <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: duration: 1.251 ms parse <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 LOG: duration: 0.566 ms bind <unnamed> to <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' LOG: duration: 0.173 ms execute <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' (This example demonstrates the folly of ignoring parse/bind steps for duration logging purposes, BTW.) Along the way, create a less ad-hoc mechanism for determining which commands are logged by log_statement = mod and log_statement = ddl. The former coding was actually missing quite a few things that look like ddl to me, and it did not handle EXECUTE or extended query protocol correctly at all. This commit does not do anything about the question of whether log_duration should be removed or made less redundant with log_min_duration_statement.
2006-09-08 00:52:01 +02:00
default:
elog(WARNING, "unrecognized commandType: %d",
(int) stmt->commandType);
lev = LOGSTMT_ALL;
break;
}
Clean up logging for extended-query-protocol operations, as per my recent proposal. Parameter logging works even for binary-format parameters, and logging overhead is avoided when disabled. log_statement = all output for the src/test/examples/testlibpq3.c example now looks like LOG: statement: execute <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: statement: execute <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' and log_min_duration_statement = 0 results in LOG: duration: 2.431 ms parse <unnamed>: SELECT * FROM test1 WHERE t = $1 LOG: duration: 2.335 ms bind <unnamed> to <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: duration: 0.394 ms execute <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: duration: 1.251 ms parse <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 LOG: duration: 0.566 ms bind <unnamed> to <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' LOG: duration: 0.173 ms execute <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' (This example demonstrates the folly of ignoring parse/bind steps for duration logging purposes, BTW.) Along the way, create a less ad-hoc mechanism for determining which commands are logged by log_statement = mod and log_statement = ddl. The former coding was actually missing quite a few things that look like ddl to me, and it did not handle EXECUTE or extended query protocol correctly at all. This commit does not do anything about the question of whether log_duration should be removed or made less redundant with log_min_duration_statement.
2006-09-08 00:52:01 +02:00
}
Clean up logging for extended-query-protocol operations, as per my recent proposal. Parameter logging works even for binary-format parameters, and logging overhead is avoided when disabled. log_statement = all output for the src/test/examples/testlibpq3.c example now looks like LOG: statement: execute <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: statement: execute <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' and log_min_duration_statement = 0 results in LOG: duration: 2.431 ms parse <unnamed>: SELECT * FROM test1 WHERE t = $1 LOG: duration: 2.335 ms bind <unnamed> to <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: duration: 0.394 ms execute <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: duration: 1.251 ms parse <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 LOG: duration: 0.566 ms bind <unnamed> to <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' LOG: duration: 0.173 ms execute <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' (This example demonstrates the folly of ignoring parse/bind steps for duration logging purposes, BTW.) Along the way, create a less ad-hoc mechanism for determining which commands are logged by log_statement = mod and log_statement = ddl. The former coding was actually missing quite a few things that look like ddl to me, and it did not handle EXECUTE or extended query protocol correctly at all. This commit does not do anything about the question of whether log_duration should be removed or made less redundant with log_min_duration_statement.
2006-09-08 00:52:01 +02:00
break;
default:
elog(WARNING, "unrecognized node type: %d",
(int) nodeTag(parsetree));
Clean up logging for extended-query-protocol operations, as per my recent proposal. Parameter logging works even for binary-format parameters, and logging overhead is avoided when disabled. log_statement = all output for the src/test/examples/testlibpq3.c example now looks like LOG: statement: execute <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: statement: execute <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' and log_min_duration_statement = 0 results in LOG: duration: 2.431 ms parse <unnamed>: SELECT * FROM test1 WHERE t = $1 LOG: duration: 2.335 ms bind <unnamed> to <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: duration: 0.394 ms execute <unnamed>: SELECT * FROM test1 WHERE t = $1 DETAIL: parameters: $1 = 'joe''s place' LOG: duration: 1.251 ms parse <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 LOG: duration: 0.566 ms bind <unnamed> to <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' LOG: duration: 0.173 ms execute <unnamed>: SELECT * FROM test1 WHERE i = $1::int4 DETAIL: parameters: $1 = '2' (This example demonstrates the folly of ignoring parse/bind steps for duration logging purposes, BTW.) Along the way, create a less ad-hoc mechanism for determining which commands are logged by log_statement = mod and log_statement = ddl. The former coding was actually missing quite a few things that look like ddl to me, and it did not handle EXECUTE or extended query protocol correctly at all. This commit does not do anything about the question of whether log_duration should be removed or made less redundant with log_min_duration_statement.
2006-09-08 00:52:01 +02:00
lev = LOGSTMT_ALL;
break;
}
return lev;
}