*** a/doc/src/sgml/func.sgml	2008-11-27 19:09:20.000000000 +0000
--- b/doc/src/sgml/func.sgml	2008-11-30 20:52:26.000000000 +0000
***************
*** 10269,10281 ****
          <primary>lag</primary>
         </indexterm>
         <function>
!          lag(<replaceable class="parameter">value</replaceable>, <replaceable
!          class="parameter">offset</replaceable>, [<replaceable 
           class="parameter">default</replaceable>])
         </function>
        </entry>
        <entry>
!         <type>any, integer[, any]</type>
        </entry>
        <entry>
         <type>same type as <replaceable class="parameter">value</replaceable></type>
--- 10269,10281 ----
          <primary>lag</primary>
         </indexterm>
         <function>
!          lag(<replaceable class="parameter">value</replaceable>, [<replaceable
!          class="parameter">offset</replaceable>], [<replaceable 
           class="parameter">default</replaceable>])
         </function>
        </entry>
        <entry>
!         <type>any, [integer], [any]</type>
        </entry>
        <entry>
         <type>same type as <replaceable class="parameter">value</replaceable></type>
***************
*** 10283,10291 ****
        <entry>
          returns <replaceable class="parameter">value</replaceable> evaluated on
          the row that is <replaceable class="parameter">offset</replaceable> number of
!         rows before the current row within the partition. If <replaceable
!         class="parameter">default</replaceable> is specified and the target row is out
          of the partition, <replaceable class="parameter">default</replaceable> is returned.
        </entry>
       </row>
  
--- 10283,10294 ----
        <entry>
          returns <replaceable class="parameter">value</replaceable> evaluated on
          the row that is <replaceable class="parameter">offset</replaceable> number of
!         rows before the current row within the partition. If <replaceable class="parameter">
!         offset</replaceable>  is ommited then a default offset of 1 is assumed. If 
!         <replaceable class="parameter">default</replaceable> is specified and the target row is out
          of the partition, <replaceable class="parameter">default</replaceable> is returned.
+         Note that <replaceable class="parameter">default</replaceable> may only be specified
+         if <replaceable class="parameter">offset</replaceable> is also specified.
        </entry>
       </row>
  
***************
*** 10295,10307 ****
          <primary>lead</primary>
         </indexterm>
         <function>
!          lead(<replaceable class="parameter">value</replaceable>, <replaceable
!          class="parameter">offset</replaceable>, [<replaceable
           class="parameter">default</replaceable>])
         </function>
        </entry>
        <entry>
!         <type>any, integer[, any]</type>
        </entry>
        <entry>
         <type>same type as <replaceable class="parameter">value</replaceable></type>
--- 10298,10310 ----
          <primary>lead</primary>
         </indexterm>
         <function>
!          lead(<replaceable class="parameter">value</replaceable>, [<replaceable
!          class="parameter">offset</replaceable>], [<replaceable
           class="parameter">default</replaceable>])
         </function>
        </entry>
        <entry>
!         <type>any, [integer], [any]</type>
        </entry>
        <entry>
         <type>same type as <replaceable class="parameter">value</replaceable></type>
***************
*** 10309,10317 ****
        <entry>
          returns <replaceable class="parameter">value</replaceable> evaluated on
          the row that is <replaceable class="parameter">offset</replaceable> number of
!         rows after the current row within the partition. If <replaceable
!         class="parameter">default</replaceable> is specified and the target row is out
          of the partition, <replaceable class="parameter">default</replaceable> is returned.
        </entry>
       </row>
  
--- 10312,10323 ----
        <entry>
          returns <replaceable class="parameter">value</replaceable> evaluated on
          the row that is <replaceable class="parameter">offset</replaceable> number of
!         rows after the current row within the partition.  If <replaceable class="parameter">
!         offset</replaceable>  is ommited then a default offset of 1 is assumed. If
! 	<replaceable class="parameter">default</replaceable> is specified and the target row is out
          of the partition, <replaceable class="parameter">default</replaceable> is returned.
+         Note that <replaceable class="parameter">default</replaceable> may only be specified
+         if <replaceable class="parameter">offset</replaceable> is also specified.
        </entry>
       </row>
  
*** a/src/backend/utils/adt/wfunc.c	2008-11-30 19:40:33.000000000 +0000
--- b/src/backend/utils/adt/wfunc.c	2008-11-30 20:41:50.000000000 +0000
***************
*** 18,24 ****
  #include "utils/builtins.h"
  
  static bool rank_up(FunctionCallInfo fcinfo);
! static Datum leadlag_common(FunctionCallInfo fcinfo, bool forward, bool fetchdefault);
  
  /*
   * SQL spec window functions
--- 18,24 ----
  #include "utils/builtins.h"
  
  static bool rank_up(FunctionCallInfo fcinfo);
! static Datum leadlag_common(FunctionCallInfo fcinfo, bool forward, bool fetchdefault, bool withoffset);
  
  /*
   * SQL spec window functions
***************
*** 30,38 ****
  Datum cume_dist(PG_FUNCTION_ARGS);
  Datum ntile(PG_FUNCTION_ARGS);
  Datum lag(PG_FUNCTION_ARGS);
! Datum lag_withdefault(PG_FUNCTION_ARGS);
  Datum lead(PG_FUNCTION_ARGS);
! Datum lead_withdefault(PG_FUNCTION_ARGS);
  Datum first_value(PG_FUNCTION_ARGS);
  Datum last_value(PG_FUNCTION_ARGS);
  Datum nth_value(PG_FUNCTION_ARGS);
--- 30,40 ----
  Datum cume_dist(PG_FUNCTION_ARGS);
  Datum ntile(PG_FUNCTION_ARGS);
  Datum lag(PG_FUNCTION_ARGS);
! Datum lag_with_offset(PG_FUNCTION_ARGS);
! Datum lag_with_offset_and_default(PG_FUNCTION_ARGS);
  Datum lead(PG_FUNCTION_ARGS);
! Datum lead_with_offset(PG_FUNCTION_ARGS);
! Datum lead_with_offset_and_default(PG_FUNCTION_ARGS);
  Datum first_value(PG_FUNCTION_ARGS);
  Datum last_value(PG_FUNCTION_ARGS);
  Datum nth_value(PG_FUNCTION_ARGS);
***************
*** 314,320 ****
   * datum is out of range.
   */
  static Datum
! leadlag_common(FunctionCallInfo fcinfo, bool forward, bool fetchdefault)
  {
  	WindowObject	winobj = PG_WINDOW_OBJECT();
  	int4			offset;
--- 316,322 ----
   * datum is out of range.
   */
  static Datum
! leadlag_common(FunctionCallInfo fcinfo, bool forward, bool fetchdefault, bool withoffset)
  {
  	WindowObject	winobj = PG_WINDOW_OBJECT();
  	int4			offset;
***************
*** 322,335 ****
  	bool			isnull;
  	bool			isout;
  
! 	offset = WinRowGetArg(winobj, 1, &isnull);
! 	if (isnull)
! 		PG_RETURN_NULL();
  
  	result = WinPartGetArg(winobj, 0,
  						   (forward ? offset : -offset),
  						   WINDOW_SEEK_CURRENT, &isnull, &isout);
- 
  	if (isout)
  	{
  		/*
--- 324,341 ----
  	bool			isnull;
  	bool			isout;
  
! 	if (withoffset)
! 	{
! 		offset = WinRowGetArg(winobj, 1, &isnull);
! 		if (isnull)
! 			PG_RETURN_NULL();
! 	}
! 	else 
! 		offset = 1;
  
  	result = WinPartGetArg(winobj, 0,
  						   (forward ? offset : -offset),
  						   WINDOW_SEEK_CURRENT, &isnull, &isout);
  	if (isout)
  	{
  		/*
***************
*** 348,393 ****
  
  /*
   * lag
!  * returns the value of VE evaluated on a row that is OFFSET
!  * number of rows before the current row within a partition,
   * per spec.
   */
  Datum
  lag(PG_FUNCTION_ARGS)
  {
! 	return leadlag_common(fcinfo, false, false);
  }
  
  /*
!  * lag_withdefault
!  * same as lag but accepts default value as its third argument
   */
  Datum
! lag_withdefault(PG_FUNCTION_ARGS)
  {
! 	return leadlag_common(fcinfo, false, true);
  }
  
  /*
   * lead
   * returns the value of VE evaluated on a row that is OFFSET
   * number of rows after the current row within a partition,
   * per spec.
   */
  Datum
! lead(PG_FUNCTION_ARGS)
  {
! 	return leadlag_common(fcinfo, true, false);
  }
  
  /*
!  * lead_withdefault
!  * same as lead but accepts default value as its third argument
   */
  Datum
! lead_withdefault(PG_FUNCTION_ARGS)
  {
! 	return leadlag_common(fcinfo, true, true);
  }
  
  /*
--- 354,425 ----
  
  /*
   * lag
!  * returns the value of VE evaluated on a row that is 1
!  * row before the current row within a partition,
   * per spec.
   */
  Datum
  lag(PG_FUNCTION_ARGS)
  {
! 	return leadlag_common(fcinfo, false, false, false);
! }
! 
! /*
!  * lag_with_offset
!  * returns the value of VE evelulated on a row that is OFFSET
!  * rows before the current row within a partition,
!  * per spec.
!  */
! Datum
! lag_with_offset(PG_FUNCTION_ARGS)
! {
! 	return leadlag_common(fcinfo, false, false, true);
  }
  
  /*
!  * lag_with_offset_and_default
!  * same as lag_with_offset but accepts default value
!  * as its third argument.
   */
  Datum
! lag_with_offset_and_default(PG_FUNCTION_ARGS)
  {
! 	return leadlag_common(fcinfo, false, true, true);
  }
  
  /*
   * lead
+  * returns the value of VE evaluated on a row that is 1
+  * row after the current row within a partition,
+  * per spec.
+  */
+ Datum
+ lead(PG_FUNCTION_ARGS)
+ {
+ 	return leadlag_common(fcinfo, true, false, false);
+ }
+ 
+ /*
+  * lead_with_offset
   * returns the value of VE evaluated on a row that is OFFSET
   * number of rows after the current row within a partition,
   * per spec.
   */
  Datum
! lead_with_offset(PG_FUNCTION_ARGS)
  {
! 	return leadlag_common(fcinfo, true, false, true);
  }
  
  /*
!  * lead_with_offset_and_default
!  * same as lead_with_offset but accepts default value
!  * as its third argument.
   */
  Datum
! lead_with_offset_and_default(PG_FUNCTION_ARGS)
  {
! 	return leadlag_common(fcinfo, true, true, true);
  }
  
  /*

*** a/src/include/catalog/pg_proc.h	2008-11-30 19:41:08.000000000 +0000
--- b/src/include/catalog/pg_proc.h	2008-11-30 20:42:32.000000000 +0000
***************
*** 4613,4631 ****
  DESCR("fraction of row_number per the partition rows");
  DATA(insert OID = 3903 (  ntile PGNSP PGUID 12 1 0 0 f t f t f s 1 23 "23" _null_ _null_ _null_ ntile _null_ _null_ _null_));
  DESCR("split number of rows divided by a bucket number");
! DATA(insert OID = 3904 (  lag PGNSP PGUID 12 1 0 0 f t f t f s 2 2283 "2283 23"       _null_ _null_ _null_ lag _null_ _null_ _null_));
  DESCR("fetch the preceding row value");
! DATA(insert OID = 3905 (  lag PGNSP PGUID 12 1 0 0 f t f t f s 3 2283 "2283 23 2283"  _null_ _null_ _null_ lag_withdefault _null_ _null_ _null_));
  DESCR("fetch the preceding row value with default");
! DATA(insert OID = 3906 (  lead PGNSP PGUID 12 1 0 0 f t f t f s 2 2283 "2283 23"       _null_ _null_ _null_ lead _null_ _null_ _null_));
  DESCR("fetch the following row value");
! DATA(insert OID = 3907 (  lead PGNSP PGUID 12 1 0 0 f t f t f s 3 2283 "2283 23 2283"  _null_ _null_ _null_ lead_withdefault _null_ _null_ _null_));
  DESCR("fetch the following row value with default");
! DATA(insert OID = 3908 (  first_value PGNSP PGUID 12 1 0 0 f t f t f s 1 2283 "2283"  _null_ _null_ _null_ first_value _null_ _null_ _null_));
  DESCR("fetch the first row value");
! DATA(insert OID = 3909 (  last_value PGNSP PGUID 12 1 0 0 f t f t f s 1 2283 "2283"  _null_ _null_ _null_ last_value _null_ _null_ _null_));
  DESCR("fetch the last row value");
! DATA(insert OID = 3910 (  nth_value PGNSP PGUID 12 1 0 0 f t f t f s 2 2283 "2283 23" _null_ _null_ _null_ nth_value _null_ _null_ _null_));
  DESCR("fetch following row value");
    
  
--- 4613,4635 ----
  DESCR("fraction of row_number per the partition rows");
  DATA(insert OID = 3903 (  ntile PGNSP PGUID 12 1 0 0 f t f t f s 1 23 "23" _null_ _null_ _null_ ntile _null_ _null_ _null_));
  DESCR("split number of rows divided by a bucket number");
! DATA(insert OID = 3904 (  lag PGNSP PGUID 12 1 0 0 f t f t f s 1 2283 "2283"       _null_ _null_ _null_ lag _null_ _null_ _null_));
  DESCR("fetch the preceding row value");
! DATA(insert OID = 3905 (  lag PGNSP PGUID 12 1 0 0 f t f t f s 2 2283 "2283 23"       _null_ _null_ _null_ lag_with_offset _null_ _null_ _null_));
! DESCR("fetch the preceding row value");
! DATA(insert OID = 3906 (  lag PGNSP PGUID 12 1 0 0 f t f t f s 3 2283 "2283 23 2283"  _null_ _null_ _null_ lag_with_offset_and_default _null_ _null_ _null_));
  DESCR("fetch the preceding row value with default");
! DATA(insert OID = 3907 (  lead PGNSP PGUID 12 1 0 0 f t f t f s 1 2283 "2283"       _null_ _null_ _null_ lead _null_ _null_ _null_));
! DESCR("fetch the following row value");
! DATA(insert OID = 3908 (  lead PGNSP PGUID 12 1 0 0 f t f t f s 2 2283 "2283 23"       _null_ _null_ _null_ lead_with_offset _null_ _null_ _null_));
  DESCR("fetch the following row value");
! DATA(insert OID = 3909 (  lead PGNSP PGUID 12 1 0 0 f t f t f s 3 2283 "2283 23 2283"  _null_ _null_ _null_ lead_with_offset_and_default _null_ _null_ _null_));
  DESCR("fetch the following row value with default");
! DATA(insert OID = 3910 (  first_value PGNSP PGUID 12 1 0 0 f t f t f s 1 2283 "2283"  _null_ _null_ _null_ first_value _null_ _null_ _null_));
  DESCR("fetch the first row value");
! DATA(insert OID = 3911 (  last_value PGNSP PGUID 12 1 0 0 f t f t f s 1 2283 "2283"  _null_ _null_ _null_ last_value _null_ _null_ _null_));
  DESCR("fetch the last row value");
! DATA(insert OID = 3912 (  nth_value PGNSP PGUID 12 1 0 0 f t f t f s 2 2283 "2283 23" _null_ _null_ _null_ nth_value _null_ _null_ _null_));
  DESCR("fetch following row value");
