
    ɯei                       d dl Z d dlZd dlZd dlZd dlZd dlmZ d dlmZ d dl	m
Z
mZmZmZmZmZmZmZ d dl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mZmZm Z  d dl!m"Z" d dl#m$Z$ d d	l%m&Z& d d
l'm(Z(m)Z)m*Z*m+Z+ d dl,m-Z- d dl.m/Z/ d dl0m1Z1 d dl2m3Z3m4Z4m5Z5m6Z6m7Z7m8Z8m9Z9 d dl:m;Z; d dl<m=Z= d dl>m?Z?m@Z@mAZAmBZB d dlCmDZD d dlEmFZFmGZGmHZHmIZImJZJmKZKmLZLmMZMmNZNmOZOmPZPmQZQmRZRmSZSmTZTmUZUmVZVmWZWmXZXmYZY d dlZm[Z[m\Z\m]Z] d dl^m_Z_ d dl`maZambZb d dlcmdZdmeZemfZfmgZgmhZh d dlimjZj d dlkmlZl d dlmmnZnmoZompZpmqZq ej                  dk  rd dl	msZs nd dltmsZs  eeu      ZvdZwddd d!d"d#d$Zxd%d&d'd'd(d%d)d*d+d,d-d.Zyd/Zzd0e{d1e{fd2Z|d3e}d1e}fd4Z~ G d5 d6      Zy)7    N)defaultdict)	getLogger)AnyDictListLiteralOptionalTupleUnionCallable)datetime)convert_value_to_sql_optioncreate_file_format_statement$drop_file_format_if_exists_statementinfer_schema_statementquote_name_without_upper_casing)	Attribute)ReadFileNode)Alias)build_expr_from_python_valbuild_proto_from_struct_typebuild_table_namewith_src_position)JDBC)DataSourcePartitioner)
Connection)STATEMENT_PARAMS_DATA_SOURCEDATA_SOURCE_DBAPI_SIGNATURE"create_data_source_table_and_stagelocal_ingestion!STATEMENT_PARAMS_DATA_SOURCE_JDBCDATA_SOURCE_JDBC_SIGNATUREget_jdbc_dbms)SnowparkClientExceptionMessages)set_api_call_source)ColumnOrNameconvert_sf_to_sp_typeconvert_sp_to_sf_typemost_permissive_type)get_types_from_type_hints)SNOWURL_PREFIXSTAGE_PREFIXXML_ROW_TAG_STRINGXML_ROW_DATA_COLUMN_NAMEXML_READER_FILE_PATHXML_READER_API_SIGNATUREXML_READER_SQL_COMMENTINFER_SCHEMA_FORMAT_TYPESSNOWFLAKE_PATH_PREFIXESTempObjectTypeget_aliased_option_nameget_copy_into_table_optionsget_stage_partsis_in_stored_procedure&parse_positional_args_to_list_variadicprivate_preview	publicapirandom_name_for_temp_objectwarningexperimental)METADATA_COLUMN_TYPESColumn_to_col_if_str)	DataFrame)SnowparkSessionException SnowparkDataframeReaderException)sql_exprcolconcatlitto_file)MockServerConnection)Table)
StructTypeTimestampTimeZoneVariantTypeStructField)   	   )Iterable)JSONtime_travel_mode	statementoffset	timestamptimestamp_typestream)TIME_TRAVEL_MODE	STATEMENTOFFSET	TIMESTAMPTIMESTAMP_TYPESTREAMFIELD_DELIMITERPARSE_HEADERPATTERNINFER_SCHEMARECORD_DELIMITERFIELD_OPTIONALLY_ENCLOSED_BYNULL_IFDATE_FORMATTIMESTAMP_FORMAT)	DELIMITERHEADERPATHGLOBFILTERFILENAMEPATTERNINFERSCHEMASEPLINESEPQUOTE	NULLVALUE
DATEFORMATTIMESTAMPFORMATrP   pathreturnc                 x    | j                  d      t        fdt        D              st        d|  d      | S )Nz"'c              3   @   K   | ]  }j                  |        y wN)
startswith).0prefixstripped_paths     e/var/www/html/glpi_dashboard/venv/lib/python3.12/site-packages/snowflake/snowpark/dataframe_reader.py	<genexpr>z'_validate_stage_path.<locals>.<genexpr>   s     VF}''/Vs   'zc' is an invalid Snowflake stage location. DataFrameReader can only read files from stage locations.)stripanyr3   
ValueError)rt   r|   s    @r}   _validate_stage_pathr      sA    JJu%MV>UVVvxy
 	
 K    optionsc                 &   i }t               }d| v rRd| v r!| d   j                         dk(  rt        d      d| v rt        d      d|d<   | d   |d	<   |j                  d       t        j                         D ]  \  }}|| v s||vs| |   ||<    |S )
aB  
    Extract time travel options from DataFrameReader options.

    Special handling for 'AS-OF-TIMESTAMP' (PySpark compatibility):
    - Automatically sets time_travel_mode to 'at'
    - Cannot be used with time_travel_mode='before' (raises error)
    - Cannot be mixed with regular 'timestamp' option (raises error)
    zAS-OF-TIMESTAMPrZ   beforezBCannot use 'as-of-timestamp' option with time_travel_mode='before'r]   z:Cannot use both 'as-of-timestamp' and 'timestamp' options.atrT   rW   )setlowerr   add_TIME_TRAVEL_OPTIONS_PARAMS_MAPitems)r   resultexcluded_keys
option_key
param_names        r}   !_extract_time_travel_from_optionsr      s     FEM G#')*+113x?T  '!L  &*!"%&78{+&"A"G"G"I 5
J Z}%D!(!4F:5 Mr   c            )          e Zd ZdZe	 dSdddeddfd       Zed	        Zde	e
e   e
e   f   fd
Ze	 dSddddddddeeee   f   dedeed      dee   dee   deeeef      deeeef      dee   defd       ZedSdededd fd       Zedddee   dedd fd       Zedee   fd       Zej8                  deddfd       Ze	 dSded   dedd fd       ZedTd ee   dedefd!       ZedSd ededefd"       Z edSd ededefd#       Z!edSd ededefd$       Z"edSd ededefd%       Z#edSd ededefd&       Z$edSd ededefd'       Z%edSd(ede&dedd fd)       Z'e	 dTd*ee(   dedd fd+       Z)d edede	e
e
e
e*f   fd,Z+d-ede	e
e
e
f   fd.Z,d ededefd/Z- e.d01      edddddddd2d2ddddd3d4ed5e/d6ee/   d7ee   d8ee   d9ee   d:eeeef      d;eeeef      d<ee   d=ee   d>ee   d?eeeef      d@ee
e      dAeeee
e   f      dedef dB              Z0 e.dC1      edddddddd2dDdddddEdFdddGdHe1dI   d7ee   d8ee   d9ee   d:eeeef      d;eeeef      d<ee   dJee   d=ee   d>ee   d?eeeef      d@ee
e      dAeeee
e   f      d5ee/   dKedLedMee/   dedef&dN              Z2e e3dO1      dSd ededefdP              Z4dSdQededefdRZ5y)UDataFrameReaderaW=  Provides methods to load data in various supported formats from a Snowflake
    stage to a :class:`DataFrame`. The paths provided to the DataFrameReader must refer
    to Snowflake stages.

    To use this object:

    1. Access an instance of a :class:`DataFrameReader` by using the
    :attr:`Session.read` property.

    2. Specify any `format-specific options <https://docs.snowflake.com/en/sql-reference/sql/create-file-format.html#format-type-options-formattypeoptions>`_ and `copy options <https://docs.snowflake.com/en/sql-reference/sql/copy-into-table.html#copy-options-copyoptions>`_
    by calling the :func:`option` or :func:`options` method. These methods return a
    DataFrameReader that is configured with these options. (Note that although
    specifying copy options can make error handling more robust during the reading
    process, it may have an effect on performance.)

    3. Specify the schema of the data that you plan to load by constructing a
    :class:`types.StructType` object and passing it to the :func:`schema` method if the file format is CSV. Other file
    formats such as JSON, XML, Parquet, ORC, and AVRO don't accept a schema.
    This method returns a :class:`DataFrameReader` that is configured to read data that uses the specified schema.
    Currently, inferring schema is also supported for CSV and JSON formats as a preview feature open to all accounts.

    4. Specify the format of the data by calling the method named after the format
    (e.g. :func:`csv`, :func:`json`, etc.). These methods return a :class:`DataFrame`
    that is configured to load data in the specified format.

    5. Call a :class:`DataFrame` method that performs an action (e.g.
    :func:`DataFrame.collect`) to load the data from the file.

    The following examples demonstrate how to use a DataFrameReader.
            >>> # Create a temp stage to run the example code.
            >>> _ = session.sql("CREATE or REPLACE temp STAGE mystage").collect()

    Example 1:
        Loading the first two columns of a CSV file and skipping the first header line:

            >>> from snowflake.snowpark.types import StructType, StructField, IntegerType, StringType, FloatType
            >>> _ = session.file.put("tests/resources/testCSV.csv", "@mystage", auto_compress=False)
            >>> # Define the schema for the data in the CSV file.
            >>> user_schema = StructType([StructField("a", IntegerType()), StructField("b", StringType()), StructField("c", FloatType())])
            >>> # Create a DataFrame that is configured to load data from the CSV file.
            >>> df = session.read.options({"field_delimiter": ",", "skip_header": 1}).schema(user_schema).csv("@mystage/testCSV.csv")
            >>> # Load the data into the DataFrame and return an array of rows containing the results.
            >>> df.collect()
            [Row(A=2, B='two', C=2.2)]

    Example 2:
        Loading a gzip compressed json file:

            >>> _ = session.file.put("tests/resources/testJson.json", "@mystage", auto_compress=True)
            >>> # Create a DataFrame that is configured to load data from the gzipped JSON file.
            >>> json_df = session.read.option("compression", "gzip").json("@mystage/testJson.json.gz")
            >>> # Load the data into the DataFrame and return an array of rows containing the results.
            >>> json_df.show()
            -----------------------
            |"$1"                 |
            -----------------------
            |{                    |
            |  "color": "Red",    |
            |  "fruit": "Apple",  |
            |  "size": "Large"    |
            |}                    |
            -----------------------
            <BLANKLINE>


    In addition, if you want to load only a subset of files from the stage, you can use the
    `pattern <https://docs.snowflake.com/en/sql-reference/sql/copy-into-table.html#loading-using-pattern-matching>`_
    option to specify a regular expression that matches the files that you want to load.

    Example 3:
        Loading only the CSV files from a stage location:

            >>> from snowflake.snowpark.types import StructType, StructField, IntegerType, StringType
            >>> from snowflake.snowpark.functions import col
            >>> _ = session.file.put("tests/resources/*.csv", "@mystage", auto_compress=False)
            >>> # Define the schema for the data in the CSV files.
            >>> user_schema = StructType([StructField("a", IntegerType()), StructField("b", StringType()), StructField("c", FloatType())])
            >>> # Create a DataFrame that is configured to load data from the CSV files in the stage.
            >>> csv_df = session.read.option("pattern", ".*V[.]csv").schema(user_schema).csv("@mystage").sort(col("a"))
            >>> # Load the data into the DataFrame and return an array of rows containing the results.
            >>> csv_df.collect()
            [Row(A=1, B='one', C=1.2), Row(A=2, B='two', C=2.2), Row(A=3, B='three', C=3.3), Row(A=4, B='four', C=4.4)]

    To load Parquet, ORC and AVRO files, no schema is accepted because the schema will be automatically inferred.
    Inferring the schema can be disabled by setting option "infer_schema" to ``False``. Then you can use ``$1`` to access
    the column data as an OBJECT.

    Example 4:
        Loading a Parquet file with inferring the schema.
            >>> from snowflake.snowpark.functions import col
            >>> _ = session.file.put("tests/resources/test.parquet", "@mystage", auto_compress=False)
            >>> # Create a DataFrame that uses a DataFrameReader to load data from a file in a stage.
            >>> df = session.read.parquet("@mystage/test.parquet").where(col('"num"') == 2)
            >>> # Load the data into the DataFrame and return an array of rows containing the results.
            >>> df.collect()
            [Row(str='str2', num=2)]

    Example 5:
        Loading an ORC file and infer the schema:
            >>> from snowflake.snowpark.functions import col
            >>> _ = session.file.put("tests/resources/test.orc", "@mystage", auto_compress=False)
            >>> # Create a DataFrame that uses a DataFrameReader to load data from a file in a stage.
            >>> df = session.read.orc("@mystage/test.orc").where(col('"num"') == 2)
            >>> # Load the data into the DataFrame and return an array of rows containing the results.
            >>> df.collect()
            [Row(str='str2', num=2)]

    Example 6:
        Loading an AVRO file and infer the schema:
            >>> from snowflake.snowpark.functions import col
            >>> _ = session.file.put("tests/resources/test.avro", "@mystage", auto_compress=False)
            >>> # Create a DataFrame that uses a DataFrameReader to load data from a file in a stage.
            >>> df = session.read.avro("@mystage/test.avro").where(col('"num"') == 2)
            >>> # Load the data into the DataFrame and return an array of rows containing the results.
            >>> df.collect()
            [Row(str='str2', num=2)]

    Example 7:
        Loading a Parquet file without inferring the schema:
            >>> from snowflake.snowpark.functions import col
            >>> _ = session.file.put("tests/resources/test.parquet", "@mystage", auto_compress=False)
            >>> # Create a DataFrame that uses a DataFrameReader to load data from a file in a stage.
            >>> df = session.read.option("infer_schema", False).parquet("@mystage/test.parquet").where(col('$1')["num"] == 2)
            >>> # Load the data into the DataFrame and return an array of rows containing the results.
            >>> df.show()
            -------------------
            |"$1"             |
            -------------------
            |{                |
            |  "num": 2,      |
            |  "str": "str2"  |
            |}                |
            -------------------
            <BLANKLINE>

    Loading JSON and XML files doesn't support schema either. You also need to use ``$1`` to access the column data as an OBJECT.

    Example 8:
        Loading a JSON file:
            >>> from snowflake.snowpark.functions import col, lit
            >>> _ = session.file.put("tests/resources/testJson.json", "@mystage", auto_compress=False)
            >>> # Create a DataFrame that uses a DataFrameReader to load data from a file in a stage.
            >>> df = session.read.json("@mystage/testJson.json").where(col("$1")["fruit"] == lit("Apple"))
            >>> # Load the data into the DataFrame and return an array of rows containing the results.
            >>> df.show()
            -----------------------
            |"$1"                 |
            -----------------------
            |{                    |
            |  "color": "Red",    |
            |  "fruit": "Apple",  |
            |  "size": "Large"    |
            |}                    |
            |{                    |
            |  "color": "Red",    |
            |  "fruit": "Apple",  |
            |  "size": "Large"    |
            |}                    |
            -----------------------
            <BLANKLINE>

    Example 9:
        Loading an XML file:
            >>> _ = session.file.put("tests/resources/test.xml", "@mystage", auto_compress=False)
            >>> # Create a DataFrame that uses a DataFrameReader to load data from a file in a stage.
            >>> df = session.read.xml("@mystage/test.xml")
            >>> # Load the data into the DataFrame and return an array of rows containing the results.
            >>> df.show()
            ---------------------
            |"$1"               |
            ---------------------
            |<test>             |
            |  <num>1</num>     |
            |  <str>str1</str>  |
            |</test>            |
            |<test>             |
            |  <num>2</num>     |
            |  <str>str2</str>  |
            |</test>            |
            ---------------------
            <BLANKLINE>

    Example 10:
        Loading a CSV file with an already existing FILE_FORMAT:
            >>> from snowflake.snowpark.types import StructType, StructField, IntegerType, StringType
            >>> _ = session.sql("create file format if not exists csv_format type=csv skip_header=1 null_if='none';").collect()
            >>> _ = session.file.put("tests/resources/testCSVspecialFormat.csv", "@mystage", auto_compress=False)
            >>> # Define the schema for the data in the CSV files.
            >>> schema = StructType([StructField("ID", IntegerType()),StructField("USERNAME", StringType()),StructField("FIRSTNAME", StringType()),StructField("LASTNAME", StringType())])
            >>> # Create a DataFrame that is configured to load data from the CSV files in the stage.
            >>> df = session.read.schema(schema).option("format_name", "csv_format").csv("@mystage/testCSVspecialFormat.csv")
            >>> # Load the data into the DataFrame and return an array of rows containing the results.
            >>> df.collect()
            [Row(ID=0, USERNAME='admin', FIRSTNAME=None, LASTNAME=None), Row(ID=1, USERNAME='test_user', FIRSTNAME='test', LASTNAME='user')]

    Example 11:
        Querying metadata for staged files:
            >>> from snowflake.snowpark.column import METADATA_FILENAME, METADATA_FILE_ROW_NUMBER
            >>> df = session.read.with_metadata(METADATA_FILENAME, METADATA_FILE_ROW_NUMBER.as_("ROW NUMBER")).schema(user_schema).csv("@mystage/testCSV.csv")
            >>> # Load the data into the DataFrame and return an array of rows containing the results.
            >>> df.show()
            --------------------------------------------------------
            |"METADATA$FILENAME"  |"ROW NUMBER"  |"A"  |"B"  |"C"  |
            --------------------------------------------------------
            |testCSV.csv          |1             |1    |one  |1.2  |
            |testCSV.csv          |2             |2    |two  |2.2  |
            --------------------------------------------------------
            <BLANKLINE>

    Example 12:
        Inferring schema for csv and json files (Preview Feature - Open):
            >>> # Read a csv file without a header
            >>> df = session.read.option("INFER_SCHEMA", True).csv("@mystage/testCSV.csv")
            >>> df.show()
            ----------------------
            |"c1"  |"c2"  |"c3"  |
            ----------------------
            |1     |one   |1.2   |
            |2     |two   |2.2   |
            ----------------------
            <BLANKLINE>

            >>> # Read a csv file with header and parse the header
            >>> _ = session.file.put("tests/resources/testCSVheader.csv", "@mystage", auto_compress=False)
            >>> df = session.read.option("INFER_SCHEMA", True).option("PARSE_HEADER", True).csv("@mystage/testCSVheader.csv")
            >>> df.show()
            ----------------------------
            |"id"  |"name"  |"rating"  |
            ----------------------------
            |1     |one     |1.2       |
            |2     |two     |2.2       |
            ----------------------------
            <BLANKLINE>

            >>> df = session.read.option("INFER_SCHEMA", True).json("@mystage/testJson.json")
            >>> df.show()
            ------------------------------
            |"color"  |"fruit"  |"size"  |
            ------------------------------
            |Red      |Apple    |Large   |
            |Red      |Apple    |Large   |
            ------------------------------
            <BLANKLINE>

    Example 13:
        Reading an XML file with a row tag
            >>> # Each XML record is extracted as a separate row,
            >>> # and each field within that record becomes a separate column of type VARIANT
            >>> _ = session.file.put("tests/resources/nested.xml", "@mystage", auto_compress=False)
            >>> df = session.read.option("rowTag", "tag").xml("@mystage/nested.xml")
            >>> df.show()
            -----------------------
            |"'test'"             |
            -----------------------
            |{                    |
            |  "num": "1",        |
            |  "obj": {           |
            |    "bool": "true",  |
            |    "str": "str2"    |
            |  },                 |
            |  "str": "str1"      |
            |}                    |
            -----------------------
            <BLANKLINE>

            >>> # Query nested fields using dot notation
            >>> from snowflake.snowpark.functions import col
            >>> df.select(
            ...     "'test'.num", "'test'.str", col("'test'.obj"), col("'test'.obj.bool")
            ... ).show()
            ------------------------------------------------------------------------------------------------------
            |"""'TEST'"":""NUM"""  |"""'TEST'"":""STR"""  |"""'TEST'"":""OBJ"""  |"""'TEST'"":""OBJ"".""BOOL"""  |
            ------------------------------------------------------------------------------------------------------
            |"1"                   |"str1"                |{                     |"true"                         |
            |                      |                      |  "bool": "true",     |                               |
            |                      |                      |  "str": "str2"       |                               |
            |                      |                      |}                     |                               |
            ------------------------------------------------------------------------------------------------------
            <BLANKLINE>
    Tsessionz"snowflake.snowpark.session.Session	_emit_astru   Nc                    || _         d | _        i | _        d | _        d | _        d | _        d | _        d | _        d | _        ddg| _	        d | _
        |r1t        j                         }t        |j                         || _
        y y )Njdbcdbapi)_session_user_schema_cur_options
_file_path
_file_type_metadata_cols_infer_schema_transformations_infer_schema_target_columns_DataFrameReader__format_data_source_format_astprotoExprr   dataframe_reader)selfr   r   readers       r}   __init__zDataFrameReader.__init__  s      26,.)-)-@D  	* BF)'+$*G#4 	ZZ\Ff556DI r   c                 `    | j                   t        v r| j                  j                  dd      S y)Nrc   TF)r   r2   r   getr   s    r}   _infer_schemazDataFrameReader._infer_schema  s-     ??77$$((>>r   c           
         | j                   rH| j                   D cg c]2  }| j                  j                  j                  |j                  i       4 }}ng }g }dt
        dt        fd}	 | j                   xs g D cg c]A  }t        |j                         j                  t         ||      j                                  C }}||fS c c}w c c}w # t        $ r$ t        dt        j                          d|       w xY w)N	unaliasedru   c                     t        | t              rTt        | j                  t              r | j                  j                  j
                  S | j                         j                  S | S rx   )
isinstancer@   _expressionr   childsql_namedname)r   s    r}   _get_unaliased_namezMDataFrameReader._get_metadata_project_and_schema.<locals>._get_unaliased_name  sO    )V,i33U;$0066::: '')...r   z1Metadata column name is not supported. Supported z, Got )r   r   	_analyzeranalyzer   r&   strr   r   r   r?   upperKeyErrorr   keys)r   rF   metadata_projectmetadata_schemar   metadata_cols         r}    _get_metadata_project_and_schemaz0DataFrameReader._get_metadata_project_and_schema  s     ..  ''//D   
  "	< 	C 		 %)$7$7$=2
 !	  '')..)*=l*K*Q*Q*STO   00; "  	CDYD^D^D`Caaghxgyz 	s$   7C*C <ACC C -C?rT   rU   rV   rW   rX   rY   r   rT   )r   r   rU   rV   rW   rX   rY   c                   d}	|r| j                   | j                  j                  j                         }	t	        |	j
                  j                  |	      }
|
j                  j                  | j                          t        |
j                  |       |||
j                  _        |||
j                  _        |||
j                  _        |t        |
j                   |       |t#        |      |
j$                  _        |||
j&                  _        |
||||||d}nt)        | j*                        } | j                  j,                  |fddi|}|r|	|	j.                  |_        |S )a  Returns a Table that points to the specified table.

        This method is an alias of :meth:`~snowflake.snowpark.session.Session.table` with
        additional support for setting time travel options via the :meth:`option` method.

        Args:
            name: Name of the table to use.
            time_travel_mode: Time travel mode, either 'at' or 'before'. Can also be set via
                ``option("time_travel_mode", "at")``.
            statement: Query ID for time travel. Can also be set via ``option("statement", "query_id")``.
            offset: Negative integer representing seconds in the past for time travel.
                Can also be set via ``option("offset", -60)``.
            timestamp: Timestamp string or datetime object for time travel.
                Can also be set via ``option("timestamp", "2023-01-01 12:00:00")`` or
                ``option("as-of-timestamp", "2023-01-01 12:00:00")``.
            timestamp_type: Type of timestamp interpretation ('NTZ', 'LTZ', or 'TZ').
                Can also be set via ``option("timestamp_type", "LTZ")``.
            stream: Stream name for time travel. Can also be set via ``option("stream", "stream_name")``.

        Note:
            Time travel options can be set either as direct parameters or via the
            :meth:`option` method, but NOT both. If any direct time travel parameter
            is provided, all time travel options will be ignored to avoid conflicts.

            PySpark Compatibility: The ``as-of-timestamp`` option automatically sets
            ``time_travel_mode="at"`` and cannot be used with ``time_travel_mode="before"``.

        Examples::

            # Using direct parameters
            >>> table = session.read.table("my_table", time_travel_mode="at", offset=-3600)  # doctest: +SKIP

            # Using options (recommended for chaining)
            >>> table = (session.read  # doctest: +SKIP
            ...     .option("time_travel_mode", "at")
            ...     .option("offset", -3600)
            ...     .table("my_table"))

            # PySpark-style as-of-timestamp (automatically sets mode to "at")
            >>> table = session.read.option("as-of-timestamp", "2023-01-01 12:00:00").table("my_table")  # doctest: +SKIP

            # timestamp_type automatically set to "TZ" due to timezone info
            >>> import datetime, pytz  # doctest: +SKIP
            >>> tz_aware = datetime.datetime(2023, 1, 1, 12, 0, 0, tzinfo=pytz.UTC)  # doctest: +SKIP
            >>> table1 = session.read.table("my_table", time_travel_mode="at", timestamp=tz_aware)  # doctest: +SKIP

            # timestamp_type remains "NTZ" (user's explicit choice respected)
            >>> table2 = session.read.table("my_table", time_travel_mode="at", timestamp=tz_aware, timestamp_type="NTZ")  # doctest: +SKIP

            # Mixing options and parameters (direct parameters completely override options)
            >>> table = (session.read  # doctest: +SKIP
            ...     .option("time_travel_mode", "before")  # This will be IGNORED
            ...     .option("offset", -60)                 # This will be IGNORED
            ...     .table("my_table", time_travel_mode="at", offset=-3600))  # Only this is used
        Nr   r   F)r   r   
_ast_batchbindr   expr
read_tabler   CopyFromr   r   rT   valuerU   rV   r   rW   r   rX   rY   r   r   tableuid_ast_id)r   r   r   rT   rU   rV   rW   rX   rY   stmtasttime_travel_paramsr   s                r}   r   zDataFrameReader.table
  sL   L .==++002D#DII$8$8$?CJJ		*SXXt,+-=$$*$&/#!#)

 $*3==)D)+.~+>""(!#)

 '$4& &"0 " "C4CTCT!U###DPEP=OP) HHEMr   schemac                     |r6| j                   *t        || j                   j                  j                         || _        | S )a  Define the schema for CSV files that you want to read.

        Args:
            schema: Schema configuration for the CSV file to be read.

        Returns:
            a :class:`DataFrameReader` instance with the specified schema configuration for the data to be read.
        )r   r   r   r   r   )r   r   r   s      r}   r   zDataFrameReader.schemaw  s7     .(1K1K1R1RS"r   r   metadata_colsc                   t        | j                  j                  t              r+| j                  j                  j	                  dt
               |r| j                  yt        | \  }}|| j                  j                  j                  _
        |D ]D  }t        | j                  j                  j                  j                  j                         |       F |D cg c]  }t        |d       c}| _        | S c c}w )a
  Define the metadata columns that need to be selected from stage files.

        Returns:
            a :class:`DataFrameReader` instance with metadata columns to read.

        See Also:
            https://docs.snowflake.com/en/user-guide/querying-metadata
        zDataFrameReader.with_metadata)external_feature_nameraise_error)r   r   _connrJ   log_not_supported_errorNotImplementedErrorr   r9   r   metadata_columnsvariadicr   argsr   rA   r   )r   r   r   	col_namesis_variadicerF   s          r}   with_metadatazDataFrameReader.with_metadata  s     dmm))+?@MM77&E/ 8  .%K&"I{ DODII&&77@ *II..??DDHHJA %
 3 ?@
 	
s   C8c                     | j                   S rx   )r   r   s    r}   _formatzDataFrameReader._format  s    }}r   r   c                     |j                         j                         }g d}|j                  | j                         ||vrt	        d| d| d      || _        y )N)csvjsonavroparquetorcxmlInvalid format 'z'. Supported formats are .)r   r   extendr   r   r   )r   r   canon_formatallowed_formatss       r}   r   zDataFrameReader._format  sf    {{}**,
 	t778."5')B?BSSTU  %r   format)r   r   r   r   r   r   r   r   c                     || _         |r;| j                  /| j                   | j                  j                  j                  _        | S )a  Specify the format of the file(s) to load.

        Args:
            format: The format of the file(s) to load. Supported formats are csv, json, avro, parquet, orc, and xml.
                Snowpark data source type is also supported, currently support dbapi and jdbc.

        Returns:
            a :class:`DataFrameReader` instance that is set up to load data from the specified file format in a Snowflake stage.
        )r   r   r   r   r   )r   r   r   s      r}   r   zDataFrameReader.format  s8    " .6:llDII&&--3r   rt   c           
         | j                   t        d      | j                   j                         }|| j                  v r|t        d| d      || j                  vr|t	        d      |dk(  rL | j
                  di | j                  j                         D ci c]  \  }}|j                         | c}}S |dk(  rL | j                  di | j                  j                         D ci c]  \  }}|j                         | c}}S t        | | j                   d      }| ||d	      }|r| j                  | j                  j                  j                         }t        |j                  j                   |      }	||	_        |	j$                  j'                  | j                         |j(                  |_        |S t        d
| j                    d      c c}}w c c}}w )aZ  Specify the path of the file(s) to load.

        Args:
            path: The stage location of a file, or a stage location that has files.
             This parameter is required for all formats except dbapi.

        Returns:
            a :class:`DataFrame` that is set up to load data from the specified file(s) in a Snowflake stage.
        NzKPlease specify the format of the file(s) to load using the format() method.z.The 'path' parameter is not supported for the z1 format. Please omit this parameter when calling.zEDataFrameReader.load() missing 1 required positional argument: 'path'r   r   Fr   r   z'. )r   r   r   r   	TypeErrorr   r   r   r   getattrr   r   r   r   r   r   	read_loadrt   r   r   r   r   )
r   rt   r   
format_strkvloaderresr   r   s
             r}   loadzDataFrameReader.load  s    <<]  \\'')
111d6F@L}~  T555$,W   4::U$:K:K:Q:Q:S T$!QA TUU499T9J9J9P9P9RSA	1STTt||T2/CTYY2}}//446'		(;(;TB

##DII."hhJ+DLL><==! !USs   G-G!c                    t        |      }|| _        d| _        d\  }}| j                  s| j                  st        j                         t        | j                  j                  t              r1| j                  j                  j                  ddddddt        	       | j                  |d      \  }}}}|pt        |t              r|t        j!                  d| d       t#        dt%               d      g}dg}g }n)d| j&                  d<   | j                  j)                         }| j+                         \  }}d
}	|r|| j,                  p| j                  j.                  j1                         }	t3        |	j4                  j6                  |	      }
||
_        |
j:                  j=                  | j,                         | j                  j>                  rtA        | j                  | j                  jB                  jE                  | j                  jB                  jG                  tI        || j                  | j&                  |||||      | j                  jB                        | j                  jB                        |	|      }n>tA        | j                  tI        || j                  | j&                  |||||      |	|      }| |_%        tM        |d       |S )a$  Specify the path of the CSV file(s) to load.

        Args:
            path: The stage location of a CSV file, or a stage location that has CSV files.

        Returns:
            a :class:`DataFrame` that is set up to load data from the specified CSV file(s) in a Snowflake stage.
        CSV)NNz?Read option 'INFER_SCHEMA of value 'TRUE' for file format 'csv'zDataFrameReader.csvr   rc   TRUE)r   optionoption_valuer   internal_feature_nameparameters_infor   Nz-Could not infer csv schema due to exception: zu. 
Using schema (C1, VariantType()) instead. Please use DataFrameReader.schema() to specify user schema for the file.z"C1"T)z$1C1F)schema_to_casttransformationsr   r   analyzerfrom_r	  )	_ast_stmtr   )'r   r   r   r   r   r$   'DF_MUST_PROVIDE_SCHEMA_FOR_READING_FILEr   r   r   rJ   r   r   _infer_schema_for_file_formatFileNotFoundErrorloggerr=   r   rN   r   _to_attributesr   r   r   r   r   r   read_csvrt   r   r   sql_simplifier_enabledrB   r   create_select_statementcreate_select_snowflake_planr   _readerr%   )r   rt   r   r  r  r   	exceptionr   r   r   r   dfs               r}   r   zDataFrameReader.csv  s    $D)*4'  %%5]]__$----/CD##;;*k*?"'"0(.%
 !4 < 	 224?$i):;#OCI; O; ;
 $FKM4@A"."$05Dn-&&557F,0,Q,Q,S)/ .==++002D#DII$6$6=CCHJJ		*==//''??--11NN$  OO --"+9,;-=,;	 "&!8!8 O  "]]44 @   #'B, OO%%#1$3%5$3	 #B 
B 56	r   c                    d| j                   vrd| j                   d<   | j                  |d      }|r| j                  | j                  j                  j                         }t        |j                  j                  |      }||_	        |j                  j                  | j                         |j                  |_        |S )a(  Specify the path of the JSON file(s) to load.

        Args:
            path: The stage location of a JSON file, or a stage location that has JSON files.

        Returns:
            a :class:`DataFrame` that is set up to load data from the specified JSON file(s) in a Snowflake stage.
        rc   FrS   )r   _read_semi_structured_filer   r   r   r   r   r   	read_jsonrt   r   r   r   r   r   rt   r   r  r   r   s         r}   r   zDataFrameReader.jsono  s     !2!2205Dn-,,T6: .==++002D#DII$7$7>CCHJJ		*BJ	r   c                 H   | j                  |d      }|r| j                  | j                  j                  j	                         }t        |j                  j                  |      }||_        |j                  j                  | j                         |j                  |_        |S )a  Specify the path of the AVRO file(s) to load.

        Args:
            path: The stage location of an AVRO file, or a stage location that has AVRO files.

        Note:
            When using :meth:`DataFrame.select`, quote the column names to select the desired columns.
            This is needed because converting from AVRO to `class`:`DataFrame` does not capitalize the
            column names from the original columns and a :meth:`DataFrame.select` without quote looks for
            capitalized column names.

        Returns:
            a :class:`DataFrame` that is set up to load data from the specified AVRO file(s) in a Snowflake stage.
        AVRO)r  r   r   r   r   r   r   	read_avrort   r   r   r   r   r  s         r}   r   zDataFrameReader.avro  s      ,,T6: .==++002D#DII$7$7>CCHJJ		*BJ	r   c                 H   | j                  |d      }|r| j                  | j                  j                  j	                         }t        |j                  j                  |      }||_        |j                  j                  | j                         |j                  |_        |S )a  Specify the path of the PARQUET file(s) to load.

        Args:
            path: The stage location of a PARQUET file, or a stage location that has PARQUET files.

        Note:
            When using :meth:`DataFrame.select`, quote the column names to select the desired columns.
            This is needed because converting from PARQUET to `class`:`DataFrame` does not capitalize the
            column names from the original columns and a :meth:`DataFrame.select` without quote looks for
            capitalized column names.

        Returns:
            a :class:`DataFrame` that is set up to load data from the specified PARQUET file(s) in a Snowflake stage.
        PARQUET)r  r   r   r   r   r   r   read_parquetrt   r   r   r   r   r  s         r}   r   zDataFrameReader.parquet  s    " ,,T9= .==++002D#DII$:$:DACCHJJ		*BJ	r   c                 H   | j                  |d      }|r| j                  | j                  j                  j	                         }t        |j                  j                  |      }||_        |j                  j                  | j                         |j                  |_        |S )a  Specify the path of the ORC file(s) to load.

        Args:
            path: The stage location of a ORC file, or a stage location that has ORC files.

        Note:
            When using :meth:`DataFrame.select`, quote the column names to select the desired columns.
            This is needed because converting from ORC to `class`:`DataFrame` does not capitalize the
            column names from the original columns and a :meth:`DataFrame.select` without quote looks for
            capitalized column names.

        Returns:
            a :class:`DataFrame` that is set up to load data from the specified ORC file(s) in a Snowflake stage.
        ORC)r  r   r   r   r   r   r   read_orcrt   r   r   r   r   r  s         r}   r   zDataFrameReader.orc  s      ,,T59 .==++002D#DII$6$6=CCHJJ		*BJ	r   c                 H   | j                  |d      }|r| j                  | j                  j                  j	                         }t        |j                  j                  |      }||_        |j                  j                  | j                         |j                  |_        |S )a  Specify the path of the XML file(s) to load.

        Args:
            path: The stage location of an XML file, or a stage location that has XML files.

        Returns:
            a :class:`DataFrame` that is set up to load data from the specified XML file(s) in a Snowflake stage.

        Notes about reading XML files using a row tag:

            - We support reading XML by specifying the element tag that represents a single record using the ``rowTag``
              option. See Example 13 in :class:`DataFrameReader`.

            - Each XML record is flattened into a single row, with each XML element or attribute mapped to a column.
              All columns are represented with the variant type to accommodate heterogeneous or nested data. Therefore,
              every column value has a size limit due to the variant type.

            - The column names are derived from the XML element names. It will always be wrapped by single quotes.

            - To parse the nested XML under a row tag, you can use dot notation ``.`` to query the nested fields in
              a DataFrame. See Example 13 in :class:`DataFrameReader`.

            - ``compression`` is not supported for XML files when ``rowTag`` is specified.

            - When ``rowTag`` is specified, the following options are supported for reading XML files
              via :meth:`option()` or :meth:`options()`:

              + ``mode``: Specifies the mode for dealing with corrupt XML records. The default value is ``PERMISSIVE``. The supported values are:

                  - ``PERMISSIVE``: When it encounters a corrupt record, it sets all fields to null and includes a `columnNameOfCorruptRecord` column.

                  - ``DROPMALFORMED``: Ignores the whole record that cannot be parsed correctly.

                  - ``FAILFAST``: When it encounters a corrupt record, it raises an exception immediately.

              + ``columnNameOfCorruptRecord``: Specifies the name of the column that contains the corrupt record.
                The default value is '_corrupt_record'.

              + ``ignoreNamespace``: remove namespace prefixes from XML element names when constructing result column names.
                The default value is ``True``. Parsing uses recovery mode to tolerate malformed records (e.g., undefined
                namespace prefixes in attributes such as ``diffgr:id`` or ``msdata:rowOrder``). When this option is enabled,
                element name prefixes are stripped where resolvable; if a prefix isn't declared on the row tag element,
                it cannot be resolved and will be left intact (i.e. this setting is ignored for that element).
                For example, for the following XML data with a row tag ``abc:def``:
                ```
                <abc:def><abc:xyz>0</abc:xyz></abc:def>
                ```
                the result column name is ``abc:xyz`` where ``abc`` is not stripped.

              + ``attributePrefix``: The prefix to add to the attribute names. The default value is ``_``.

              + ``excludeAttributes``: Whether to exclude attributes from the XML element. The default value is ``False``.

              + ``valueTag``: The column name used for the value when there are attributes in an element that has no child elements.
                The default value is ``_VALUE``.

              + ``nullValue``: The value to treat as a null value. The default value is ``""``.

              + ``charset``: The character encoding of the XML file. The default value is ``utf-8``.

              + ``ignoreSurroundingWhitespace``: Whether or not whitespaces surrounding values should be skipped.
                The default value is ``False``.

              + ``rowValidationXSDPath``: The Snowflake stage path to the XSD file used for row validation.
                Rows that do not match the XSD schema will be considered corrupt records and handled according to
                the specified ``mode`` option.

              + ``cacheResult``: Whether to cache the result DataFrame of the XML reader to a temporary table after calling :meth:`xml`.
                When set to ``True`` (default), the result is cached and all subsequent operations on the DataFrame are performed on the cached data.
                This means the actual computation occurs before :meth:`DataFrame.collect` is called.
                When set to ``False``, the DataFrame is computed lazily and the actual computation occurs when :meth:`DataFrame.collect` is called.
        XML)r  r   r   r   r   r   r   read_xmlrt   r   r   r   r   r  s         r}   r   zDataFrameReader.xml  s~    T ,,T59.==++002D#DII$6$6=CCHJJ		*BJ	r   keyc                 ,   |rr| j                   f| j                   j                  j                  j                         }||_        t        |j                  t        |t              rt        |      n|       t        |t              }|| j                  |<   | S )a  Sets the specified option in the DataFrameReader.

        Use this method to configure any
        `format-specific options <https://docs.snowflake.com/en/sql-reference/sql/create-file-format.html#format-type-options-formattypeoptions>`_,
        `copy options <https://docs.snowflake.com/en/sql-reference/sql/copy-into-table.html#copy-options-copyoptions>`_,
        and `time travel options <https://docs.snowflake.com/en/sql-reference/constructs/at-before>`_.
        (Note that although specifying copy options can make error handling more robust during the
        reading process, it may have an effect on performance.)

        Time travel options can be used with ``table()`` method:
            - ``time_travel_mode``: Either "at" or "before"
            - ``statement``: Query ID for statement-based time travel
            - ``offset``: Seconds to go back in time (negative integer)
            - ``timestamp``: Specific timestamp for time travel
            - ``timestamp_type``: Type of timestamp interpretation ('NTZ', 'LTZ', or 'TZ').
            - ``stream``: Stream name for time travel.

        Special PySpark compatibility option:
            - ``as-of-timestamp``: Automatically sets ``time_travel_mode`` to "at" and uses the
              provided timestamp. Cannot be used with ``time_travel_mode="before"``.

        Args:
            key: Name of the option (e.g. ``compression``, ``skip_header``, ``time_travel_mode``, etc.).
            value: Value of the option.
        )r   r   r   r   _1r   _2r   rM   r   r5   READER_OPTIONS_ALIAS_MAPr   )r   r)  r   r   taliased_keys         r}   r   zDataFrameReader.option2  sz    : .		**22668AAD&Ju6G$Hc%je .c3KL).+&r   configsc                     |r|rt        d      ||st        d      |}|j                         D ]  \  }}| j                  |||        | S )aR  Sets multiple specified options in the DataFrameReader.

        This method is the same as the :meth:`option` except that you can set multiple options in one call.

        Args:
            configs: Dictionary of the names of options (e.g. ``compression``,
                ``skip_header``, etc.) and their corresponding values.
        z]Cannot set options with both a dictionary and keyword arguments. Please use one or the other.zNo options were providedr   )r   r   r   )r   r0  r   kwargsr   r   s         r}   r   zDataFrameReader.optionsZ  sd     vo  ? !;<<GMMO 	3DAqKK1	K2	3r   c                 V   t        | j                        \  }}| j                  j                  t	        t
        j                              }d }d| j                  v}| j                  j                  d|      }| j                  j                  di       }	|	j                  dd      }
| j                  j                  dd      }|}|}d}| j                  j                  dd       x}rd|	vr{|j                  t              set        |      }| j                  j                  j                  d| d	|       d
   }t        |      r 	 t        |      \  }}t        |d      \  }}| j                  j                  j                  d|       d
   }|D cg c]  }|d   dk(  s| c}d   d   }|rt!        j"                  |      n|g}|D cg c]<  }t%        j&                  dt%        j(                  |       t$        j*                        > }}g }|D ]1  }|d   }|D ]  }|j-                  d|      } |j/                  |       3 ||	d<   |j1                  |      d   |z   }d}t7        |||	xs d       }	 |rV| j                  j                  j                  t9        |||dd| j                  j:                  d      d       t=        |      }	 | j                  j                  j                  |      d
   } t        |       dk(  rt?        d| d      g }!g }"g }#d }$| D ]y  }%|%d   |%d   |%d   |%d   f\  }&}'}(})tA        |&      }*|'jC                  d      }+t        |+      },|,dk(  r|'}-d}.d}/nH|+d   }-tE        |+d   jC                  d      d         }.tE        |+d   jC                  d      d   d d       }/tG        |-|.|/d| j                  j                  jH                        }0|
rtK        |0      }0|!j/                  tM        |*|0|(             |r'|)jC                  d       d   }1d!|1 d"tO        |0       d#}2n7|d$k(  r|)}2n/|d%k(  r"|)jQ                         j                  d&      r|)}2nd'|* d(|' }2|"j/                  |2|&f       |#j/                  tS        |2             | tU        jV                  |!      | _,        |#| _-        | jX                  j\                  | _/        |#D 3cg c]  }3|3j`                  jb                   }$}3	 |(| j                  j                  j                  |d       	 |!|"|$d fS c c}w c c}w # t2        $ r}t5        dd| d|        Y d }~d }~ww xY w# t2        $ rE}|r6t7        ||d       }| j                  j                  j                  |      d
   } n|Y d }~d }~ww xY wc c}3w # t2        $ r:}d d d |fcY d }~|(| j                  j                  j                  |d       S S d }~ww xY w# |(| j                  j                  j                  |d       w w xY w))NFORMAT_NAMEINFER_SCHEMA_OPTIONSUSE_RELAXED_TYPESFTRY_CASTrb   FILESzlist z pattern = dataT)return_full_stage_namezdescribe stage r   STAGE_LOCATIONrP   ^ infer_schema_pattern_matchingz,Failed to infer schema for provided pattern z with error:
)tempif_not_existuse_scoped_temp_objectsis_generated)is_ddl_on_temp_objectzGiven path: 'z!' could not be found or is empty.      (,)nullable:z	TRY_CAST(z AS )r   r!  GET_IGNORE_CASE$1:::)2r6   r   r   $get_fully_qualified_name_if_possibler<   r4   FILE_FORMATr   popry   r+   r   r   	run_querylenr7   r   loadsrecompileescape
IGNORECASEsubappend	partition	Exceptionr=   r   r   _use_scoped_temp_objectsr   r  r   splitintr'   max_string_sizer)   r   r(   r   rE   rL   _from_attributesr   r   namesr   r   r   )4r   rt   r   format_type_options_temp_file_format_name$drop_tmp_file_format_if_exists_queryuse_temp_file_formatfile_format_nameinfer_schema_optionsuse_relaxed_typestry_cast
infer_pathfallback_pathshould_fallbackpatternescaped_patternmatchesstagefully_qualified_stagestage_descriptionxstage_locations_jsonstage_locationslocationregexesfilesmatchr{   regexr   infer_schema_queryresults
new_schemar  r  read_file_transformationsrcolumn_nametyperI  
expressionr   data_type_partsparts_length	data_type	precisionscaledatatypeid
identifierr.  s4                                                       r}   r  z-DataFrameReader._infer_schema_for_file_formats  s   
 "=T=N=N!OQ $ R R'(B(BC!
 ?C,,D4E4EE,,00@UV#00445KRP 1445H%P $$((U;
 
"))--i>>W>33OON3
 :'BOmm))33v[(9:G 7|0.t4HE1/>T0,)1 )-(;(;(E(E)*?)@A))%
 $5,!@P8P,,,( 0 

#78#W $ )8$ 

Qryy':&;#<bmmLG 
 E!( -!&q%, ;E%*YYr6%:F;V,	-
 5:(1 '<=a@CXX  '+O 4(*>*F$
]	###--0(+!%)040V0V%) +/ .  99IJ 5
----778JKFS 7|q '#D6)JK  JNHJO(,% *=:;A$!adAaD:P7T8Z6{C #'**S/"?31$ $I !IE / 2I #OA$6$<$<S$A!$D EI 2 8 8 =a @" EFE0y%DMM4G4G4W4W %3H=H!! !) #))#.q1B#,RD5J85T4UUV!WJu_!+Jy(Z-=-=-?-J-J%. ",J#&tfBtf!5J%%z;&?@&&x
';<U*=V !+ ; ;J GD1@D.040A0A0G0GD-DS(Tq):):(T%(T
 4?##--8PT .  >+DdJJU,& ! 7Fwi~^_]`a >  ")?%'7*& #mm11;;<NOPVWGG @ )U 	'tQ&& 4?##--8PT .  @		' 4?##--8PT .  @s   AT7 T-"T-&'T7 AT2AT7 8AV6 (U  9G$V6 V1:V6 -
T7 7	U UU 	V.):V)#V6 )V..V6 6	W9?W4W9W< 4W99W< <,X(user_schemac                    g }g }g }|j                   D ]  }t        |j                        }|j                  t	        ||j
                  |j                               d| dt        |j
                         }|j                  ||j                  f       |j                  t        |              || _	        t        j                  |      j                  | _        |D cg c]  }|j                  j                   }	}|||	fS c c}w )zgThis function accept a user input structtype and return schemas needed for reading semi-structured filerM  rN  )fieldsr   _namerZ  r   r  rI  r(   rE   r   rL   ra  rb  r   r   r   )
r   r  r  r  r  fieldr   r  r.  r  s
             r}   _get_schema_from_user_inputz+DataFrameReader._get_schema_from_user_input5  s    
 '' 	9E25;;?DNNNN tfB'<U^^'L&MNJ!!:u{{";<""8J#78	9 .=*,6,G,G-

% 	) AP$P1Q]]%6%6$P!$P>+DDD %Qs   Dc                 L   t        | j                  j                  t              ru| j                  j                  j	                         rt        dd      |t        vr<| j                  j                  j                  d| dddt        |      it               | j                  r"|j                         d	k7  rt        d
| d      t        |      }|| _        || _        t!        dt#                     g}d }d }d}| j                  r3| j%                  | j                        \  }}}|}d| j&                  d<   d}n'| j(                  r| j+                  ||      \  }}}}|r|}| j-                         \  }	}
|dk(  rIt.        | j&                  v r6t1               rt3        t4        j6                        }d| dt8         }| j                  j;                  |d      j=                  d       | j                  j                  j?                  t@        |ddd       tB         | dtD        jF                  jI                  t@               }nt@        }d}tK        t@        |ft4        jL                        \  }}tO        tQ        tR        t#               d      g      }| j                  jT                  jW                  ||||ddgdd      }nd }| j                  jX                  rt[        | j                  | j                  j\                  j_                  | j                  j\                  ja                  tc        ||| j&                  ||||	|
||
      | j                  j\                        | j                  j\                        d      }n5t[        | j                  tc        ||| j&                  ||||	|
||
      d      }| |_2        |rEtg        |th               | j&                  jk                  dd      r|jm                         }d|_7        |S tg        |d|j                                 |S )NzBCannot perform this operation because the session has been closed.1404)
error_codezRead semi structured z filez*DataFrameReader._read_semi_structured_filer   r  r   zRead z does not support user schemaz"$1"Frc   Tr'  z create temp stage if not exists  r   )compress_data	overwriteskip_upload_on_content_match/	XMLReaderzsnowflake-snowpark-pythonzlxml<6)output_schemainput_typespackagesreplace _suppress_local_package_warnings)r  r  r   r   use_user_schemaxml_reader_udtfr  r
  CACHERESULTzDataFrameReader.)8r   r   r   rJ   	is_closedrC   #LOCAL_TESTING_SUPPORTED_FILE_FORMATr   r   r   r   r   r   r   r   r   r   rN   r  r   r   r  r   r-   r8   r<   r4   STAGEr1   r   collectupload_filer/   r,   osrt   basenamer*   TABLE_FUNCTIONrL   rO   r.   udtfregister_from_filer  rB   r   r  r  r   r  r%   r0   r   cache_result_all_variant_cols)r   rt   r   r   r  r  r  r  rd  r   r   
temp_stagesql_create_temp_stagepython_file_pathhandler_namer  r  r  r  s                      r}   r  z*DataFrameReader._read_semi_structured_fileO  s!   dmm))+?@}}"",,..X%  @@##;;,A&*O*V%-s6{$; 3	 <  6!9uVH,IJKK#D) FKM23$(!
 001B1BC	)F05Dn-"O 224@)#,0,Q,Q,S)/U?1T5F5FF%' 99M9MN
*J:,VWXnWo(p%!!"75!IQQ# R  ##//("'"15 0  '3^J<qAQAQRfAg@h#i #7  'L6%|4n6S6SNA{ '5{}dKLM #mm00CC +'5x@15 D O #O==//''??--11NN$ " --"+9,E-=,;,;,; "&!8!8 O  "]]44! @ $  )B. %%#1$=%5$3$3$3  B  
$<=  $$]D9__&'+$ 	  &6v||~6F$GH	r   z1.38.0)versionr   )
propertiesr   querycolumnlower_boundupper_boundnum_partitionsquery_timeout
fetch_sizecustom_schema
predicatessession_init_statementr   urludtf_configsr  r   r  r  r  r  r  r  r  r  r  r  c                   |s|r|r|rt        d      |j                  dd      }|j                  dd      }|j                  ddg      }|j                  dd      }|j                  d	d      }t               }t        |d
<   d|d<   t	        |      |d<   |d   |d<   t
        di}|||t        d      t        j                         }t        j                  d|        |rt        |t              r|g}t        d)i d| j                  d|d|d|d|d|d|d|xs |d|dndd	|d|d|d|d|	d|
d|d|d|d |d!|}|j                  }t!        t"        j$                        }| j                  j'                  |D cg c]  }|g c}d"g#      j(                  j+                  |d$|%       |j-                  |      }|j/                  ||j0                  |&      }t        j                         }||z
  |d'<   |j0                  j3                         |d(<   | j                  j4                  j6                  j9                  |       t;        |t               |S c c}w )*a  
        Reads data from a database table or query into a DataFrame using a JDBC connection string,
        with support for optional partitioning, parallel processing, and query customization.

        There are multiple methods to partition data and accelerate ingestion.
        These methods can be combined to achieve optimal performance:

        1.Use column, lower_bound, upper_bound and num_partitions at the same time when you need to split large tables into smaller partitions for parallel processing.
        These must all be specified together, otherwise error will be raised.
        2.Set max_workers to a proper positive integer.
        This defines the maximum number of processes and threads used for parallel execution.
        3.Adjusting fetch_size can optimize performance by reducing the number of round trips to the database.
        4.Use predicates to defining WHERE conditions for partitions,
        predicates will be ignored if column is specified to generate partition.
        5.Set custom_schema to avoid snowpark infer schema, custom_schema must have a matched
        column name with table in external data source.

        Args:
            url: A connection string used to establish connections to external data source with JDBC driver.
                Please do not include any secrets in this parameter. Secret in connection string will be removed and ignored.
            udtf_configs: A dictionary containing configuration parameters for ingesting external data using a Snowflake UDTF.
                This parameter is required for jdbc.

                The dictionary may include the following keys:

                - external_access_integration (str, required): The name of the external access integration,
                    which allows the UDTF to access external endpoints.

                - secret (str, required): The name of the snowflake secret that contain username and password of
                    external data source.

                - imports (List[str], required): A list of stage file names to import into the UDTF.
                    Please include Jar file of jdbc driver to establish connection to external data source.

                - java_version (int, optional): A integer that indicate the java runtime version of udtf.
                    By default, we use java 17.

            properties: A dictionary containing key-value pair that is needed during establishing connection with external data source.
                Please do not include any secrets in this parameter.

            table: The name of the table in the external data source.
                This parameter cannot be used together with the `query` parameter.
            query: A valid SQL query to be used as the data source in the FROM clause.
                This parameter cannot be used together with the `table` parameter.
            column: The column name used for partitioning the table. Partitions will be retrieved in parallel.
                The column must be of a numeric type (e.g., int or float) or a date type.
                When specifying `column`, `lower_bound`, `upper_bound`, and `num_partitions` must also be provided.
            lower_bound: lower bound of partition, decide the stride of partition along with `upper_bound`.
                This parameter does not filter out data. It must be provided when `column` is specified.
            upper_bound: upper bound of partition, decide the stride of partition along with `lower_bound`.
                This parameter does not filter out data. It must be provided when `column` is specified.
            num_partitions: number of partitions to create when reading in parallel from multiple processes and threads.
                It must be provided when `column` is specified.
            query_timeout: The timeout (in seconds) for each query execution. A default value of `0` means
                the query will never time out. The timeout behavior can also be configured within
                the `create_connection` method when establishing the database connection, depending on the capabilities
                of the DBMS and its driver.
            fetch_size: The number of rows to fetch per batch from the external data source.
                This determines how many rows are retrieved in each round trip,
                which can improve performance for drivers with a low default fetch size.
            custom_schema: a custom snowflake table schema to read data from external data source,
                the column names should be identical to corresponded column names external data source.
                This can be a schema string, for example: "id INTEGER, int_col INTEGER, text_col STRING",
                or StructType, for example: StructType([StructField("ID", IntegerType(), False), StructField("INT_COL", IntegerType(), False), StructField("TEXT_COL", StringType(), False)])
            predicates: A list of expressions suitable for inclusion in WHERE clauses, where each expression defines a partition.
                Partitions will be retrieved in parallel.
                If both `column` and `predicates` are specified, `column` takes precedence.
            session_init_statement: One or more SQL statements executed before fetching data from
                the external data source.
                This can be used for session initialization tasks such as setting configurations.
                For example, `"SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED"` can be used in SQL Server
                to avoid row locks and improve read performance.
                The `session_init_statement` is executed only once at the beginning of each partition read.

        Example::
            .. code-block:: python

                udtf_configs={
                        "external_access_integration": ...,
                        "secret": ...,
                        "imports": [...],
                    }
                df = session.read.jdbc(
                    url=...,
                    udtf_configs=udtf_configs,
                    query=...,
                )

        Example::
            .. code-block:: python

                udtf_configs={
                    "external_access_integration": ...,
                    "secret": ...,
                    "imports": [...],
                }
                df = (
                    session.read.format("jdbc")
                    .option("url", ...)
                    .option("udtf_configs", udtf_configs)
                    .option("query", ...)
                    .load()
                )
        9Either 'table' or 'query' must be provided, but not both.external_access_integrationNimportsr  zcom.snowflake:snowpark:latestjava_version   secretfunction_nameudtf_ingestioningestion_mode	dbms_type1zQexternal_access_integration, secret and imports must be specified in udtf configsingestion start at: r   r  r  table_or_queryis_queryTFr  r  r  r  r  r  r  r  r  r   r[  r   r?  
table_typestatement_paramsr   end_to_end_durationr   r   )rD   r   r   r"   r#   r!   r   timeperf_counterr  debugr   r   r   r   
partitionsr<   r4   TABLEcreate_dataframewritesave_as_tablereadto_result_snowpark_dfr   simple_stringr   _telemetry_clientsend_data_source_perf_telemetryr%   )r   r  r  r  r   r  r  r  r  r  r  r  r  r  r  r   r  r  r  r  r  telemetry_json_stringstatements_params_for_telemetry
start_timejdbc_clientr  partitions_tabler  res_dfend_times                                 r}   r   zDataFrameReader.jdbc  s   z e52K  '3&6&6)4'
# ""9d3##J1P0QR#'';!!(D1 +1Ko.2B./-:3-?k*+7	+Bi(+Lc*R'&.'/V^c  &&(
+J<89!j1G&M&<%=" 
MM

 )D
 "	

 
 
 &
 !>E
 #.TE
 
 
 $
 $
 *
 (
  "!
" (#
$ "%
& $:'
(  )
. !++
6~7K7KL&&",-eW-{m 	' 	

%<  
 ./22""i 3 
 $$&7?*7L34*0--*E*E*Gh'--MM!	
 	F$>?% .s   
I%z1.29.0i rD  F)r   r  r  r  r  r  max_workersr  r  r  r  r  r  fetch_merge_countfetch_with_processconnection_parametersr   create_connection).r   r  r  r  r  c                   |s|r|r|rt        d      t               }t        |d<   |dnd|d<   |xs |}|dnd}t        d	i}t	        j
                         }t        j                  d
|        |rt        |t              r|g}t        ||||||||	|
|||||      }|j                  }|j                  }|j                  j                  |d<   |j                  j                  |d<   |5d|vrt!        d      t#        t$        j&                        }| j(                  j+                  |D cg c]  }|g c}dg      j,                  j/                  |d|       |j1                  | j(                  |||d   |
|j3                  dd      |j3                  dd      ||	|d      }t	        j
                         }||z
  |d<   t        j                  d| d||z
          | j(                  j4                  j6                  j9                  |       t;        |t               |S t#        t$        j&                        }t#        t$        j<                        }t?        | j(                  ||||       tA        | j(                  |||||||||
       t	        j
                         }||z
  |d<   |jB                  jE                  | |||      } | j                  jG                         |d<   | j(                  j4                  j6                  j9                  |       t        j                  d| d||z
          t        j                  dtI        jJ                  |              t;        | t               | S c c}w )a-2  
        Reads data from a database table or query into a DataFrame using a DBAPI connection,
        with support for optional partitioning, parallel processing, and query customization.

        Usage Notes:
            - Ingestion performance tuning:
                - **Partitioning**: Use ``column``, ``lower_bound``, ``upper_bound``, and ``num_partitions``
                  together to split large tables into smaller partitions for parallel processing.
                  All four parameters must be specified together, otherwise an error will be raised.
                - **Parallel execution**: Set ``max_workers`` to control the maximum number of processes
                  and threads used for parallel execution.
                - **Fetch optimization**: Adjust ``fetch_size`` to optimize performance by reducing
                  the number of round trips to the database.
                - **Partition filtering**: Use ``predicates`` to define WHERE conditions for partitions.
                  Note that ``predicates`` will be ignored if ``column`` is specified for partitioning.
                - **Schema specification**: Set ``custom_schema`` to skip schema inference. The custom schema
                  must have matching column names with the table in the external data source.
            - Execution timing and error handling:
                - **UDTF Ingestion**: Uses lazy evaluation. Errors are reported as ``SnowparkSQLException``
                  during DataFrame actions (e.g., ``DataFrame.collect()``).
                - **Local Ingestion**: Uses eager execution. Errors are reported immediately as
                  ``SnowparkDataFrameReaderException`` when this method is called.

        Args:
            create_connection: A callable that returns a DB-API compatible database connection.
                The callable can optionally accept keyword arguments via `**kwargs`.
                If connection_parameters is provided, those will be passed as keyword arguments to this callable.
                The callable must be picklable, as it will be passed to and executed in child processes.
            table: The name of the table in the external data source.
                This parameter cannot be used together with the `query` parameter.
            query: A valid SQL query to be used as the data source in the FROM clause.
                This parameter cannot be used together with the `table` parameter.
            column: The column name used for partitioning the table. Partitions will be retrieved in parallel.
                The column must be of a numeric type (e.g., int or float) or a date type.
                When specifying `column`, `lower_bound`, `upper_bound`, and `num_partitions` must also be provided.
            lower_bound: lower bound of partition, decide the stride of partition along with `upper_bound`.
                This parameter does not filter out data. It must be provided when `column` is specified.
            upper_bound: upper bound of partition, decide the stride of partition along with `lower_bound`.
                This parameter does not filter out data. It must be provided when `column` is specified.
            num_partitions: number of partitions to create when reading in parallel from multiple processes and threads.
                It must be provided when `column` is specified.
            max_workers: number of processes and threads used for parallelism.
            query_timeout: The timeout (in seconds) for each query execution. A default value of `0` means
                the query will never time out. The timeout behavior can also be configured within
                the `create_connection` method when establishing the database connection, depending on the capabilities
                of the DBMS and its driver.
            fetch_size: The number of rows to fetch per batch from the external data source.
                This determines how many rows are retrieved in each round trip,
                which can improve performance for drivers with a low default fetch size.
            custom_schema: a custom snowflake table schema to read data from external data source,
                the column names should be identical to corresponded column names external data source.
                This can be a schema string, for example: "id INTEGER, int_col INTEGER, text_col STRING",
                or StructType, for example: StructType([StructField("ID", IntegerType(), False), StructField("INT_COL", IntegerType(), False), StructField("TEXT_COL", StringType(), False)])
            predicates: A list of expressions suitable for inclusion in WHERE clauses, where each expression defines a partition.
                Partitions will be retrieved in parallel.
                If both `column` and `predicates` are specified, `column` takes precedence.
            session_init_statement: One or more SQL statements executed before fetching data from
                the external data source.
                This can be used for session initialization tasks such as setting configurations.
                For example, `"SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED"` can be used in SQL Server
                to avoid row locks and improve read performance.
                The `session_init_statement` is executed only once at the beginning of each partition read.
            udtf_configs: A dictionary containing configuration parameters for ingesting external data using a Snowflake UDTF.
                If this parameter is provided, the workload will be executed within a Snowflake UDTF context.

                The dictionary may include the following keys:

                - external_access_integration (str, required): The name of the external access integration,
                    which allows the UDTF to access external endpoints.

                - imports (List[str], optional): A list of stage file names to import into the UDTF.
                    Use this to include any private packages required by your `create_connection()` function.

                - packages (List[str], optional): A list of package names (with optional version numbers)
                    required as dependencies for your `create_connection()` function.
            fetch_merge_count: The number of fetched batches to merge into a single Parquet file
                before uploading it. This improves performance by reducing the number of
                small Parquet files. Defaults to 1, meaning each `fetch_size` batch is written to its own
                Parquet file and uploaded separately.
            fetch_with_process: Whether to use multiprocessing for data fetching and Parquet file generation in local ingestion.
                Default to `False`, which means multithreading is used to fetch data in parallel.
                Setting this to `True` enables multiprocessing, which may improve performance for CPU-bound tasks
                like Parquet file generation. When using multiprocessing, guard your script with
                `if __name__ == "__main__":` and call `multiprocessing.freeze_support()` on Windows if needed.
                This parameter has no effect in UDFT ingestion.
            connection_parameters: Optional dictionary of parameters to pass to the create_connection callable.
                If provided, these parameters will be unpacked and passed as keyword arguments
                to create_connection(`**connection_parameters`).
                This allows for flexible connection configuration without hardcoding values in the callable.
                Example: {"timeout": 30, "isolation_level": "READ_UNCOMMITTED"}

        Example::
            .. code-block:: python

                import oracledb
                def create_oracledb_connection():
                    connection = oracledb.connect(...)
                    return connection

                df = session.read.dbapi(create_oracledb_connection, table=...)

        Example::
            .. code-block:: python

                import oracledb
                def create_oracledb_connection():
                    connection = oracledb.connect(...)
                    return connection

                df = session.read.dbapi(create_oracledb_connection, table=..., fetch_with_process=True)

        Example::
            .. code-block:: python

                import sqlite3
                def create_sqlite_connection(timeout=5.0, isolation_level=None, **kwargs):
                    connection = sqlite3.connect(
                        database=":memory:",
                        timeout=timeout,
                        isolation_level=isolation_level
                    )
                    return connection

                connection_params = {"timeout": 30.0, "isolation_level": "DEFERRED"}
                df = session.read.dbapi(
                    create_sqlite_connection,
                    table=...,
                    connection_parameters=connection_params
                )

        Example::
            .. code-block:: python

                import oracledb
                def create_oracledb_connection():
                    connection = oracledb.connect(...)
                    return connection

                # pull data from target table with parallelism using partition column
                df_local_par_column = session.read.dbapi(
                    create_oracledb_connection,
                    table="target_table",
                    fetch_size=100000,
                    num_partitions=4,
                    column="ID",  # swap with the column you want your partition based on
                    upper_bound=10000,
                    lower_bound=0
                )

        Example::
            .. code-block:: python

                import oracledb
                def create_oracledb_connection():
                    connection = oracledb.connect(...)
                    return connection

                # pull data from target table with parallelism using predicates
                df_local_predicates = session.read.dbapi(
                    create_oracledb_connection,
                    table="target_table",
                    fetch_size=100000,
                    predicates=[
                        "ID < 3",
                        "ID >= 3"
                    ]
                )

        Example::
            .. code-block:: python

                import oracledb
                def create_oracledb_connection():
                    connection = oracledb.connect(...)
                    return connection
                udtf_configs = {
                    "external_access_integration": "<your external access integration>"
                }

                # pull data from target table with udtf ingestion

                df_udtf_basic = session.read.dbapi(
                    create_oracledb_connection,
                    table="target_table",
                    udtf_configs=udtf_configs
                )

        Example::
            .. code-block:: python

                import oracledb
                def create_oracledb_connection():
                    connection = oracledb.connect(...)
                    return connection
                udtf_configs = {
                    "external_access_integration": "<your external access integration>"
                }

                # pull data from target table with udtf ingestion with parallelism using partition column

                df_udtf_par_column = session.read.dbapi(
                    create_oracledb_connection,
                    table="target_table",
                    udtf_configs=udtf_configs,
                    fetch_size=100000,
                    num_partitions=4,
                    column="ID",  # swap with the column you want your partition based on
                    upper_bound=10000,
                    lower_bound=0
                )

        Example::
            .. code-block:: python

                import oracledb
                def create_oracledb_connection():
                    connection = oracledb.connect(...)
                    return connection
                udtf_configs = {
                    "external_access_integration": "<your external access integration>"
                }

                # pull data from target table with udtf ingestion with parallelism using partition column

                df_udtf_predicates = session.read.dbapi(
                    create_oracledb_connection,
                    table="target_table",
                    udtf_configs=udtf_configs,
                    fetch_size=100000,
                    predicates=[
                        "ID < 3",
                        "ID >= 3"
                    ]
                )

        r  r  Nr  r    r  TFr  r  r  driver_typer  zexternal_access_integration cannot be None when udtf ingestion is used. Please refer to https://docs.snowflake.com/en/sql-reference/sql/create-external-access-integration to create external access integrationr[  r  r?  r  r  r  )r  r  r  r  r  r  r   r  zingestion end at: z, total time: )r   r   snowflake_table_namesnowflake_stage_namer  )
r   partitionerpartitioned_queriesr  r  r  r  r  r  r   r   r   zrecorded telemetry: )&rD   r   r   r   r  r  r  r  r   r   r   r   r  r  r   r  r   r<   r4   r  r   r  r  r  _udtf_ingestionr   r   r  r  r%   r  r   r    driverr  r  r   dumps)!r   r  r   r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r   r  r  r  r  r  r  struct_schemar  r  r  r  r  r  r  s!                                    r}   r   zDataFrameReader.dbapi  s   H e52K  !,1Lo. , 8>O 	./ % =4e+G*M'&&(
+J<89!j1G&M&<%="+"!
  $**)44-8-B-B-H-Hk*/:/F/F/L/Lm, #,L@  g   ;>;O;OPMM**&9:U%:K= + eMM !!@ " 
 ,, :;%$((D9%))*d;'=+!@ - B ((*H;Cj;P!"78LL$XJnX
=R<ST MM11QQ%  $?@I  ;>;O;OP:>;O;OP*MM !5!5,K	
 	MM# 3#1!5!5,K"7	
 $$&7?*7L34 ##99& : 
 +1--*E*E*Gh'--MM!	
 	 
.J9N8OP	
 	+DJJ7L,M+NOPF$?@Y ;s   +
M,z1.37.0c           
      ^   t        |      }d| }d| j                  v r"| j                  d   }t        |      }|d| z  }| j                  j	                  ||      j                  t        t        t        d      t        d                  j                  d            }t        |d       |S )	a  
        Returns a DataFrame with a single column ``FILE`` containing a list of files
        in the specified Snowflake stage location (either internal or external).

        Args:
            path: The stage location to list files from (e.g., "@mystage", "@mystage/path/").

        Example::

            >>> # Create a temp stage and upload some test files
            >>> _ = session.sql("CREATE OR REPLACE TEMP STAGE mystage").collect()
            >>> _ = session.file.put("tests/resources/testCSV.csv", "@mystage", auto_compress=False)
            >>> _ = session.file.put("tests/resources/testCSVheader.csv", "@mystage", auto_compress=False)
            >>> _ = session.file.put("tests/resources/testJson.json", "@mystage", auto_compress=False)

            >>> # List all files in the stage
            >>> df = session.read.file("@mystage")
            >>> df.count()
            3

            >>> # List files matching a pattern (only CSV files)
            >>> df = session.read.option("pattern", ".*\.csv").file("@mystage")
            >>> df.count()
            2

            >>> # List files with a more specific pattern
            >>> df = session.read.option("pattern", ".*header.*").file("@mystage")
            >>> df.count()
            1
        zLIST rb   z PATTERN = r   @z"name"filezDataFrameReader.file)r   r   r   r   r   selectrI   rG   rH   rF   aliasr%   )r   rt   r   
list_queryro  rp  r  s          r}   r  zDataFrameReader.file%  s    B $D) TF^
 )))''	2G9'BOK'899J
 ]]zY?FFF3s8S]34::6B
 	B 67	r   
stage_namec                 j   d}|r|| j                   p| j                  j                  j                         }t	        |j
                  j                  |      }|j                  j                  | j                          ||_	        | j                  j                  |d      }|r||j                  |_        |S )ai  
        Returns a DataFrame representing the results of a directory table query on the specified stage.

        This method is an alias of :meth:`~snowflake.snowpark.session.Session.directory`.

        Args:
            stage_name: The name of the stage to query. The stage name should not include the '@' prefix
                as it will be added automatically.

        Returns:
            A DataFrame containing metadata about files in the stage with the following columns:

            - ``RELATIVE_PATH``: Path to the files to access using the file URL
            - ``SIZE``: Size of the file in bytes
            - ``LAST_MODIFIED``: Timestamp when the file was last updated in the stage
            - ``MD5``: MD5 checksum for the file
            - ``ETAG``: ETag header for the file
            - ``FILE_URL``: Snowflake file URL to access the file

        NFr   )r   r   r   r   r   r   read_directoryr   r   r  	directoryr   r   )r   r  r   r   r   	dataframes         r}   r  zDataFrameReader.directory\  s    , .==++002D#DII$<$<dCCJJ		*'CNMM++J%+H	) $Ir   )T)NT)6__name__
__module____qualname____doc__r;   boolr   propertyr   r
   r   r   r   r   r   rR   r	   r   r_  r   rM   rK   r   rL   r   r&   r   r   setterr   rB   r   r   r   r   r   r   r   r   r   r   r   r\  r  r  r  r:   dictr   r   r   r>   r  r  r   r   r}   r   r      sv   Wr OS;HL	 .  1%S	4	?8R2S 1B  j
 ?C#' $48BF $jC#&'j j
 #7>#:;j C=j j E#x-01j !s,='=!>?j j 
j jX Z D DU  " HL &|4 AE 	   D #   ^^%S %T % %"  K

  
 , )># )>$ )>) )> )>V g g g	 g gR     0     6 C D I  8   	  6 R R R	 R Rh %# %c %d %FW % %N @D~9=	 0@K@K @K 
tT4*	+	@KDE%E	tT4	 E4Is IC II IV X& &*## $1515(,'($%:>*.BF#FF F
 TNF }F }F F eCHo.F eCHo.F !F  }F SMF  c:o 67F T#Y'F  !)sDI~)> ?!F" #F$ 
%F  'FP X&
  $# $1515(,%)'($*:>*.BF'+!"#(04)}#$56} }	}
 }} } eCHo.} eCHo.} !} c]}  }} SM}  c:o 67} T#Y'} !)sDI~)> ?}  tn!}" #}$ !%}&  (~'}( )}* 
+}  '}~ (#3 3 3 3 $ 3j"C "D "I "r   r   )r   r  rU  sysr  collectionsr   loggingr   typingr   r   r   r   r	   r
   r   r   r   snowflake.snowpark	snowflake4snowflake.snowpark._internal.proto.generated.ast_pb2snowpark	_internalr   	generatedast_pb24snowflake.snowpark._internal.analyzer.analyzer_utilsr   r   r   r   r   0snowflake.snowpark._internal.analyzer.expressionr   9snowflake.snowpark._internal.analyzer.snowflake_plan_noder   6snowflake.snowpark._internal.analyzer.unary_expressionr   &snowflake.snowpark._internal.ast.utilsr   r   r   r   (snowflake.snowpark._internal.data_sourcer   ?snowflake.snowpark._internal.data_source.datasource_partitionerr   :snowflake.snowpark._internal.data_source.datasource_typingr   .snowflake.snowpark._internal.data_source.utilsr   r   r   r    r!   r"   r#   *snowflake.snowpark._internal.error_messager$   &snowflake.snowpark._internal.telemetryr%   'snowflake.snowpark._internal.type_utilsr&   r'   r(   r)   &snowflake.snowpark._internal.udf_utilsr*   "snowflake.snowpark._internal.utilsr+   r,   r-   r.   r/   r0   r1   r2   r3   r4   r5   r6   r7   r8   r9   r:   r;   r<   r=   r>   snowflake.snowpark.columnr?   r@   rA   snowflake.snowpark.dataframerB   snowflake.snowpark.exceptionsrC   rD   snowflake.snowpark.functionsrE   rF   rG   rH   rI   #snowflake.snowpark.mock._connectionrJ   snowflake.snowpark.tablerK   snowflake.snowpark.typesrL   rM   rN   rO   version_inforR   collections.abcr  r  r  r   r-  _MAX_RETRY_TIMEr   r   r  r   r   r   r   r}   <module>r/     s{    	 	 
  #  M M M   D D D  G R H  : R   W F  M     , T S 2 M L D *  v(	8	&/ # +&#  # !!+)  s s !t ! !HN Nr   