@@ -1178,6 +1178,121 @@ def test_st_hasz(eng, geom, expected):
11781178 eng .assert_query_result (f"SELECT ST_HasZ({ geom_or_null (geom )} )" , expected )
11791179
11801180
1181+ @pytest .mark .parametrize ("eng" , [SedonaDB , PostGIS ])
1182+ @pytest .mark .parametrize (
1183+ ("geom" , "index" , "expected" ),
1184+ [
1185+ # I. Null/Empty/Non-Polygon Inputs
1186+ # NULL input
1187+ (None , 1 , None ),
1188+ # POINT
1189+ ("POINT (0 0)" , 1 , None ),
1190+ # POINT EMPTY
1191+ ("POINT EMPTY" , 1 , None ),
1192+ # LINESTRING
1193+ ("LINESTRING (0 0, 0 1, 1 2)" , 1 , None ),
1194+ # LINESTRING EMPTY
1195+ ("LINESTRING EMPTY" , 1 , None ),
1196+ # MULTIPOINT
1197+ ("MULTIPOINT ((0 0), (1 1))" , 1 , None ),
1198+ # MULTIPOLYGON (Interior rings are within constituent Polygons, not the MultiPolygon itself)
1199+ ("MULTIPOLYGON (((1 1, 1 3, 3 3, 3 1, 1 1)))" , 1 , None ),
1200+ # GEOMETRYCOLLECTION
1201+ ("GEOMETRYCOLLECTION (POINT(1 1))" , 1 , None ),
1202+ # II. Polygon Edge Cases
1203+ # POLYGON EMPTY
1204+ ("POLYGON EMPTY" , 1 , None ),
1205+ # Polygon with NO interior rings, index=1
1206+ ("POLYGON ((0 0, 1 0, 1 1, 0 1, 0 0))" , 1 , None ),
1207+ # Invalid index n=0 (Assuming 1-based indexing means n=0 is invalid/out of range)
1208+ ("POLYGON ((0 0, 1 0, 1 1, 0 1, 0 0))" , 0 , None ),
1209+ # Index n too high (index=2, but 0 holes)
1210+ ("POLYGON ((0 0, 1 0, 1 1, 0 1, 0 0))" , 2 , None ),
1211+ # III. Valid Polygon with Interior Ring(s)
1212+ # Polygon: ((0 0, 4 0, 4 4, 0 4, 0 0), (1 1, 1 2, 2 2, 2 1, 1 1))
1213+ # Single hole, index=1
1214+ (
1215+ "POLYGON ((0 0, 4 0, 4 4, 0 4, 0 0), (1 1, 1 2, 2 2, 2 1, 1 1))" ,
1216+ 1 ,
1217+ "LINESTRING (1 1, 1 2, 2 2, 2 1, 1 1)" ,
1218+ ),
1219+ # Single hole, negative index=-1
1220+ (
1221+ "POLYGON ((0 0, 4 0, 4 4, 0 4, 0 0), (1 1, 1 2, 2 2, 2 1, 1 1))" ,
1222+ - 1 ,
1223+ None ,
1224+ ),
1225+ # Single hole, index=2 (index too high)
1226+ ("POLYGON ((0 0, 4 0, 4 4, 0 4, 0 0), (1 1, 1 2, 2 2, 2 1, 1 1))" , 2 , None ),
1227+ # Polygon: ((0 0, 6 0, 6 6, 0 6, 0 0), (1 1, 1 2, 2 2, 2 1, 1 1), (4 4, 4 5, 5 5, 5 4, 4 4))
1228+ # Two holes, index=1 (first hole)
1229+ (
1230+ "POLYGON ((0 0, 6 0, 6 6, 0 6, 0 0), (1 1, 1 2, 2 2, 2 1, 1 1), (4 4, 4 5, 5 5, 5 4, 4 4))" ,
1231+ 1 ,
1232+ "LINESTRING (1 1, 1 2, 2 2, 2 1, 1 1)" ,
1233+ ),
1234+ # Two holes, index=2 (second hole)
1235+ (
1236+ "POLYGON ((0 0, 6 0, 6 6, 0 6, 0 0), (1 1, 1 2, 2 2, 2 1, 1 1), (4 4, 4 5, 5 5, 5 4, 4 4))" ,
1237+ 2 ,
1238+ "LINESTRING (4 4, 4 5, 5 5, 5 4, 4 4)" ,
1239+ ),
1240+ # Two holes, index=3 (index too high)
1241+ (
1242+ "POLYGON ((0 0, 6 0, 6 6, 0 6, 0 0), (1 1, 1 2, 2 2, 2 1, 1 1), (4 4, 4 5, 5 5, 5 4, 4 4))" ,
1243+ 3 ,
1244+ None ,
1245+ ),
1246+ # IV. Invalid/Malformed Polygon Input
1247+ # External hole (WKT is syntactically valid, second ring is usually treated as a hole by parsers regardless of validity)
1248+ (
1249+ "POLYGON ((0 0, 4 0, 4 4, 0 4, 0 0), (5 5, 5 6, 6 6, 6 5, 5 5))" ,
1250+ 1 ,
1251+ "LINESTRING (5 5, 5 6, 6 6, 6 5, 5 5)" ,
1252+ ),
1253+ # Intersecting holes (WKT is syntactically valid)
1254+ (
1255+ "POLYGON ((0 0, 4 0, 4 4, 0 4, 0 0), (1 1, 1 3, 3 3, 3 1, 1 1), (2 2, 2 2.5, 2.5 2.5, 2.5 2, 2 2))" ,
1256+ 2 ,
1257+ "LINESTRING (2 2, 2 2.5, 2.5 2.5, 2.5 2, 2 2)" ,
1258+ ),
1259+ # Z Dimensions
1260+ ("POINT Z (1 1 5)" , 1 , None ),
1261+ (
1262+ "POLYGON Z ((0 0 10, 4 0 10, 4 4 10, 0 4 10, 0 0 10), (1 1 5, 1 2 5, 2 2 5, 2 1 5, 1 1 5))" ,
1263+ 1 ,
1264+ "LINESTRING Z (1 1 5, 1 2 5, 2 2 5, 2 1 5, 1 1 5)" ,
1265+ ),
1266+ ("POLYGON Z ((0 0 10, 4 0 10, 4 4 10, 0 4 10, 0 0 10))" , 1 , None ),
1267+ # M Dimensions
1268+ ("LINESTRING M (0 0 1, 1 1 2)" , 1 , None ),
1269+ ("POLYGON M ((0 0 1, 4 0 2, 4 4 3, 0 4 4, 0 0 5))" , 1 , None ),
1270+ (
1271+ "POLYGON M ((0 0 1, 4 0 2, 4 4 3, 0 4 4, 0 0 5), (1 1 6, 1 2 7, 2 2 8, 2 1 9, 1 1 10))" ,
1272+ 1 ,
1273+ "LINESTRING M (1 1 6, 1 2 7, 2 2 8, 2 1 9, 1 1 10)" ,
1274+ ),
1275+ # ZM Dimensions
1276+ ("POLYGON ZM EMPTY" , 1 , None ),
1277+ (
1278+ "POLYGON ZM ((0 0 10 1, 4 0 10 2, 4 4 10 3, 0 4 10 4, 0 0 10 5), (1 1 5 6, 1 2 5 7, 2 2 5 8, 2 1 5 9, 1 1 5 10))" ,
1279+ 2 ,
1280+ None ,
1281+ ),
1282+ (
1283+ "POLYGON ZM ((0 0 10 1, 4 0 10 2, 4 4 10 3, 0 4 10 4, 0 0 10 5), (1 1 5 6, 1 2 5 7, 2 2 5 8, 2 1 5 9, 1 1 5 10))" ,
1284+ 1 ,
1285+ "LINESTRING ZM (1 1 5 6, 1 2 5 7, 2 2 5 8, 2 1 5 9, 1 1 5 10)" ,
1286+ ),
1287+ ],
1288+ )
1289+ def test_st_interiorringn (eng , geom , index , expected ):
1290+ eng = eng .create_or_skip ()
1291+ eng .assert_query_result (
1292+ f"SELECT ST_InteriorRingN({ geom_or_null (geom )} , { val_or_null (index )} )" , expected
1293+ )
1294+
1295+
11811296@pytest .mark .parametrize ("eng" , [SedonaDB , PostGIS ])
11821297@pytest .mark .parametrize (
11831298 ("geom" , "expected" ),
0 commit comments