Re: ANALYZE command [REPOST] - Mailing list pgsql-patches

From Bruce Momjian
Subject Re: ANALYZE command [REPOST]
Date
Msg-id 200105082102.f48L2ck02282@candle.pha.pa.us
Whole thread Raw
In response to ANALYZE command [REPOST]  (Fernando Nasser <fnasser@cygnus.com>)
List pgsql-patches
Seems this has already been done by Tom Lane.  Thanks.

> [My apologies: I forgot to tell to which sources the patch
> applies, as required and, which is worse, I attached the wrong
> patch;  I have corrected it now.]
>
>
> This patch is a follow-up to the split of the vacuum and analyze
> (done by Bruce Momjian last year).  I applies to today's CVS
> sources.
>
> It adds a separate SQL extension command ANALYZE that will only
> perform the analyze part and thus only use shared locks.
>
> I will submit the doc and test changes in a separate patch, if
> you decide that we are really going ahead with the ANALYZE
> command.
>
> This version still does not update pg_class.  Those statistics
> are still tied in the vacuum part (num. of pages, tuples and
> indication if the relation has an index).  The patch allows for
> analyze_rel() to work differently if run as part of a VACUUM or
> as an standalone ANALYZE, so the missing bits can be added
> without changes to the current behavior of VACUUM ANALYZE.
>
> Possible future improvements:
>
> 1) Add the pg_class update to ANALYZE;
>
> 2) Add a VERBOSE option that prints information to gives the
> DBA a hint if it is worth of running VACUUM or not.
>
> Thanks.
>
>
> -- Fernando Nasser Red Hat Inc.              E-Mail:
> fnasser@redhat.com

> Index: src/backend/commands/analyze.c
> ===================================================================
> RCS file:
> /home/projects/pgsql/cvsroot/pgsql/src/backend/commands/analyze.c,v
> retrieving revision 1.16 diff -c -p -r1.16 analyze.c ***
> src/backend/commands/analyze.c   2001/03/22 06:16:11     1.16
> --- src/backend/commands/analyze.c   2001/04/24 22:22:24
> *************** *** 35,41 **** --- 35,46 ----
>   #include "utils/fmgroids.h" #include "utils/inval.h" #include
>   "utils/syscache.h" + #include "utils/temprel.h"
>
> + static MemoryContext vac_context = NULL; + + static int
> MESSAGE_LEVEL;          /* message level */ +
>   #define swapLong(a,b)      {long tmp; tmp=a; a=b; b=tmp;}
>   #define swapInt(a,b)       {int tmp; tmp=a; a=b; b=tmp;}
>   #define swapDatum(a,b)     {Datum tmp; tmp=a; a=b; b=tmp;}
> *************** static void attr_stats(Relation onerel, ***
> 49,61 ****
>   static void bucketcpy(Form_pg_attribute attr, Datum value,
>   Datum *bucket, int *bucket_len); static void update_attstats(Oid
>   relid, int natts, VacAttrStats *vacattrstats); static void
>   del_stats(Oid relid, int attcnt, int *attnums);
>
>
>   /*
>    * analyze_rel() -- analyze relation */ void ! analyze_rel(Oid
> relid, List *anal_cols2, int MESSAGE_LEVEL)
>   {
> HeapTuple       tuple; Relation        onerel; --- 54,175
> ----
>   static void bucketcpy(Form_pg_attribute attr, Datum value,
>   Datum *bucket, int *bucket_len); static void update_attstats(Oid
>   relid, int natts, VacAttrStats *vacattrstats); static void
>   del_stats(Oid relid, int attcnt, int *attnums); + static void
> do_analyze(NameData *VacRelP, List *anal_cols2); + static void
> analyze_rel_1(Oid relid, List *anal_cols2, int vacuum); + + +
> void + analyze(char *vacrel, List *anal_cols) + { +    NameData
> VacRel; +    Name            VacRelName; +    MemoryContext old;
> +    List       *le; +    List       *anal_cols2 = NIL; + +
> /* +     * We cannot run ANALYZE inside a user transaction block;
> if we were +     * inside a transaction, then our commit- and
> +     * start-transaction-command calls would not have the
> intended effect!  +     */ +    if (IsTransactionBlock()) +
> elog(ERROR, "ANALYZE cannot run inside a BEGIN/END block"); +
> +    MESSAGE_LEVEL = DEBUG;
>
> +    /* +     * Create special memory context for cross-transaction
> storage.  +     * +     * Since it is a child of QueryContext,
> it will go away eventually even +     * if we suffer an error;
> there's no need for special abort cleanup +     * logic.  +
> */ +    vac_context = AllocSetContextCreate(QueryContext, +
> "Analyze", +
> ALLOCSET_DEFAULT_MINSIZE, +
> ALLOCSET_DEFAULT_INITSIZE, +
> ALLOCSET_DEFAULT_MAXSIZE); + +    /* vacrel gets de-allocated
> on xact commit, so copy it to safe storage */ +    if (vacrel)
> +    { +            namestrcpy(&VacRel, vacrel); +
> VacRelName = &VacRel; +    } +    else +            VacRelName
> = NULL;
>
> +    /* must also copy the column list, if any, to safe storage
> */ +    old = MemoryContextSwitchTo(vac_context); +    foreach(le,
> anal_cols) +    { +            char       *col = (char *)
> lfirst(le); + +            anal_cols2 = lappend(anal_cols2,
> pstrdup(col)); +    } +    MemoryContextSwitchTo(old); + +
> /* +     * Start up the analyzer.  +     * +     * NOTE: since
> this commits the current transaction, the memory holding +
> * any passed-in parameters gets freed here.  We must have already
> +     * copied pass-by-reference parameters to safe storage.
> Don't make me +     * fix this again!  +     */ +    vacuum_init();
> + +    /* analyze the database */ +    do_analyze(VacRelName,
> anal_cols2); + +    vacuum_shutdown(vac_context); + } +
>   /* +  * do_analyze() -- analyze the database.  +  * +  *
> This routine builds a list of relations to analyze, and then
> calls +  *         code that analyze them one at a time.  +  */
> + static void + do_analyze(NameData *VacRelP, List *anal_cols2)
> + { +    VRelList        vrl, +                            cur;
> + +    /* get list of relations */ +    vrl = vacuum_getrels(VacRelP,
> vac_context); + +    /* analyze each heap relation */ +    for
> (cur = vrl; cur != (VRelList) NULL; cur = cur->vrl_next) +
> { +            analyze_rel_1(cur->vrl_relid, anal_cols2, 0 /*
> not vacuum */); +    } + } + + /*
>    * analyze_rel() -- analyze relation +  * +  * Called through
> here when doing vacuum
>    */ void ! analyze_rel(Oid relid, List *anal_cols2, int
> msg_level) ! { !    /* !     * Use the MESSAGE_LEVEL as set on
> vacuum.  !     */ !    MESSAGE_LEVEL = msg_level; !
> analyze_rel_1(relid, anal_cols2, 1 /* vacuum */); ! } !  ! /*
> !  * analyze_rel_1() -- analyze relation !  * !  * Do the job
> for ANALYZE or VACUUM ANALYSE in one relation !  */ !  ! static
> void ! analyze_rel_1(Oid relid, List *anal_cols2, int vacuum)
>   {
> HeapTuple       tuple; Relation        onerel; ***************
> analyze_rel(Oid relid, List *anal_cols2, *** 107,116 ****
> {
>
>     /*
> !             * we already did an elog during vacuum elog(NOTICE,
> "Skipping !             * \"%s\" --- only table owner can VACUUM
> it", !             * RelationGetRelationName(onerel));
>      */ heap_close(onerel, NoLock); CommitTransactionCommand();
>     return;
> --- 221,231 ----
> {
>
>     /*
> !             * we already did an elog during vacuum
>      */
> +            if (!vacuum) +                    elog(NOTICE,
> "Skipping \"%s\" --- only table owner can ANALYZE it", +
> RelationGetRelationName(onerel));
>     heap_close(onerel, NoLock); CommitTransactionCommand();
>     return;
> *************** analyze_rel(Oid relid, List *anal_cols2, ***
> 127,133 ****
>     List       *le;
>
>     if (length(anal_cols2) > attr_cnt)
> !                    elog(ERROR, "vacuum: too many attributes
> specified for relation %s",
>              RelationGetRelationName(onerel));
>     attnums = (int *) palloc(attr_cnt * sizeof(int));
>     foreach(le, anal_cols2)
> --- 242,248 ----
>     List       *le;
>
>     if (length(anal_cols2) > attr_cnt)
> !                    elog(ERROR, "analyze: too many attributes
> specified for relation %s",
>              RelationGetRelationName(onerel));
>     attnums = (int *) palloc(attr_cnt * sizeof(int));
>     foreach(le, anal_cols2)
> *************** analyze_rel(Oid relid, List *anal_cols2, ***
> 143,149 ****
>             attnums[tcnt++] = i; else {
> !                            elog(ERROR, "vacuum: there is no
> attribute %s in %s",
>                  col,
>                  RelationGetRelationName(onerel));
>         } }
> --- 258,264 ----
>             attnums[tcnt++] = i; else {
> !                            elog(ERROR, "analyze: there is no
> attribute %s in %s",
>                  col,
>                  RelationGetRelationName(onerel));
>         } }
> Index: src/backend/commands/vacuum.c
> ===================================================================
> RCS file:
> /home/projects/pgsql/cvsroot/pgsql/src/backend/commands/vacuum.c,v
> retrieving revision 1.189 diff -c -p -r1.189 vacuum.c ***
> src/backend/commands/vacuum.c    2001/03/25 23:23:58     1.189
> --- src/backend/commands/vacuum.c    2001/04/24 22:22:25
> *************** static int   MESSAGE_LEVEL;          /* message
> le *** 60,69 ****
>   static TransactionId XmaxRecent;
>
>   /* non-export function prototypes */ - static void vacuum_init(void);
> - static void vacuum_shutdown(void);
>   static void vac_vacuum(NameData *VacRelP, bool analyze, List
>   *anal_cols2); - static VRelList getrels(NameData *VacRelP);
>   static void vacuum_rel(Oid relid); static void scan_heap(VRelStats
>   *vacrelstats, Relation onerel, VacPageList vacuum_pages,
>   VacPageList fraged_pages); static void repair_frag(VRelStats
>   *vacrelstats, Relation onerel, VacPageList vacuum_pages,
>   VacPageList fraged_pages, int nindices, Relation *Irel); ---
> 60,66 ---- *************** vacuum(char *vacrel, bool verbose,
> bool *** 163,169 ****
> vac_vacuum(VacRelName, analyze, anal_cols2);
>
> /* clean up */ !    vacuum_shutdown();
>   }
>
>   /* --- 160,166 ----
> vac_vacuum(VacRelName, analyze, anal_cols2);
>
> /* clean up */ !    vacuum_shutdown(vac_context);
>   }
>
>   /* *************** vacuum(char *vacrel, bool verbose, bool
> *** 186,200 ****
>    *         vacuum_shutdown() to match the commit waiting for
>    us back in *         PostgresMain().  */ ! static void
>   vacuum_init() {
> /* matches the StartTransaction in PostgresMain() */
> CommitTransactionCommand(); }
>
> ! static void ! vacuum_shutdown()
>   {
> /* on entry, we are not in a transaction */
>
> --- 183,197 ----
>    *         vacuum_shutdown() to match the commit waiting for
>    us back in *         PostgresMain().  */ ! void
>   vacuum_init() {
> /* matches the StartTransaction in PostgresMain() */
> CommitTransactionCommand(); }
>
> ! void ! vacuum_shutdown(MemoryContext context)
>   {
> /* on entry, we are not in a transaction */
>
> *************** vacuum_shutdown() *** 218,224 ****
>  * StartTransactionCommand, else we might be trying to
>  delete the * active context!  */ !
> MemoryContextDelete(vac_context);
> vac_context = NULL; }
>
> --- 215,221 ----
>  * StartTransactionCommand, else we might be trying to
>  delete the * active context!  */ !
> MemoryContextDelete(context);
> vac_context = NULL; }
>
> *************** vac_vacuum(NameData *VacRelP, bool analy ***
> 237,243 ****
>             cur;
>
> /* get list of relations */ !    vrl = getrels(VacRelP);
>
> /* vacuum each heap relation */ for (cur = vrl; cur !=
> (VRelList) NULL; cur = cur->vrl_next) --- 234,240 ----
>             cur;
>
> /* get list of relations */ !    vrl = vacuum_getrels(VacRelP,
> vac_context);
>
> /* vacuum each heap relation */ for (cur = vrl; cur !=
> (VRelList) NULL; cur = cur->vrl_next) ***************
> vac_vacuum(NameData *VacRelP, bool analy *** 249,256 ****
> } }
>
> ! static VRelList ! getrels(NameData *VacRelP)
>   {
> Relation        rel; TupleDesc       tupdesc; --- 246,253
> ----
> } }
>
> ! VRelList ! vacuum_getrels(NameData *VacRelP, MemoryContext
> context)
>   {
> Relation        rel; TupleDesc       tupdesc; ***************
> getrels(NameData *VacRelP) *** 317,327 ****
>     /* get a relation list entry for this guy */ if
>     (vrl == (VRelList) NULL)
>         vrl = cur = (VRelList)
> !                            MemoryContextAlloc(vac_context,
> sizeof(VRelListData));
>     else {
>         cur->vrl_next = (VRelList)
> !                            MemoryContextAlloc(vac_context,
> sizeof(VRelListData));
>         cur = cur->vrl_next; }
>
> --- 314,324 ----
>     /* get a relation list entry for this guy */ if
>     (vrl == (VRelList) NULL)
>         vrl = cur = (VRelList)
> !                            MemoryContextAlloc(context,
> sizeof(VRelListData));
>     else {
>         cur->vrl_next = (VRelList)
> !                            MemoryContextAlloc(context,
> sizeof(VRelListData));
>         cur = cur->vrl_next; }
>
> Index: src/backend/nodes/copyfuncs.c
> ===================================================================
> RCS file:
> /home/projects/pgsql/cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v
> retrieving revision 1.140 diff -c -p -r1.140 copyfuncs.c ***
> src/backend/nodes/copyfuncs.c    2001/03/22 06:16:14     1.140
> --- src/backend/nodes/copyfuncs.c    2001/04/24 22:22:25
> *************** _copyVacuumStmt(VacuumStmt *from) *** 2218,2223
> **** --- 2218,2235 ----
> return newnode; }
>
> + static AnalyzeStmt * + _copyAnalyzeStmt(AnalyzeStmt *from) +
> { +    AnalyzeStmt *newnode = makeNode(AnalyzeStmt); + +    if
> (from->anarel) +            newnode->anarel = pstrdup(from->anarel);
> +    Node_Copy(from, newnode, va_spec); + +    return newnode;
> + } +
>   static ExplainStmt * _copyExplainStmt(ExplainStmt *from) {
> *************** copyObject(void *from) *** 2780,2785 **** ---
> 2792,2800 ----
>         break; case T_RemoveOperStmt:
>         retval = _copyRemoveOperStmt(from);
> +                    break; +            case T_AnalyzeStmt:
> +                    retval = _copyAnalyzeStmt(from);
>         break; case T_RenameStmt:
>         retval = _copyRenameStmt(from);
> Index: src/backend/nodes/equalfuncs.c
> ===================================================================
> RCS file:
> /home/projects/pgsql/cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v
> retrieving revision 1.88 diff -c -p -r1.88 equalfuncs.c ***
> src/backend/nodes/equalfuncs.c   2001/03/22 03:59:31     1.88
> --- src/backend/nodes/equalfuncs.c   2001/04/24 22:22:25
> *************** _equalVacuumStmt(VacuumStmt *a, VacuumSt ***
> 1126,1131 **** --- 1126,1142 ----
>   }
>
>   static bool + _equalAnalyzeStmt(AnalyzeStmt *a, AnalyzeStmt
> *b) + { +    if (!equalstr(a->anarel, b->anarel)) +
> return false; +    if (!equal(a->va_spec, b->va_spec)) +
> return false; + +    return true; + } + + static bool
>   _equalExplainStmt(ExplainStmt *a, ExplainStmt *b) {
> if (!equal(a->query, b->query)) *************** equal(void
> *a, void *b) *** 1946,1951 **** --- 1957,1965 ----
>         break; case T_RemoveOperStmt:
>         retval = _equalRemoveOperStmt(a, b);
> +                    break; +            case T_AnalyzeStmt:
> +                    retval = _equalAnalyzeStmt(a, b);
>         break; case T_RenameStmt:
>         retval = _equalRenameStmt(a, b);
> Index: src/backend/parser/gram.y
> ===================================================================
> RCS file: /home/projects/pgsql/cvsroot/pgsql/src/backend/parser/gram.y,v
> retrieving revision 2.221 diff -c -p -r2.221 gram.y ***
> src/backend/parser/gram.y        2001/02/18 18:06:10     2.221
> --- src/backend/parser/gram.y        2001/04/24 22:22:26
> *************** static void doNegateFloat(Value *v); *** 130,135
> **** --- 130,136 ----
>
>   %type <node>       stmt,
>     AlterGroupStmt, AlterSchemaStmt, AlterTableStmt,
>     AlterUserStmt,
> +            AnalyzeStmt, CheckPointStmt,
>     ClosePortalStmt, ClusterStmt, CommentStmt,
>     ConstraintsSetStmt, CopyStmt, CreateAsStmt,
>     CreateGroupStmt, CreatePLangStmt, CreateSchemaStmt,
>     CreateSeqStmt, CreateStmt, CreateTrigStmt,
> *************** static void doNegateFloat(Value *v); *** 142,148
> ****
>     RenameStmt, RevokeStmt, RuleActionStmt,
>     RuleActionStmtOrEmpty, RuleStmt, SelectStmt,
>     TransactionStmt, TruncateStmt, UnlistenStmt,
>     UpdateStmt, VacuumStmt, VariableResetStmt,
> !            VariableSetStmt, VariableShowStmt, ViewStmt,
> CheckPointStmt
>
>   %type <node>       select_no_parens, select_with_parens,
>   select_clause,
>             simple_select
> --- 143,149 ----
>     RenameStmt, RevokeStmt, RuleActionStmt,
>     RuleActionStmtOrEmpty, RuleStmt, SelectStmt,
>     TransactionStmt, TruncateStmt, UnlistenStmt,
>     UpdateStmt, VacuumStmt, VariableResetStmt,
> !            VariableSetStmt, VariableShowStmt, ViewStmt
>
>   %type <node>       select_no_parens, select_with_parens,
>   select_clause,
>             simple_select
> *************** stmt :       AlterSchemaStmt *** 426,431 ****
> --- 427,433 ----
>     | AlterTableStmt | AlterGroupStmt | AlterUserStmt
> +            | AnalyzeStmt
>     | ClosePortalStmt | CopyStmt | CreateStmt
> *************** va_list:  name *** 3037,3042 **** --- 3039,3074
> ----
>             { $$ = makeList1($1); }
>     | va_list ',' name
>             { $$ = lappend($1, $3); }
> +            ; + + +
> /*****************************************************************************
> +  * +  *         QUERY:  +  *                         analyze
> +  * +
> *****************************************************************************/
> + + /* We use opt_va_list and va_list defined for vacuum. */ +
> + AnalyzeStmt:  ANALYZE +                                 { +
> AnalyzeStmt *n = makeNode(AnalyzeStmt); +
> n->anarel = NULL; +
> n->va_spec = NIL; +                                         $$
> = (Node *)n; +                                 } +
> | ANALYZE relation_name opt_va_list +
> { +                                    AnalyzeStmt *n =
> makeNode(AnalyzeStmt); +
> n->anarel = $2; +                                    n->va_spec
> = $3; +                                    if ( $3 != NIL &&
> !$2 ) +                                            elog(ERROR,"ANALYZE
> syntax error at or near \"(\"" +
> "\n\tRelation name must be specified"); + +
> $$ = (Node *)n; +                            }
>     ;
>
>
> Index: src/backend/tcop/utility.c
> ===================================================================
> RCS file:
> /home/projects/pgsql/cvsroot/pgsql/src/backend/tcop/utility.c,v
> retrieving revision 1.109 diff -c -p -r1.109 utility.c ***
> src/backend/tcop/utility.c       2001/03/22 06:16:17     1.109
> --- src/backend/tcop/utility.c       2001/04/24 22:22:26
> *************** ProcessUtility(Node *parsetree, *** 711,716 ****
> --- 711,723 ----
>                ((VacuumStmt *) parsetree)->va_spec);
>         break;
>
> +            case T_AnalyzeStmt:  +
> set_ps_display(commandTag = "ANALYZE"); + +
> analyze(((AnalyzeStmt *) parsetree)->anarel, +
> ((AnalyzeStmt *) parsetree)->va_spec); +
> break; +
>     case T_ExplainStmt:
>         {
>             ExplainStmt *stmt = (ExplainStmt
>             *) parsetree;
> Index: src/include/commands/vacuum.h
> ===================================================================
> RCS file:
> /home/projects/pgsql/cvsroot/pgsql/src/include/commands/vacuum.h,v
> retrieving revision 1.34 diff -c -p -r1.34 vacuum.h ***
> src/include/commands/vacuum.h    2001/03/22 04:00:43     1.34
> --- src/include/commands/vacuum.h    2001/04/24 22:22:29
> *************** extern bool VacuumRunning; *** 122,127 **** ---
> 122,131 ----
>
>   extern void vc_abort(void); extern void vacuum(char *vacrel,
>   bool verbose, bool analyze, List *anal_cols); + extern void
> vacuum_init(void); + extern void vacuum_shutdown(MemoryContext
> vac_context); + extern VRelList vacuum_getrels(NameData *VacRelP,
> MemoryContext vac_context); + extern void analyze(char *vacrel,
> List *anal_cols);
>   extern void analyze_rel(Oid relid, List *anal_cols2, int
>   MESSAGE_LEVEL);
>
>   #define ATTNVALS_SCALE     1000000000              /* XXX so
>   it can act as a float4 */ Index: src/include/nodes/nodes.h
> ===================================================================
> RCS file: /home/projects/pgsql/cvsroot/pgsql/src/include/nodes/nodes.h,v
> retrieving revision 1.89 diff -c -p -r1.89 nodes.h ***
> src/include/nodes/nodes.h        2001/04/24 00:08:38     1.89
> --- src/include/nodes/nodes.h        2001/04/24 22:22:29
> *************** typedef enum NodeTag *** 165,171 ****
> T_RemoveAggrStmt, T_RemoveFuncStmt, T_RemoveOperStmt, !
> T_RemoveStmt_XXX,                       /* not used anymore;
> tag# available */
> T_RenameStmt, T_RuleStmt, T_NotifyStmt, --- 165,171 ----
> T_RemoveAggrStmt, T_RemoveFuncStmt, T_RemoveOperStmt, !
> T_AnalyzeStmt,
> T_RenameStmt, T_RuleStmt, T_NotifyStmt, Index:
> src/include/nodes/parsenodes.h
> ===================================================================
> RCS file:
> /home/projects/pgsql/cvsroot/pgsql/src/include/nodes/parsenodes.h,v
> retrieving revision 1.126 diff -c -p -r1.126 parsenodes.h ***
> src/include/nodes/parsenodes.h   2001/03/23 04:49:56     1.126
> --- src/include/nodes/parsenodes.h   2001/04/24 22:22:29
> *************** typedef struct VacuumStmt *** 703,708 **** ---
> 703,719 ----
>   } VacuumStmt;
>
>   /* ---------------------- +  *         Analyze Statement +
> * ---------------------- +  */ + typedef struct AnalyzeStmt +
> { +    NodeTag         type; +    char       *anarel;
> /* table to analyze */ +    List       *va_spec;            /*
> columns to analyse */ + } AnalyzeStmt; + + /* ----------------------
>    *         Explain Statement * ---------------------- */ Index:
> src/interfaces/ecpg/preproc/preproc.y
> ===================================================================
> RCS file:
> /home/projects/pgsql/cvsroot/pgsql/src/interfaces/ecpg/preproc/preproc.y,v
> retrieving revision 1.136 diff -c -p -r1.136 preproc.y ***
> src/interfaces/ecpg/preproc/preproc.y    2001/04/05 08:21:14
> 1.136 --- src/interfaces/ecpg/preproc/preproc.y    2001/04/24
> 22:22:30 *************** make_name(void) *** 302,308 ****
>   %type  <str>    copy_delimiter ListenStmt CopyStmt copy_file_name
>   opt_binary %type  <str>    opt_with_copy FetchStmt direction
>   fetch_how_many from_in %type  <str>    ClosePortalStmt DropStmt
>   VacuumStmt opt_verbose func_arg ! %type  <str>    opt_analyze
> opt_va_list va_list ExplainStmt index_params
>   %type  <str>    index_list func_index index_elem opt_class
>   access_method_clause %type  <str>    index_opt_unique IndexStmt
>   func_return ConstInterval %type  <str>    func_args_list
>   func_args opt_with ProcedureStmt def_arg --- 302,308 ----
>   %type  <str>    copy_delimiter ListenStmt CopyStmt copy_file_name
>   opt_binary %type  <str>    opt_with_copy FetchStmt direction
>   fetch_how_many from_in %type  <str>    ClosePortalStmt DropStmt
>   VacuumStmt opt_verbose func_arg ! %type  <str>    opt_analyze
> opt_va_list va_list AnalyzeStmt ExplainStmt index_params
>   %type  <str>    index_list func_index index_elem opt_class
>   access_method_clause %type  <str>    index_opt_unique IndexStmt
>   func_return ConstInterval %type  <str>    func_args_list
>   func_args opt_with ProcedureStmt def_arg *************** stmt:
> AlterSchemaStmt                       { output_state *** 447,452
> **** --- 447,453 ----
>     | CreatedbStmt          { output_statement($1, 0,
>     NULL, connection); } | DropdbStmt            {
>     output_statement($1, 0, NULL, connection); } |
>     VacuumStmt            { output_statement($1, 0,
>     NULL, connection); }
> +            | AnalyzeStmt           { output_statement($1, 0,
> NULL, connection); }
>     | VariableSetStmt       { output_statement($1, 0,
>     NULL, connection); } | VariableShowStmt      {
>     output_statement($1, 0, NULL, connection); } |
>     VariableResetStmt     { output_statement($1, 0,
>     NULL, connection); }
> *************** va_list:  name *** 2282,2287 **** --- 2283,2310
> ----
>             { $$=$1; }
>     | va_list ',' name
>             { $$=cat_str(3, $1, make_str(","),
>             $3); }
> +            ; + + +
> /*****************************************************************************
> +  * +  *         QUERY:  +  *                         analyze
> +  * +
> *****************************************************************************/
> + + /* We use opt_va_list and va_list defined for vacuum. */ +
> + AnalyzeStmt:  ANALYZE +                            { +
> $$ = cat_str(1, make_str("analyze")); +
> } +            | ANALYZE relation_name opt_va_list +
> { +                                    if ( strlen($3) > 0 &&
> strlen($2) == 0 ) +
> mmerror(ET_ERROR, "ANALYZE syntax error at or near \"(\"\n\tRelations
> name must be specified"); +
> $$ = cat_str(3, make_str("analyze"), $2, $3); +
> }
>     ;
>
>

>
> ---------------------------(end of broadcast)---------------------------
> TIP 4: Don't 'kill -9' the postmaster

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 853-3000
  +  If your life is a hard drive,     |  830 Blythe Avenue
  +  Christ can be your backup.        |  Drexel Hill, Pennsylvania 19026

pgsql-patches by date:

Previous
From: Bruce Momjian
Date:
Subject: Re: dbf2pg improvements (password, charset convertions,etc.)
Next
From: Bruce Momjian
Date:
Subject: Re: \du in psql patchp