ANALYZE command [REPOST]

Поиск
Список
Период
Сортировка
Искать
От
Fernando Nasser
Тема
ANALYZE command [REPOST]
Дата
Msg-id
3AE5FE71.927768AC@cygnus.com
Список
Дерево обсуждения
ANALYZE command [REPOST] Fernando Nasser <fnasser@cygnus.com>
Re: ANALYZE command [REPOST] Bruce Momjian <pgman@candle.pha.pa.us>
Re: ANALYZE command [REPOST] Bruce Momjian <pgman@candle.pha.pa.us>
Re: ANALYZE command [REPOST] Tom Lane <tgl@sss.pgh.pa.us>
[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.comIndex: 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 	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 	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 	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      copy_delimiter ListenStmt CopyStmt copy_file_name opt_binary
  %type      opt_with_copy FetchStmt direction fetch_how_many from_in
  %type      ClosePortalStmt DropStmt VacuumStmt opt_verbose func_arg
! %type      opt_analyze opt_va_list va_list ExplainStmt index_params
  %type      index_list func_index index_elem opt_class access_method_clause
  %type      index_opt_unique IndexStmt func_return ConstInterval
  %type      func_args_list func_args opt_with ProcedureStmt def_arg
--- 302,308 ----
  %type      copy_delimiter ListenStmt CopyStmt copy_file_name opt_binary
  %type      opt_with_copy FetchStmt direction fetch_how_many from_in
  %type      ClosePortalStmt DropStmt VacuumStmt opt_verbose func_arg
! %type      opt_analyze opt_va_list va_list AnalyzeStmt ExplainStmt index_params
  %type      index_list func_index index_elem opt_class access_method_clause
  %type      index_opt_unique IndexStmt func_return ConstInterval
  %type      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);
+ 				}
  		;
  
  
В списке pgsql-patches по дате отправления
От: Fernando Nasser
Дата:
Сообщение: ANALYZE command
От: Bruce Momjian
Дата:
Сообщение: Re: ANALYZE command [REPOST]
FAQ