
    hP<                         d dl Z d dlmZ d dlmZ d dlZd dlZd dlZd dl	m
Z
 ed        ZddZ	 	 	 	 	 	 	 ddZd Zd	 Zd
 Zd Zd Z	 	 	 	 	 	 ddZed        Zy)    N)contextmanager)	lru_cache)GeoDataFramec              #   8  K   ddl m}m} t        | |      r3| j	                         s| j                         5  |  ddd       y|  yt        | |      r| j                         5 }| ddd       yt        d|        # 1 sw Y   yxY w# 1 sw Y   yxY ww)a  
    Yield a connection within a transaction context.

    Engine.begin() returns a Connection with an implicit Transaction while
    Connection.begin() returns the Transaction. This helper will always return a
    Connection with an implicit (possibly nested) Transaction.

    Parameters
    ----------
    conn_or_engine : Connection or Engine
        A sqlalchemy Connection or Engine instance

    Returns
    -------
    Connection
    r   )
ConnectionEngineNzUnknown Connectable: )sqlalchemy.engine.baser   r   
isinstancein_transactionbegin
ValueError)conn_or_enginer   r   conns       C/var/www/html/immo/lib/python3.12/site-packages/geopandas/io/sql.py	_get_connr      s     $ :.*-,,.%%' %$$% % ! 	NF	+!!# 	tJ	 	 00@ABB% %
	 	s3   5BB*B&B+BBBBBc                 H   || vrt        d| d      | j                  j                         j                  |      dkD  rt        d| d      | |   j	                         }|j
                  st        j                  j                  }	 d }t        |j                  d   t              r|}n|}|j                  |      x| |<   }|t        j                  |j                  d         }|dk7  r_	 t        ||      }	|	j
                  s|	d   j                         }
|
 d	| }n+d
| d| d}t!        j"                  |t$        d       d| }	 t-        | ||      S # t&        j(                  j*                  $ r* d| d}t!        j"                  |t$        d       d| }Y Tw xY w)a  Transform a pandas DataFrame into a GeoDataFrame.

    The column 'geom_col' must be a geometry column in WKB representation.
    To be used to convert df based on pd.read_sql to gdf.

    Parameters
    ----------
    df : DataFrame
        pandas DataFrame with geometry column in WKB representation.
    geom_col : string, default 'geom'
        column name to convert to shapely geometries
    crs : pyproj.CRS, optional
        CRS to use for the returned GeoDataFrame. The value can be anything accepted
        by :meth:`pyproj.CRS.from_user_input() <pyproj.crs.CRS.from_user_input>`,
        such as an authority string (eg "EPSG:4326") or a WKT string.
        If not set, tries to determine CRS from the SRID associated with the
        first geometry in the database, and assigns that to all geometries.
    con : sqlalchemy.engine.Connection or sqlalchemy.engine.Engine
        Active connection to the database to query.

    Returns
    -------
    GeoDataFrame
    zQuery missing geometry column ''   zDuplicate geometry column 'zC' detected in SQL query output. Onlyone geometry column is allowed.c                 V    t         j                  j                  t        |       d      S )z!Load from binary encoded as text.T)hex)shapelywkbloadsstr)xs    r   load_geom_textz$_df_to_geodf.<locals>.load_geom_textV   s     ;;$$SV$66    r   	auth_name:zCould not find srid z+ in the spatial_ref_sys table. Trying epsg:z as a fallback.   
stacklevelzepsg:z[Could not find the spatial reference system table (spatial_ref_sys) in PostGIS.Trying epsg:)crsgeometry)r   columnsto_listcountdropnaemptyr   r   r   r
   iatbytesapplyget_srid_get_spatial_ref_sys_dfitemwarningswarnUserWarningpderrorsDatabaseErrorr   )dfgeom_colr#   congeomsload_geom_bytesr   	load_geomsridspatial_ref_sys_dfr   warning_msgs               r   _df_to_geodfr?   .   s   2 r:8*AFGG	zz!!(+a/)( 4. .
 	

 xL!E;;!++++(	7 eiilE*'I&I${{9558u;##EIIaL1Dqy-)@d)K& .33$6{$C$H$H$J	!*1TF3 34& 9++/&A $
 !k;1M %dVnh77+ yy.. )''+fO=  
 MM+{qI!$.C)s   .E AF! F!c	           	          |+t        j                  | |||||      }	t        |	      S t        j                  | |||||      }
fd|
D        S )a  Return a GeoDataFrame corresponding to the result of the query
    string, which must contain a geometry column in WKB representation.

    It is also possible to use :meth:`~GeoDataFrame.read_file` to read from a database.
    Especially for file geodatabases like GeoPackage or SpatiaLite this can be easier.

    Parameters
    ----------
    sql : string
        SQL query to execute in selecting entries from database, or name
        of the table to read from the database.
    con : sqlalchemy.engine.Connection or sqlalchemy.engine.Engine
        Active connection to the database to query.
    geom_col : string, default 'geom'
        column name to convert to shapely geometries
    crs : dict or str, optional
        CRS to use for the returned GeoDataFrame; if not set, tries to
        determine CRS from the SRID associated with the first geometry in
        the database, and assigns that to all geometries.
    chunksize : int, default None
        If specified, return an iterator where chunksize is the number of rows to
        include in each chunk.

    See the documentation for pandas.read_sql for further explanation
    of the following parameters:
    index_col, coerce_float, parse_dates, params, chunksize

    Returns
    -------
    GeoDataFrame

    Examples
    --------
    PostGIS

    >>> from sqlalchemy import create_engine  # doctest: +SKIP
    >>> db_connection_url = "postgresql://myusername:mypassword@myhost:5432/mydatabase"
    >>> con = create_engine(db_connection_url)  # doctest: +SKIP
    >>> sql = "SELECT geom, highway FROM roads"
    >>> df = geopandas.read_postgis(sql, con)  # doctest: +SKIP

    SpatiaLite

    >>> sql = "SELECT ST_AsBinary(geom) AS geom, highway FROM roads"
    >>> df = geopandas.read_postgis(sql, con)  # doctest: +SKIP
    )	index_colcoerce_floatparse_datesparams	chunksizer7   r#   r8   c              3   <   K   | ]  }t        |         yw)rF   N)r?   ).0r6   r8   r#   r7   s     r   	<genexpr>z _read_postgis.<locals>.<genexpr>   s$      
FHLhCSAA
s   )r3   read_sqlr?   )sqlr8   r7   r#   rA   rB   rC   rD   rE   r6   df_generators    ```       r   _read_postgisrM   ~   sy    r [[%#
 BsDD {{%#

LX
 	
r   c                 D   t        | j                  j                  j                               }d}|D ]  }|d|v sd} t	        |      dk(  r)|rd}n&|d   t        d      |d   j                         }nd}t        | j                  j                        r|d	z  }||fS )
a  Get basic geometry type of a GeoDataFrame.

    See more info from:
    https://geoalchemy-2.readthedocs.io/en/latest/types.html#geoalchemy2.types._GISType

    Following rules apply:
     - if geometries all share the same geometry-type,
       geometries are inserted with the given GeometryType with following types:
        - Point, LineString, Polygon, MultiPoint, MultiLineString, MultiPolygon,
          GeometryCollection.
        - LinearRing geometries will be converted into LineString -objects.
     - in all other cases, geometries will be inserted with type GEOMETRY:
        - a mix of Polygons and MultiPolygons in GeoSeries
        - a mix of Points and LineStrings in GeoSeries
        - geometry is of type GeometryCollection,
          such as GeometryCollection([Point, LineStrings])
     - if any of the geometries has Z-coordinate, all records will
       be written with 3D.
    F
LinearRingTr   
LINESTRINGr   z No valid geometries in the data.GEOMETRYZ)	listr$   	geom_typeuniquelenr   upperanyhas_z)gdf
geom_types	has_curvegttarget_geom_types        r   _get_geometry_typer_      s    ( cll,,3356JI :RI	 :!+!}$ !CDD#-a=#6#6#8 % 3<<CY&&r   c                 j   d}d}| j                   W	 dD ]Q  }| j                   j                  |      }| n1| j                   j                  d|      }|Ct        |d         } n |d
}t        j                  |t        d	       |S # t        $ r t        j                  |t        d	       Y Iw xY w)z6Get EPSG code from CRS if available. If not, return 0.NzNCould not parse CRS from the GeoDataFrame. Inserting data without defined CRS.)d   F      )min_confidenceESRI)r   rd   r      r!   r   )r#   to_epsgto_authorityint	Exceptionr0   r1   r2   )rZ   r<   r>   
confidence	auth_srids        r   _get_srid_from_crsrm     s     DX  ww	B+ 	
wwjA#GG00$Z 1 	 (y|,D	 |k;1=K  	BMM+{qA	Bs   AB
 B
 
%B21B2c                     ddl m | j                  dk(  }| j                  ||f   j	                  fd      | j                  ||f<   | S )Nr   )
LineStringrO   c                      |       S )N )geomro   s    r   <lambda>z3_convert_linearring_to_linestring.<locals>.<lambda>)  s    Z% r   )shapely.geometryro   rT   locr,   )rZ   	geom_namemaskro   s      @r   !_convert_linearring_to_linestringrx   !  sJ    +
 ==L(D"wwtY7==% CGGD)O Jr   c                     t        j                  t        j                  | |   j                  j                  |      dd      }t        j                  | d      }|||<   |S )zConvert geometries to ewkb.)r<   T)r   include_sridF)copy)r   to_wkbset_sridvalues_datar3   	DataFrame)rZ   rv   r<   r9   r6   s        r   _convert_to_ewkbr   .  sV    NNY..444@E 
c	&BByMIr   c                    dd l }dd l}|j                         }|j                  |      }|j	                  |       |j                  d       dj                  d |D              }|j                  }	d| j                  j                   d| j                  j                   d| d}
|	j                         5 }t        |d      rOt        |j                        r:|j                  |
      5 }|j                  |j!                                d d d        n|j#                  |
|       d d d        y # 1 sw Y   xY w# 1 sw Y   y xY w)	Nr   z, c              3   (   K   | ]
  }d | d   yw)"Nrq   )rH   ks     r   rI   z$_psql_insert_copy.<locals>.<genexpr>G  s     /Q!A3a/s   zCOPY "z"."z" (z) FROM STDIN WITH CSVr{   )csvioStringIOwriter	writerowsseekjoin
connectiontableschemanamecursorhasattrcallabler{   writereadcopy_expert)tblr   keys	data_iterr   r   s_bufr   r%   
dbapi_connrK   curr{   s                r   _psql_insert_copyr   >  s   KKMEZZF
Y	JJqMii/$//GJ
!!"#ciinn%5S	AVW  
			 (3HSXX$6# )$

5::<() ) OOC'( () )( (s$   43D7' D+D7+D4	0D77E c	                    	 ddl m}	 ddlm}
 | j                         } | j                  j                  }t        |       }t        |       \  }}| |	||      ||<   n| |	||      i}|rt        | |      } t        | ||      } ||}nd}|dk(  r|t        |      5 }|j                  j                  |||      rK|j                   |
d	| d
| d
| d            j!                         d   }||k7  rd| d| d}t#        |      ddd       t        |      5 }| j%                  ||||||||t&        	       ddd       y# t        $ r t	        d      w xY w# 1 sw Y   TxY w# 1 sw Y   yxY w)a  
    Upload GeoDataFrame into PostGIS database.

    This method requires SQLAlchemy and GeoAlchemy2, and a PostgreSQL
    Python driver (e.g. psycopg2) to be installed.

    Parameters
    ----------
    name : str
        Name of the target table.
    con : sqlalchemy.engine.Connection or sqlalchemy.engine.Engine
        Active connection to the PostGIS database.
    if_exists : {'fail', 'replace', 'append'}, default 'fail'
        How to behave if the table already exists:

        - fail: Raise a ValueError.
        - replace: Drop the table before inserting new values.
        - append: Insert new values to the existing table.
    schema : string, optional
        Specify the schema. If None, use default schema: 'public'.
    index : bool, default True
        Write DataFrame index as a column.
        Uses *index_label* as the column name in the table.
    index_label : string or sequence, default None
        Column label for index column(s).
        If None is given (default) and index is True,
        then the index names are used.
    chunksize : int, optional
        Rows will be written in batches of this size at a time.
        By default, all rows will be written at once.
    dtype : dict of column name to SQL type, default None
        Specifying the datatype for columns.
        The keys should be the column names and the values
        should be the SQLAlchemy types.

    Examples
    --------
    >>> from sqlalchemy import create_engine  # doctest: +SKIP
    >>> engine = create_engine("postgresql://myusername:mypassword@myhost:5432/mydatabase";)  # doctest: +SKIP
    >>> gdf.to_postgis("my_table", engine)  # doctest: +SKIP
    r   )Geometry)textz,'to_postgis()' requires geoalchemy2 package.N)geometry_typer<   publicappendzSELECT Find_SRID('z', 'z');z"The CRS of the target table (EPSG:z5) differs from the CRS of current GeoDataFrame (EPSG:z).)r   	if_existsindexindex_labelrE   dtypemethod)geoalchemy2r   
sqlalchemyr   ImportErrorr{   r$   r   rm   r_   rx   r   r   dialect	has_tableexecutefetchoner   to_sqlr   )rZ   r   r8   r   r   r   r   rE   r   r   r   rv   r<   r   r\   schema_namer   target_sridmsgs                      r   _write_postgisr   V  s   jJ(# ((*C!!I c"D  2#6M9 #-dKiH=tLM /Y? 3	4
0CHs^ 	*z!!++JfE(00-k]$tfDSVWX(*Q  $&<[M JFFJV2O  %S/)	* 
3 
:

#$ 	 
	

 
]  JHIIJ@	* 	*
 
s$   D? A)EE#?EE #E,c                 8    d| }t        j                  ||       S )Nz9SELECT srid, auth_name FROM spatial_ref_sys WHERE srid = )r3   rJ   )r8   r<   spatial_ref_sys_sqls      r   r.   r.     s(     DD6J  ;;*C00r   )rr   NN)rr   NNTNNN)NfailFNNN)r0   
contextlibr   	functoolsr   pandasr3   r   shapely.wkb	geopandasr   r   r?   rM   r_   rm   rx   r   r   r   r.   rq   r   r   <module>r      s     %     " C C@M8f S
l,'^<
 (8 

q
h 1 1r   