
    ɯeiH                        d Z ddlZddlmZ ddlmZmZmZmZ ddl	Z
ddlmc mc mc mc mZ ddlmZmZ ddlmZmZ ddlmZmZmZmZmZmZmZmZm Z m!Z! ddl"m#Z#m$Z$ dd	l%m&Z& dd
l'm(Z(m)Z) ejT                  dk  rddlm+Z+ nddl,m+Z+ dee-df   dee-df   deeef   fdZ. G d de      Z/ G d d      Z0	 ddee-e/f   de1ddfdZ2dejf                  dee-e/f   dee-e/f   ddfdZ4 G d d      Z5y)zWindow frames in Snowpark.    N)IntEnum)ListOptionalTupleUnion)
ExpressionLiteral)	Ascending	SortOrder)

CurrentRow
RangeFrameRowFrameSpecifiedWindowFrameUnboundedFollowingUnboundedPrecedingUnspecifiedFrameWindowExpressionWindowFrameWindowSpecDefinition)-build_expr_from_snowpark_column_or_python_valwith_src_position)ColumnOrName)parse_positional_args_to_list	publicapi)   	   )Iterablestartsnowflake.snowpark.Columnendreturnc                 V   t        | t              rC| dk(  rt               }no| t        j                  k  rt               }nQt        t        |             }n<t        | t        j                  j                        r| j                  }nt        d      t        |t              rL|dk(  rt               }||fS |t        j                  k\  rt               }||fS t        t        |            }||fS t        |t        j                  j                        r|j                  }||fS t        d      )Nr   z$start must be an integer or a Columnz"end must be an integer or a Column)
isinstanceintr   WindowUNBOUNDED_PRECEDINGr   r	   	snowflakesnowparkColumn_expression
ValueErrorUNBOUNDED_FOLLOWINGr   )r   r    boundary_startboundary_ends       [/var/www/html/glpi_dashboard/venv/lib/python3.12/site-packages/snowflake/snowpark/window.py_convert_boundary_to_exprr0   +   s    %A:'\Nf000/1N$SZ0N	E9--44	5**?@@#s!8%<L <'' F...-/L <'' #3s8,L <'' 
C++22	3 <'' =>>    c                   B    e Zd Zej                   Zej                  ZdZy)WindowRelativePositionr   N)__name__
__module____qualname__sysmaxsizer&   r,   CURRENT_ROW r1   r/   r3   r3   J   s    ;;,++Kr1   r3   c                      e Zd ZU dZej
                  Zeed<   eZeed<   ej                  Z	eed<   e	Z
eed<   ej                  Zeed<   eZeed<   eedd	d
eeee   f   deddfd              Zeedd	d
eeee   f   deddfd              Zee	 ddeeef   deeef   deddfd              Zee	 ddeedf   deedf   deddfd              Zedd       ZeZeZeZeZy)r%   ar  
    Contains functions to form :class:`WindowSpec`. See
    `Snowflake Window functions <https://docs.snowflake.com/en/sql-reference/functions-analytic.html#window-functions>`_ for reference.

    Examples::

        >>> from snowflake.snowpark.functions import col, avg
        >>> window1 = Window.partition_by("value").order_by("key").rows_between(Window.CURRENT_ROW, 2)
        >>> window2 = Window.order_by(col("key").desc()).range_between(Window.UNBOUNDED_PRECEDING, Window.UNBOUNDED_FOLLOWING)
        >>> df = session.create_dataframe([(1, "1"), (2, "2"), (1, "3"), (2, "4")], schema=["key", "value"])
        >>> df.select(avg("value").over(window1).as_("window1"), avg("value").over(window2).as_("window2")).sort("window1").collect()
        [Row(WINDOW1=1.0, WINDOW2=2.5), Row(WINDOW1=2.0, WINDOW2=2.5), Row(WINDOW1=3.0, WINDOW2=2.5), Row(WINDOW1=4.0, WINDOW2=2.5)]
    r&   unboundedPrecedingr,   unboundedFollowingr9   
currentRowT	_emit_astcolsr@   r!   
WindowSpecc                 H    t        j                         j                  |d| iS )z
        Returns a :class:`WindowSpec` object with partition by clause.

        Args:
            cols: A column, as :class:`str`, :class:`~snowflake.snowpark.column.Column`
                or a list of those.
        r@   )r%   _specpartition_byr@   rA   s     r/   rE   zWindow.partition_byk   s       ||~**DFIFFr1   c                 H    t        j                         j                  |d| iS )z
        Returns a :class:`WindowSpec` object with order by clause.

        Args:
            cols: A column, as :class:`str`, :class:`~snowflake.snowpark.column.Column`
                or a list of those.
        r@   )r%   rD   order_byrF   s     r/   rH   zWindow.order_by}   s       ||~&&B	BBr1   r   r    c                 N    t         j                         j                  | ||      S )ar  
        Returns a :class:`WindowSpec` object with the row frame clause.

        Args:
            start: The relative position from the current row as a boundary start (inclusive).
                The frame is unbounded if this is :attr:`Window.UNBOUNDED_PRECEDING`, or any
                value less than or equal to -9223372036854775807 (``-sys.maxsize``).
            end: The relative position from the current row as a boundary end (inclusive).
                The frame is unbounded if this is :attr:`Window.UNBOUNDED_FOLLOWING`, or any
                value greater than or equal to 9223372036854775807 (``sys.maxsize``).

        Note:
            You can use :attr:`Window.UNBOUNDED_PRECEDING`, :attr:`Window.UNBOUNDED_FOLLOWING`,
            and :attr:`Window.CURRENT_ROW` to specify ``start`` and ``end``, instead of using
            integral values directly.
        r?   )r%   rD   rows_betweenr   r    r@   s      r/   rJ   zWindow.rows_between   s"    . ||~**5#*KKr1   r   c                 N    t         j                         j                  | ||      S )ar  
        Returns a :class:`WindowSpec` object with the range frame clause.
        ``start`` and ``end`` can be

            - an integer representing the relative position from the current row, or

            - :attr:`Window.UNBOUNDED_PRECEDING`, :attr:`Window.UNBOUNDED_FOLLOWING`
              and :attr:`Window.CURRENT_ROW`, which represent unbounded preceding,
              unbounded following and current row respectively, or

            - a :class:`~snowflake.snowpark.column.Column` object created by
              :func:`~snowflake.snowpark.functions.make_interval` to use
              `Interval constants <https://docs.snowflake.com/en/sql-reference/data-types-datetime#interval-constants>`_.
              Interval constants can only be used with this function when the order by column is TIMESTAMP or DATE type
              See more details how to use interval constants in
              `RANGE BETWEEN <https://docs.snowflake.com/sql-reference/functions-analytic#label-range-between-syntax-desc>`_
              clause. However, you cannot mix the numeric values and interval constants in the same range frame clause.

        Args:
            start: The relative position from the current row as a boundary start (inclusive).
                The frame is unbounded if this is :attr:`Window.UNBOUNDED_PRECEDING`, or any
                value less than or equal to -9223372036854775807 (``-sys.maxsize``).
            end: The relative position from the current row as a boundary end (inclusive).
                The frame is unbounded if this is :attr:`Window.UNBOUNDED_FOLLOWING`, or any
                value greater than or equal to 9223372036854775807 (``sys.maxsize``).

        Example 1
            Use numeric values to specify the range frame:

            >>> from snowflake.snowpark.functions import col, count, make_interval
            >>>
            >>> df = session.range(5)
            >>> window = Window.order_by("id").range_between(-1, Window.CURRENT_ROW)
            >>> df.select(col("id"), count("id").over(window).as_("count")).show()
            ------------------
            |"ID"  |"COUNT"  |
            ------------------
            |0     |1        |
            |1     |2        |
            |2     |2        |
            |3     |2        |
            |4     |2        |
            ------------------
            <BLANKLINE>

        Example 2
            Use interval constants to specify the range frame:

            >>> import datetime
            >>> from snowflake.snowpark.types import StructType, StructField, TimestampType, TimestampTimeZone
            >>>
            >>> df = session.create_dataframe(
            ...    [
            ...        datetime.datetime(2021, 12, 21, 9, 12, 56),
            ...        datetime.datetime(2021, 12, 21, 8, 12, 56),
            ...        datetime.datetime(2021, 12, 21, 7, 12, 56),
            ...        datetime.datetime(2021, 12, 21, 6, 12, 56),
            ...    ],
            ...    schema=StructType([StructField("a", TimestampType(TimestampTimeZone.NTZ))]),
            ... )
            >>> window = Window.order_by(col("a").desc()).range_between(-make_interval(hours=1), make_interval(hours=1))
            >>> df.select(col("a"), count("a").over(window).as_("count")).show()
            ---------------------------------
            |"A"                  |"COUNT"  |
            ---------------------------------
            |2021-12-21 09:12:56  |2        |
            |2021-12-21 08:12:56  |3        |
            |2021-12-21 07:12:56  |3        |
            |2021-12-21 06:12:56  |2        |
            ---------------------------------
            <BLANKLINE>

        r?   )r%   rD   range_betweenrK   s      r/   rM   zWindow.range_between   s#    ` ||~++E3)+LLr1   c                  ,    t        g g t                     S N)rB   r   r:   r1   r/   rD   zWindow._spec   s    "b"2"455r1   NT)r!   rB   )r4   r5   r6   __doc__r3   r&   r$   __annotations__r<   r,   r=   r9   r>   staticmethodr   r   r   r   boolrE   rH   rJ   rM   rD   orderBypartitionByrangeBetweenrowsBetweenr:   r1   r/   r%   r%   P   s     6III11  6III11 .99K9!J! G\"$
G
 G 
G  G   C\"$
C
 C 
C  C   LS001L3../L L 
	L  L.  NMS556NM3334NM NM 
	NM  NM` 6 6 GK LKr1   r%   valuenamec                 f    ddl m} t        | t              st        | |      st	        | d      y y )Nr   )r)   z must be an integer or a Column)snowflake.snowparkr)   r#   r$   r+   )rY   rZ   r)   s      r/    _check_window_position_parameterr]     s6     *eS!*UF*CD6!@ABB +D!r1   astc                    t        |t              rm|t        j                  k(  rd| j                  _        |t        j
                  k(  rd| j                  _        |t        j                  k(  r<d| j                  _        n*t        | j                  j                  j                  |       t        |t              rn|t        j                  k(  rd| j                  _        |t        j
                  k(  rd| j                  _        |t        j                  k(  rd| j                  _        yyt        | j                  j                  j                  |       y)a  
    Helper function for AST generation to fill relative positions for window spec range-between, and rows-between. If value passed in for start/end is
    of type WindowRelativePosition encoding will preserve for e.g. Window.CURRENT_ROW the syntax.

    Args:
        ast: AST where to fill start/end.
        start: relative start position, integer or special enum value.
        end: relative end position, integer or special enum value.
    TN)r#   r3   r9   r   %window_relative_position__current_rowr,   -window_relative_position__unbounded_followingr&   -window_relative_position__unbounded_precedingr   "window_relative_position__positionnr    )r^   r   r    s      r/   -_fill_window_spec_ast_with_relative_positionsre     s     %/0*666>BCII;*>>>FJCIIC*>>>FJCIIC5II88::E	
 #-.(444<@CGG9(<<<DHCGGA(<<<DHCGGA = 	6GG6688#	
r1   c                   z   e Zd ZdZ	 ddee   dee   dedee	j                     ddf
dZed	d
deeee   f   dedd fd       Zed	d
deeee   f   dedd fd       Ze	 ddeeef   deeef   dedd fd       Ze	 ddeedf   deedf   dedd fd       Z	 	 ddedee	j.                     deddfdZeZeZeZeZy)rB   z!Represents a window frame clause.Npartition_spec
order_specframer^   r!   c                     || _         || _        || _        |)t        j                         }t        |j                        }|| _        y rO   )rg   rh   ri   protoWindowSpecExprr   window_spec_empty_ast)selfrg   rh   ri   r^   
window_asts         r/   __init__zWindowSpec.__init__8  sD     -$
;&&(C*3+@+@AJ	r1   Tr?   rA   r@   c                
   t        | }|D cg c]o  }t        |t        j                  j                  j
                        r|j                  n2t        j                  j                  j                  |      j                  q }}d}|rt        j                         }t        |j                        }|j                  j                  | j                         |D ]  }|j                  j                         }t        |t        j                  j                  j
                        r|n*t        j                  j                  j                  |d      }	t!        ||	        t#        || j$                  | j&                  |      S c c}w )z
        Returns a new :class:`WindowSpec` object with the new partition by clause.

        See Also:
            - :func:`Window.partition_by`
        N_caller_namer^   )r   r#   r'   r(   columnr)   r*   rk   rl   r   window_spec_partition_bywndCopyFromrn   rA   addr   rB   rh   ri   )
ro   r@   rA   exprserg   r^   rp   col_astcols
             r/   rE   zWindowSpec.partition_byI  sK    .t4
 	
  !Y//66==> MM##**11!4@@A
 
 &&(C*3+G+GHJNN##DII. L$//--/ "!Y%7%7%>%>%E%EF "++2299!$9O 
 >gsKL .$//4::3OO-
s   A4F c                F   t        | }g }|D ]  }t        |t              rU|j                  t	        t
        j                  j                  j                  |      j                  t                            it        |t
        j                  j                  j                        st        |j                  t              r|j                  |j                         t        |j                  t              s|j                  t	        |j                  t                             d}|rt        j                         }t        |j                        }|j                   j#                  | j$                         |D ]  }|j&                  j)                         }t        |t
        j                  j                  j                        r|n*t
        j                  j                  j                  |d      }	t+        ||	        t-        | j.                  || j0                  |      S )z
        Returns a new :class:`WindowSpec` object with the new order by clause.

        See Also:
            - :func:`Window.order_by`
        Nrs   ru   )r   r#   strappendr   r'   r(   rv   r)   r*   r
   r   rk   rl   r   window_spec_order_byrx   ry   rn   rA   rz   r   rB   rg   ri   )
ro   r@   rA   r{   rh   r|   r^   rp   r}   r~   s
             r/   rH   zWindowSpec.order_byq  s    .t4
 	MA!S!!!!**1188;GG
 Ay1188??@ammY7%%amm4z:%%iy{&KL	M &&(C*3+C+CDJNN##DII. L$//--/ "!Y%7%7%>%>%E%EF "++2299!$9O 
 >gsKL $--z4::3OOr1   r   r    c           	      z   t        |d       t        |d       t        ||      \  }}d}|r[t        j                         }t	        |j
                        }t        |||       |j                  j                  | j                         t        | j                  | j                  t        t               ||      |      S )z
        Returns a new :class:`WindowSpec` object with the new row frame clause.

        See Also:
            - :func:`Window.rows_between`
        r   r    Nru   )r]   r0   rk   rl   r   window_spec_rows_betweenre   rx   ry   rn   rB   rg   rh   r   r   )ro   r   r    r@   r-   r.   r^   rp   s           r/   rJ   zWindowSpec.rows_between  s     	)8(e4'@'L$ &&(C*3+G+GHJ9*eSQNN##DII.OO ^\J	
 	
r1   r   c           	      z   t        |d       t        |d       d}|r[t        j                         }t        |j                        }t        |||       |j                  j                  | j                         t        ||      \  }}t        | j                  | j                  t        t               ||      |      S )z
        Returns a new :class:`WindowSpec` object with the new range frame clause.

        See Also:
            - :func:`Window.range_between`
        r   r    Nru   )r]   rk   rl   r   window_spec_range_betweenre   rx   ry   rn   r0   rB   rg   rh   r   r   )ro   r   r    r@   r^   rp   r-   r.   s           r/   rM   zWindowSpec.range_between  s     	)8(e4 &&(C*3+H+HIJ9*eSQNN##DII.'@'L$OO ~|L	
 	
r1   	aggregatez snowflake.snowpark.column.Columnc                     t        | j                  | j                  | j                        }t        j
                  j                  j                  t        ||      ||      S )N)rn   r@   )	r   rg   rh   ri   r'   r(   rv   r)   r   )ro   r   r^   r@   specs        r/   _with_aggregatezWindowSpec._with_aggregate  sR     $D$7$7$**U!!((//Y-C9 0 
 	
r1   rO   rP   )NT)r4   r5   r6   rQ   r   r   r   r   r   rk   rl   rq   r   r   r   r   rT   rE   rH   r$   r3   rJ   rM   Exprr   rU   rV   rW   rX   r:   r1   r/   rB   rB   5  s   + /3Z( O 	
 e**+ 
"  %P\"$
%P %P 
%P %PN  ,P\"$
,P ,P 
,P ,P\ 
 	
S001
 3../
 	

 

 
@ 
 	
S556
 3334
 	

 

 
H %)		
	
 ejj!	
 		

 
,	
 GK LKr1   rB   ) )6rQ   r7   enumr   typingr   r   r   r   r\   r'   4snowflake.snowpark._internal.proto.generated.ast_pb2r(   	_internalrk   	generatedast_pb20snowflake.snowpark._internal.analyzer.expressionr   r	   5snowflake.snowpark._internal.analyzer.sort_expressionr
   r   7snowflake.snowpark._internal.analyzer.window_expressionr   r   r   r   r   r   r   r   r   r   &snowflake.snowpark._internal.ast.utilsr   r   'snowflake.snowpark._internal.type_utilsr   "snowflake.snowpark._internal.utilsr   r   version_infor   collections.abcr$   r0   r3   r%   r   r]   rl   re   rB   r:   r1   r/   <module>r      s6   ! 
  / /  D D D P V   A W
 v((112(	s//	0( :z!"(>W q qj <>C,,-C58C	C%
			%
,,-%
 
s**	+%
 
	%
P| |r1   