Repository: geopandas/geopandas

Issue:
Append to PostGIS table not working when table does not exist 
@jorisvandenbossche @martinfleis 
When table does not exist in the PostGIS database, using the `if_exists="append"` raises an error because SRID check is attempted from non-existing table.

Fix is on the way. 


Discussion:

Resolving patch:
diff --git a/geopandas/io/sql.py b/geopandas/io/sql.py
--- a/geopandas/io/sql.py
+++ b/geopandas/io/sql.py
@@ -324,20 +324,22 @@ def _write_postgis(
             else:
                 schema_name = "public"
 
-            target_srid = connection.execute(
-                "SELECT Find_SRID('{schema}', '{table}', '{geom_col}');".format(
-                    schema=schema_name, table=name, geom_col=geom_name
-                )
-            ).fetchone()[0]
-
-            if target_srid != srid:
-                msg = (
-                    "The CRS of the target table (EPSG:{epsg_t}) differs from the "
-                    "CRS of current GeoDataFrame (EPSG:{epsg_src}).".format(
-                        epsg_t=target_srid, epsg_src=srid
+            # Only check SRID if table exists
+            if connection.run_callable(connection.dialect.has_table, name, schema):
+                target_srid = connection.execute(
+                    "SELECT Find_SRID('{schema}', '{table}', '{geom_col}');".format(
+                        schema=schema_name, table=name, geom_col=geom_name
                     )
-                )
-                raise ValueError(msg)
+                ).fetchone()[0]
+
+                if target_srid != srid:
+                    msg = (
+                        "The CRS of the target table (EPSG:{epsg_t}) differs from the "
+                        "CRS of current GeoDataFrame (EPSG:{epsg_src}).".format(
+                            epsg_t=target_srid, epsg_src=srid
+                        )
+                    )
+                    raise ValueError(msg)
 
     with con.begin() as connection:
 


Test patch:
diff --git a/geopandas/io/tests/test_sql.py b/geopandas/io/tests/test_sql.py
--- a/geopandas/io/tests/test_sql.py
+++ b/geopandas/io/tests/test_sql.py
@@ -585,3 +585,36 @@ def test_row_order(self, engine_postgis, df_nybb):
         sql = "SELECT * FROM {table};".format(table=table)
         df = read_postgis(sql, engine, geom_col="geometry")
         assert df["BoroCode"].tolist() == correct_order
+
+    def test_append_before_table_exists(self, engine_postgis, df_nybb):
+        """
+        Tests that insert works with if_exists='append' when table does not exist yet.
+        """
+        engine = engine_postgis
+
+        table = "nybb"
+        # If table exists, delete it before trying to write with defaults
+        drop_table_if_exists(engine, table)
+
+        write_postgis(df_nybb, con=engine, name=table, if_exists="append")
+
+        # Check that the row order matches
+        sql = "SELECT * FROM {table};".format(table=table)
+        df = read_postgis(sql, engine, geom_col="geometry")
+        validate_boro_df(df)
+
+    def test_append_with_different_crs(self, engine_postgis, df_nybb):
+        """
+        Tests that the warning is raised if table CRS differs from frame.
+        """
+        engine = engine_postgis
+
+        table = "nybb"
+        write_postgis(df_nybb, con=engine, name=table, if_exists="replace")
+
+        # Reproject
+        df_nybb2 = df_nybb.to_crs(epsg=4326)
+
+        # Should raise error when appending
+        with pytest.raises(ValueError, match="CRS of the target table"):
+            write_postgis(df_nybb2, con=engine, name=table, if_exists="append")