Skip to content

Commit 866773b

Browse files
authored
Improve the layer extent calculation of the MSSQL driver (#5781)
1 parent 848b243 commit 866773b

File tree

1 file changed

+160
-26
lines changed

1 file changed

+160
-26
lines changed

mapmssql2008.c

+160-26
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,7 @@ typedef struct ms_MSSQL2008_layer_info_t {
247247
char *user_srid; /* zero length = calculate, non-zero means using this value! */
248248
char *index_name; /* hopefully this isn't necessary - but if the optimizer ain't cuttin' it... */
249249
char *sort_spec; /* the sort by specification which should be applied to the generated select statement */
250+
int mssqlversion_major; /* the sql server major version number */
250251
SQLSMALLINT *itemtypes; /* storing the sql field types for further reference */
251252

252253
msODBCconn * conn; /* Connection to db */
@@ -973,6 +974,7 @@ int msMSSQL2008LayerOpen(layerObj *layer)
973974
layerinfo->sort_spec = NULL;
974975
layerinfo->conn = NULL;
975976
layerinfo->itemtypes = NULL;
977+
layerinfo->mssqlversion_major = 0;
976978

977979
layerinfo->conn = (msODBCconn *) msConnPoolRequest(layer);
978980

@@ -1102,26 +1104,162 @@ int msMSSQL2008LayerInitItemInfo(layerObj *layer)
11021104
return MS_SUCCESS;
11031105
}
11041106

1107+
static int getMSSQLMajorVersion(layerObj* layer)
1108+
{
1109+
msMSSQL2008LayerInfo *layerinfo = getMSSQL2008LayerInfo(layer);
1110+
if (layerinfo == NULL)
1111+
return 0;
1112+
1113+
if (layerinfo->mssqlversion_major == 0) {
1114+
char* mssqlversion_major = msLayerGetProcessingKey(layer, "MSSQL_VERSION_MAJOR");
1115+
if (mssqlversion_major != NULL) {
1116+
layerinfo->mssqlversion_major = atoi(mssqlversion_major);
1117+
}
1118+
else {
1119+
/* need to query from database */
1120+
if (executeSQL(layerinfo->conn, "SELECT SERVERPROPERTY('ProductVersion')")) {
1121+
SQLRETURN rc = SQLFetch(layerinfo->conn->hstmt);
1122+
if (rc == SQL_SUCCESS || rc == SQL_SUCCESS_WITH_INFO) {
1123+
/* process results */
1124+
char result_data[256];
1125+
SQLLEN retLen = 0;
1126+
1127+
rc = SQLGetData(layerinfo->conn->hstmt, 1, SQL_C_CHAR, result_data, sizeof(result_data), &retLen);
1128+
1129+
if (rc != SQL_ERROR) {
1130+
result_data[retLen] = 0;
1131+
layerinfo->mssqlversion_major = atoi(result_data);
1132+
}
1133+
}
1134+
}
1135+
}
1136+
}
1137+
1138+
return layerinfo->mssqlversion_major;
1139+
}
1140+
11051141
/* Get the layer extent as specified in the mapfile or a largest area */
11061142
/* covering all features */
11071143
int msMSSQL2008LayerGetExtent(layerObj *layer, rectObj *extent)
11081144
{
1109-
if(layer->debug) {
1110-
msDebug("msMSSQL2008LayerGetExtent called\n");
1111-
}
1145+
msMSSQL2008LayerInfo *layerinfo;
1146+
char *query = 0;
1147+
char result_data[256];
1148+
SQLLEN retLen;
1149+
SQLRETURN rc;
1150+
1151+
if(layer->debug) {
1152+
msDebug("msMSSQL2008LayerGetExtent called\n");
1153+
}
11121154

1113-
if (layer->extent.minx == -1.0 && layer->extent.miny == -1.0 &&
1114-
layer->extent.maxx == -1.0 && layer->extent.maxy == -1.0) {
1115-
extent->minx = extent->miny = -1.0 * FLT_MAX;
1116-
extent->maxx = extent->maxy = FLT_MAX;
1117-
} else {
1118-
extent->minx = layer->extent.minx;
1119-
extent->miny = layer->extent.miny;
1120-
extent->maxx = layer->extent.maxx;
1121-
extent->maxy = layer->extent.maxy;
1122-
}
1155+
if (!(layer->extent.minx == -1.0 && layer->extent.miny == -1.0 &&
1156+
layer->extent.maxx == -1.0 && layer->extent.maxy == -1.0)) {
1157+
/* extent was already set */
1158+
extent->minx = layer->extent.minx;
1159+
extent->miny = layer->extent.miny;
1160+
extent->maxx = layer->extent.maxx;
1161+
extent->maxy = layer->extent.maxy;
1162+
}
11231163

1124-
return MS_SUCCESS;
1164+
layerinfo = getMSSQL2008LayerInfo(layer);
1165+
1166+
if (!layerinfo) {
1167+
msSetError(MS_QUERYERR, "GetExtent called with layerinfo = NULL", "msMSSQL2008LayerGetExtent()");
1168+
return MS_FAILURE;
1169+
}
1170+
1171+
/* set up statement */
1172+
if (getMSSQLMajorVersion(layer) >= 11) {
1173+
if (strcasecmp(layerinfo->geom_column_type, "geography") == 0) {
1174+
query = msStringConcatenate(query, "WITH extent(extentcol) AS (SELECT geometry::EnvelopeAggregate(geometry::STGeomFromWKB(");
1175+
query = msStringConcatenate(query, layerinfo->geom_column);
1176+
query = msStringConcatenate(query, ".STAsBinary(), ");
1177+
query = msStringConcatenate(query, layerinfo->geom_column);
1178+
query = msStringConcatenate(query, ".STSrid)");
1179+
}
1180+
else {
1181+
query = msStringConcatenate(query, "WITH extent(extentcol) AS (SELECT geometry::EnvelopeAggregate(");
1182+
query = msStringConcatenate(query, layerinfo->geom_column);
1183+
}
1184+
query = msStringConcatenate(query, ".MakeValid()) AS extentcol FROM ");
1185+
query = msStringConcatenate(query, layerinfo->geom_table);
1186+
query = msStringConcatenate(query, ") SELECT extentcol.STPointN(1).STX, extentcol.STPointN(1).STY, extentcol.STPointN(3).STX, extentcol.STPointN(3).STY FROM extent");
1187+
}
1188+
else {
1189+
if (strcasecmp(layerinfo->geom_column_type, "geography") == 0) {
1190+
query = msStringConcatenate(query, "WITH ENVELOPE as (SELECT geometry::STGeomFromWKB(");
1191+
query = msStringConcatenate(query, layerinfo->geom_column);
1192+
query = msStringConcatenate(query, ".STAsBinary(), ");
1193+
query = msStringConcatenate(query, layerinfo->geom_column);
1194+
query = msStringConcatenate(query, ".STSrid)");
1195+
}
1196+
else {
1197+
query = msStringConcatenate(query, "WITH ENVELOPE as (SELECT ");
1198+
query = msStringConcatenate(query, layerinfo->geom_column);
1199+
}
1200+
query = msStringConcatenate(query, ".MakeValid().STEnvelope() as envelope from ");
1201+
query = msStringConcatenate(query, layerinfo->geom_table);
1202+
query = msStringConcatenate(query, "), CORNERS as (SELECT envelope.STPointN(1) as point from ENVELOPE UNION ALL select envelope.STPointN(3) from ENVELOPE) SELECT MIN(point.STX), MIN(point.STY), MAX(point.STX), MAX(point.STY) FROM CORNERS");
1203+
}
1204+
1205+
if (!executeSQL(layerinfo->conn, query)) {
1206+
msFree(query);
1207+
return MS_FAILURE;
1208+
}
1209+
1210+
msFree(query);
1211+
1212+
/* process results */
1213+
rc = SQLFetch(layerinfo->conn->hstmt);
1214+
1215+
if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
1216+
if (layer->debug) {
1217+
msDebug("msMSSQL2008LayerGetExtent: No results found.\n");
1218+
}
1219+
return MS_FAILURE;
1220+
}
1221+
1222+
rc = SQLGetData(layerinfo->conn->hstmt, 1, SQL_C_CHAR, result_data, sizeof(result_data), &retLen);
1223+
if (rc == SQL_ERROR) {
1224+
msSetError(MS_QUERYERR, "Failed to get MinX value", "msMSSQL2008LayerGetExtent()");
1225+
return MS_FAILURE;
1226+
}
1227+
1228+
result_data[retLen] = 0;
1229+
1230+
extent->minx = atof(result_data);
1231+
1232+
rc = SQLGetData(layerinfo->conn->hstmt, 2, SQL_C_CHAR, result_data, sizeof(result_data), &retLen);
1233+
if (rc == SQL_ERROR) {
1234+
msSetError(MS_QUERYERR, "Failed to get MinY value", "msMSSQL2008LayerGetExtent()");
1235+
return MS_FAILURE;
1236+
}
1237+
1238+
result_data[retLen] = 0;
1239+
1240+
extent->miny = atof(result_data);
1241+
1242+
rc = SQLGetData(layerinfo->conn->hstmt, 3, SQL_C_CHAR, result_data, sizeof(result_data), &retLen);
1243+
if (rc == SQL_ERROR) {
1244+
msSetError(MS_QUERYERR, "Failed to get MaxX value", "msMSSQL2008LayerGetExtent()");
1245+
return MS_FAILURE;
1246+
}
1247+
1248+
result_data[retLen] = 0;
1249+
1250+
extent->maxx = atof(result_data);
1251+
1252+
rc = SQLGetData(layerinfo->conn->hstmt, 4, SQL_C_CHAR, result_data, sizeof(result_data), &retLen);
1253+
if (rc == SQL_ERROR) {
1254+
msSetError(MS_QUERYERR, "Failed to get MaxY value", "msMSSQL2008LayerGetExtent()");
1255+
return MS_FAILURE;
1256+
}
1257+
1258+
result_data[retLen] = 0;
1259+
1260+
extent->maxy = atof(result_data);
1261+
1262+
return MS_SUCCESS;
11251263
}
11261264

11271265
/* Get the layer feature count */
@@ -1358,19 +1496,15 @@ static int prepare_database(layerObj *layer, rectObj rect, char **query_string)
13581496
}
13591497

13601498
/* adding spatial filter */
1361-
msMSSQL2008LayerGetExtent(layer, &extent);
1362-
if (rect.minx > extent.minx || rect.miny > extent.miny ||
1363-
rect.maxx < extent.maxx || rect.maxy < extent.maxy) {
1364-
if (hasFilter == MS_FALSE)
1365-
query = msStringConcatenate(query, " WHERE ");
1366-
else
1367-
query = msStringConcatenate(query, " AND ");
1499+
if (hasFilter == MS_FALSE)
1500+
query = msStringConcatenate(query, " WHERE ");
1501+
else
1502+
query = msStringConcatenate(query, " AND ");
13681503

1369-
query = msStringConcatenate(query, layerinfo->geom_column);
1370-
query = msStringConcatenate(query, ".STIntersects(");
1371-
query = msStringConcatenate(query, box3d);
1372-
query = msStringConcatenate(query, ") = 1 ");
1373-
}
1504+
query = msStringConcatenate(query, layerinfo->geom_column);
1505+
query = msStringConcatenate(query, ".MakeValid().STIntersects(");
1506+
query = msStringConcatenate(query, box3d);
1507+
query = msStringConcatenate(query, ") = 1 ");
13741508

13751509
if (layerinfo->sort_spec)
13761510
query = msStringConcatenate(query, layerinfo->sort_spec);

0 commit comments

Comments
 (0)