1
|
Index: src/app/postgres/qgspgsourceselect.cpp
|
2
|
===================================================================
|
3
|
--- src/app/postgres/qgspgsourceselect.cpp (revision 13803)
|
4
|
+++ src/app/postgres/qgspgsourceselect.cpp (working copy)
|
5
|
@@ -606,66 +606,105 @@
|
6
|
|
7
|
bool QgsPgSourceSelect::getTableInfo( PGconn *pg, bool searchGeometryColumnsOnly, bool searchPublicOnly )
|
8
|
{
|
9
|
- int n = 0;
|
10
|
+ int nColumns = 0;
|
11
|
+ int nGTables = 0;
|
12
|
QApplication::setOverrideCursor( Qt::WaitCursor );
|
13
|
|
14
|
- // The following query returns only tables that exist and the user has SELECT privilege on.
|
15
|
- // Can't use regclass here because table must exist, else error occurs.
|
16
|
- QString sql = "select "
|
17
|
- "f_table_name,"
|
18
|
- "f_table_schema,"
|
19
|
- "f_geometry_column,"
|
20
|
- "type,"
|
21
|
- "pg_class.relkind"
|
22
|
- " from "
|
23
|
- "geometry_columns,"
|
24
|
- "pg_class,"
|
25
|
- "pg_namespace"
|
26
|
- " where "
|
27
|
- "relname=f_table_name"
|
28
|
- " and f_table_schema=nspname"
|
29
|
- " and pg_namespace.oid=pg_class.relnamespace"
|
30
|
- " and has_schema_privilege(pg_namespace.nspname,'usage')"
|
31
|
- " and has_table_privilege('\"'||pg_namespace.nspname||'\".\"'||pg_class.relname||'\"','select')" // user has select privilege
|
32
|
- " order by "
|
33
|
- "f_table_schema,f_table_name,f_geometry_column";
|
34
|
+ PGresult *result = 0;
|
35
|
|
36
|
- PGresult *result = PQexec( pg, sql.toUtf8() );
|
37
|
- if ( result )
|
38
|
+ for ( int i = 0; i < 2; i++ )
|
39
|
{
|
40
|
- if ( PQresultStatus( result ) != PGRES_TUPLES_OK )
|
41
|
+ QString gtableName, columnName;
|
42
|
+
|
43
|
+ if ( i == 0 )
|
44
|
{
|
45
|
- QMessageBox::warning( this,
|
46
|
- tr( "Accessible tables could not be determined" ),
|
47
|
- tr( "Database connection was successful, but the accessible tables could not be determined.\n\n"
|
48
|
- "The error message from the database was:\n%1\n" )
|
49
|
- .arg( QString::fromUtf8( PQresultErrorMessage( result ) ) ) );
|
50
|
- n = -1;
|
51
|
+ gtableName = "geometry_columns";
|
52
|
+ columnName = "f_geometry_column";
|
53
|
}
|
54
|
- else if ( PQntuples( result ) > 0 )
|
55
|
+ else if ( i == 1 )
|
56
|
{
|
57
|
- for ( int idx = 0; idx < PQntuples( result ); idx++ )
|
58
|
+ gtableName = "geography_columns";
|
59
|
+ columnName = "f_geography_column";
|
60
|
+ }
|
61
|
+
|
62
|
+ // The following query returns only tables that exist and the user has SELECT privilege on.
|
63
|
+ // Can't use regclass here because table must exist, else error occurs.
|
64
|
+ QString sql = QString( "select "
|
65
|
+ "f_table_name,"
|
66
|
+ "f_table_schema,"
|
67
|
+ "%2,"
|
68
|
+ "upper(type),"
|
69
|
+ "pg_class.relkind"
|
70
|
+ " from "
|
71
|
+ "%1,"
|
72
|
+ "pg_class,"
|
73
|
+ "pg_namespace"
|
74
|
+ " where "
|
75
|
+ "relname=f_table_name"
|
76
|
+ " and f_table_schema=nspname"
|
77
|
+ " and pg_namespace.oid=pg_class.relnamespace"
|
78
|
+ " and has_schema_privilege(pg_namespace.nspname,'usage')"
|
79
|
+ " and has_table_privilege('\"'||pg_namespace.nspname||'\".\"'||pg_class.relname||'\"','select')" // user has select privilege
|
80
|
+ " order by "
|
81
|
+ "f_table_schema,f_table_name,%2" ).arg( gtableName ).arg( columnName );
|
82
|
+
|
83
|
+ QgsDebugMsg( "sql: " + sql );
|
84
|
+
|
85
|
+ result = PQexec( pg, sql.toUtf8() );
|
86
|
+ if ( result )
|
87
|
+ {
|
88
|
+ if ( PQresultStatus( result ) != PGRES_TUPLES_OK )
|
89
|
{
|
90
|
- QString tableName = QString::fromUtf8( PQgetvalue( result, idx, 0 ) );
|
91
|
- QString schemaName = QString::fromUtf8( PQgetvalue( result, idx, 1 ) );
|
92
|
- QString column = QString::fromUtf8( PQgetvalue( result, idx, 2 ) );
|
93
|
- QString type = QString::fromUtf8( PQgetvalue( result, idx, 3 ) );
|
94
|
- QString relkind = QString::fromUtf8( PQgetvalue( result, idx, 4 ) );
|
95
|
+ PGresult *r = PQexec( pg, "COMMIT" );
|
96
|
+ if ( r )
|
97
|
+ PQclear( r );
|
98
|
+ }
|
99
|
+ else
|
100
|
+ {
|
101
|
+ nGTables++;
|
102
|
|
103
|
- QString as = "";
|
104
|
- if ( type == "GEOMETRY" && !searchGeometryColumnsOnly )
|
105
|
+ if ( PQntuples( result ) > 0 )
|
106
|
{
|
107
|
- addSearchGeometryColumn( schemaName, tableName, column );
|
108
|
- as = type = "WAITING";
|
109
|
+
|
110
|
+ for ( int idx = 0; idx < PQntuples( result ); idx++ )
|
111
|
+ {
|
112
|
+ QString tableName = QString::fromUtf8( PQgetvalue( result, idx, 0 ) );
|
113
|
+ QString schemaName = QString::fromUtf8( PQgetvalue( result, idx, 1 ) );
|
114
|
+ QString column = QString::fromUtf8( PQgetvalue( result, idx, 2 ) );
|
115
|
+ QString type = QString::fromUtf8( PQgetvalue( result, idx, 3 ) );
|
116
|
+ QString relkind = QString::fromUtf8( PQgetvalue( result, idx, 4 ) );
|
117
|
+
|
118
|
+ QgsDebugMsg( QString( "%1 %2.%3.%4: %5 %6" )
|
119
|
+ .arg( gtableName )
|
120
|
+ .arg( schemaName ).arg( tableName ).arg( column )
|
121
|
+ .arg( type )
|
122
|
+ .arg( relkind ) );
|
123
|
+
|
124
|
+ QString as = "";
|
125
|
+ if ( type == "GEOMETRY" && !searchGeometryColumnsOnly )
|
126
|
+ {
|
127
|
+ addSearchGeometryColumn( schemaName, tableName, column );
|
128
|
+ as = type = "WAITING";
|
129
|
+ }
|
130
|
+
|
131
|
+ mTableModel.addTableEntry( type, schemaName, tableName, column, relkind == "v" ? pkCandidates( pg, schemaName, tableName ) : QStringList(), "" );
|
132
|
+ nColumns++;
|
133
|
+ }
|
134
|
}
|
135
|
-
|
136
|
- mTableModel.addTableEntry( type, schemaName, tableName, column, relkind == "v" ? pkCandidates( pg, schemaName, tableName ) : QStringList(), "" );
|
137
|
- n++;
|
138
|
}
|
139
|
}
|
140
|
+
|
141
|
+ PQclear( result );
|
142
|
+ result = 0;
|
143
|
}
|
144
|
|
145
|
- PQclear( result );
|
146
|
+ if ( nColumns == 0 )
|
147
|
+ {
|
148
|
+ QMessageBox::warning( this,
|
149
|
+ tr( "Accessible tables could not be determined" ),
|
150
|
+ tr( "Database connection was successful, but the accessible tables could not be determined." ) );
|
151
|
+ nColumns = -1;
|
152
|
+ }
|
153
|
|
154
|
//search for geometry columns in tables that are not in the geometry_columns metatable
|
155
|
QApplication::restoreOverrideCursor();
|
156
|
@@ -676,39 +715,47 @@
|
157
|
// geometry_columns table. This code is specific to postgresql,
|
158
|
// but an equivalent query should be possible in other
|
159
|
// databases.
|
160
|
- sql = "select "
|
161
|
- "pg_class.relname,"
|
162
|
- "pg_namespace.nspname,"
|
163
|
- "pg_attribute.attname,"
|
164
|
- "pg_class.relkind"
|
165
|
- " from "
|
166
|
- "pg_attribute,"
|
167
|
- "pg_class,"
|
168
|
- "pg_namespace"
|
169
|
- " where "
|
170
|
- "pg_namespace.oid = pg_class.relnamespace"
|
171
|
- " and pg_attribute.attrelid = pg_class.oid "
|
172
|
- " and ("
|
173
|
- "pg_attribute.atttypid = regtype('geometry')"
|
174
|
- " or pg_attribute.atttypid IN (select oid FROM pg_type WHERE typbasetype=regtype('geometry'))"
|
175
|
- ")"
|
176
|
- " and has_schema_privilege(pg_namespace.nspname,'usage')"
|
177
|
- " and has_table_privilege('\"'||pg_namespace.nspname||'\".\"'||pg_class.relname||'\"','select')";
|
178
|
+ QString sql = "select "
|
179
|
+ "pg_class.relname"
|
180
|
+ ",pg_namespace.nspname"
|
181
|
+ ",pg_attribute.attname"
|
182
|
+ ",pg_class.relkind"
|
183
|
+ " from "
|
184
|
+ "pg_attribute"
|
185
|
+ ",pg_class"
|
186
|
+ ",pg_namespace"
|
187
|
+ " where "
|
188
|
+ "pg_namespace.oid=pg_class.relnamespace"
|
189
|
+ " and pg_attribute.attrelid = pg_class.oid"
|
190
|
+ " and ("
|
191
|
+ "pg_attribute.atttypid::regtype::text IN ('geometry','geography')"
|
192
|
+ " or pg_attribute.atttypid IN (select oid FROM pg_type WHERE typbasetype::regtype::text IN ('geometry','geography'))"
|
193
|
+ ")"
|
194
|
+ " and has_schema_privilege( pg_namespace.nspname, 'usage' )"
|
195
|
+ " and has_table_privilege( '\"' || pg_namespace.nspname || '\".\"' || pg_class.relname || '\"', 'select' )";
|
196
|
+
|
197
|
// user has select privilege
|
198
|
if ( searchPublicOnly )
|
199
|
sql += " and pg_namespace.nspname = 'public'";
|
200
|
|
201
|
- if ( n > 0 )
|
202
|
+ if ( nColumns > 0 )
|
203
|
{
|
204
|
sql += " and not exists (select * from geometry_columns WHERE pg_namespace.nspname=f_table_schema AND pg_class.relname=f_table_name)";
|
205
|
+
|
206
|
+ if ( nGTables > 1 )
|
207
|
+ {
|
208
|
+ sql += " and not exists (select * from geography_columns WHERE pg_namespace.nspname=f_table_schema AND pg_class.relname=f_table_name)";
|
209
|
+ }
|
210
|
}
|
211
|
else
|
212
|
{
|
213
|
- n = 0;
|
214
|
+ nColumns = 0;
|
215
|
}
|
216
|
|
217
|
- sql += " and pg_class.relkind in ('v', 'r')"; // only from views and relations (tables)
|
218
|
+ sql += " and pg_class.relkind in( 'v', 'r' )"; // only from views and relations (tables)
|
219
|
|
220
|
+ QgsDebugMsg( "sql: " + sql );
|
221
|
+
|
222
|
result = PQexec( pg, sql.toUtf8() );
|
223
|
|
224
|
if ( PQresultStatus( result ) != PGRES_TUPLES_OK )
|
225
|
@@ -718,8 +765,8 @@
|
226
|
tr( "Database connection was successful, but the accessible tables could not be determined.\n\n"
|
227
|
"The error message from the database was:\n%1\n" )
|
228
|
.arg( QString::fromUtf8( PQresultErrorMessage( result ) ) ) );
|
229
|
- if ( n == 0 )
|
230
|
- n = -1;
|
231
|
+ if ( nColumns == 0 )
|
232
|
+ nColumns = -1;
|
233
|
}
|
234
|
else if ( PQntuples( result ) > 0 )
|
235
|
{
|
236
|
@@ -737,17 +784,20 @@
|
237
|
QString column = QString::fromUtf8( PQgetvalue( result, i, 2 ) ); // attname
|
238
|
QString relkind = QString::fromUtf8( PQgetvalue( result, i, 3 ) ); // relation kind
|
239
|
|
240
|
+ QgsDebugMsg( QString( "%1.%2.%3: %4" ).arg( schema ).arg( table ).arg( column ).arg( relkind ) );
|
241
|
+
|
242
|
addSearchGeometryColumn( schema, table, column );
|
243
|
//details.push_back(geomPair(fullDescription(schema, table, column, "WAITING"), "WAITING"));
|
244
|
- mTableModel.addTableEntry( "Waiting", schema, table, column, relkind == "v" ? pkCandidates( pg, schema, table ) : QStringList(), "" );
|
245
|
- n++;
|
246
|
+ mTableModel.addTableEntry( tr( "Waiting" ), schema, table, column, relkind == "v" ? pkCandidates( pg, schema, table ) : QStringList(), "" );
|
247
|
+ nColumns++;
|
248
|
}
|
249
|
}
|
250
|
|
251
|
PQclear( result );
|
252
|
+ result = 0;
|
253
|
}
|
254
|
|
255
|
- if ( n == 0 )
|
256
|
+ if ( nColumns == 0 )
|
257
|
{
|
258
|
QMessageBox::warning( this,
|
259
|
tr( "No accessible tables found" ),
|
260
|
@@ -756,7 +806,7 @@
|
261
|
"geometry." ) );
|
262
|
}
|
263
|
|
264
|
- return n > 0;
|
265
|
+ return nColumns > 0;
|
266
|
}
|
267
|
|
268
|
QString QgsPgSourceSelect::fullDescription( QString schema, QString table,
|
269
|
@@ -852,7 +902,9 @@
|
270
|
query += "\"" + schemas[i] + "\".\"" + tables[i] + "\"";
|
271
|
}
|
272
|
|
273
|
- PGresult* gresult = PQexec( pd, query.toUtf8() );
|
274
|
+ QgsDebugMsg( "sql: " + query );
|
275
|
+
|
276
|
+ PGresult *gresult = PQexec( pd, query.toUtf8() );
|
277
|
QString type;
|
278
|
if ( PQresultStatus( gresult ) == PGRES_TUPLES_OK )
|
279
|
{
|
280
|
Index: src/providers/postgres/qgspostgresprovider.h
|
281
|
===================================================================
|
282
|
--- src/providers/postgres/qgspostgresprovider.h (revision 13803)
|
283
|
+++ src/providers/postgres/qgspostgresprovider.h (working copy)
|
284
|
@@ -383,6 +383,11 @@
|
285
|
bool isQuery;
|
286
|
|
287
|
/**
|
288
|
+ * geometry is geography
|
289
|
+ */
|
290
|
+ bool isGeography;
|
291
|
+
|
292
|
+ /**
|
293
|
* Name of the table with no schema
|
294
|
*/
|
295
|
QString mTableName;
|
296
|
Index: src/providers/postgres/qgspostgresprovider.cpp
|
297
|
===================================================================
|
298
|
--- src/providers/postgres/qgspostgresprovider.cpp (revision 13803)
|
299
|
+++ src/providers/postgres/qgspostgresprovider.cpp (working copy)
|
300
|
@@ -68,7 +68,6 @@
|
301
|
|
302
|
providerId = providerIds++;
|
303
|
|
304
|
- QgsDebugMsg( "Postgresql Layer Creation" );
|
305
|
QgsDebugMsg( "URI: " + uri );
|
306
|
|
307
|
mUri = QgsDataSourceURI( uri );
|
308
|
@@ -78,6 +77,7 @@
|
309
|
mTableName = mUri.table();
|
310
|
geometryColumn = mUri.geometryColumn();
|
311
|
sqlWhereClause = mUri.sql();
|
312
|
+ isGeography = false;
|
313
|
|
314
|
if ( mSchemaName.isEmpty() &&
|
315
|
mTableName.startsWith( "(select", Qt::CaseInsensitive ) &&
|
316
|
@@ -374,6 +374,10 @@
|
317
|
{
|
318
|
return QString( "asewkt(%1)" ).arg( quotedIdentifier( fld.name() ) );
|
319
|
}
|
320
|
+ else if ( type == "geography" )
|
321
|
+ {
|
322
|
+ return QString( "st_astext(%1)" ).arg( quotedIdentifier( fld.name() ) );
|
323
|
+ }
|
324
|
else
|
325
|
{
|
326
|
return quotedIdentifier( fld.name() ) + "::text";
|
327
|
@@ -392,9 +396,16 @@
|
328
|
|
329
|
if ( fetchGeometry )
|
330
|
{
|
331
|
- query += QString( ",asbinary(%1,'%2')" )
|
332
|
- .arg( quotedIdentifier( geometryColumn ) )
|
333
|
- .arg( endianString() );
|
334
|
+ if ( isGeography )
|
335
|
+ {
|
336
|
+ query += QString( ",st_asbinary(%1)" ).arg( quotedIdentifier( geometryColumn ) );
|
337
|
+ }
|
338
|
+ else
|
339
|
+ {
|
340
|
+ query += QString( ",asbinary(%1,'%2')" )
|
341
|
+ .arg( quotedIdentifier( geometryColumn ) )
|
342
|
+ .arg( endianString() );
|
343
|
+ }
|
344
|
}
|
345
|
|
346
|
for ( QgsAttributeList::const_iterator it = fetchAttributes.constBegin(); it != fetchAttributes.constEnd(); ++it )
|
347
|
@@ -539,21 +550,32 @@
|
348
|
|
349
|
if ( !rect.isEmpty() )
|
350
|
{
|
351
|
- if ( useIntersect )
|
352
|
+ if ( isGeography )
|
353
|
{
|
354
|
- // Contributed by #qgis irc "creeping"
|
355
|
- // This version actually invokes PostGIS's use of spatial indexes
|
356
|
- whereClause = QString( "%1 && setsrid('BOX3D(%2)'::box3d,%3) and intersects(%1,setsrid('BOX3D(%2)'::box3d,%3))" )
|
357
|
- .arg( quotedIdentifier( geometryColumn ) )
|
358
|
- .arg( rect.asWktCoordinates() )
|
359
|
- .arg( srid );
|
360
|
+ rect = QgsRectangle( -180.0, -90.0, 180.0, 90.0 ).intersect( &rect );
|
361
|
+ if ( !rect.isFinite() )
|
362
|
+ whereClause = "false";
|
363
|
}
|
364
|
- else
|
365
|
+
|
366
|
+ if ( whereClause.isEmpty() )
|
367
|
{
|
368
|
- whereClause = QString( "%1 && setsrid('BOX3D(%2)'::box3d,%3)" )
|
369
|
- .arg( quotedIdentifier( geometryColumn ) )
|
370
|
- .arg( rect.asWktCoordinates() )
|
371
|
- .arg( srid );
|
372
|
+
|
373
|
+ if ( useIntersect )
|
374
|
+ {
|
375
|
+ // Contributed by #qgis irc "creeping"
|
376
|
+ // This version actually invokes PostGIS's use of spatial indexes
|
377
|
+ whereClause = QString( "%1 && setsrid('BOX3D(%2)'::box3d,%3) and intersects(%1,setsrid('BOX3D(%2)'::box3d,%3))" )
|
378
|
+ .arg( quotedIdentifier( geometryColumn ) )
|
379
|
+ .arg( rect.asWktCoordinates() )
|
380
|
+ .arg( srid );
|
381
|
+ }
|
382
|
+ else
|
383
|
+ {
|
384
|
+ whereClause = QString( "%1 && setsrid('BOX3D(%2)'::box3d,%3)" )
|
385
|
+ .arg( quotedIdentifier( geometryColumn ) )
|
386
|
+ .arg( rect.asWktCoordinates() )
|
387
|
+ .arg( srid );
|
388
|
+ }
|
389
|
}
|
390
|
}
|
391
|
|
392
|
@@ -2305,6 +2327,10 @@
|
393
|
{
|
394
|
values += QString( ",geomfromewkt(%1)" ).arg( quotedValue( it->toString() ) );
|
395
|
}
|
396
|
+ else if ( fit->typeName() == "geography" )
|
397
|
+ {
|
398
|
+ values += QString( ",st_geographyfromewkt(%1)" ).arg( quotedValue( it->toString() ) );
|
399
|
+ }
|
400
|
else
|
401
|
{
|
402
|
values += "," + quotedValue( it->toString() );
|
403
|
@@ -2317,6 +2343,10 @@
|
404
|
{
|
405
|
values += QString( ",geomfromewkt($%1)" ).arg( defaultValues.size() + offset );
|
406
|
}
|
407
|
+ else if ( fit->typeName() == "geography" )
|
408
|
+ {
|
409
|
+ values += QString( ",st_geographyfromewkt($%1)" ).arg( defaultValues.size() + offset );
|
410
|
+ }
|
411
|
else
|
412
|
{
|
413
|
values += QString( ",$%1" ).arg( defaultValues.size() + offset );
|
414
|
@@ -2576,7 +2606,9 @@
|
415
|
else
|
416
|
first = false;
|
417
|
|
418
|
- sql += QString( fld.typeName() != "geometry" ? "%1=%2" : "%1=geomfromewkt(%2)" )
|
419
|
+ sql += QString( fld.typeName() == "geometry" ? "%1=geomfromewkt(%2)" :
|
420
|
+ fld.typeName() == "geography" ? "%1=st_geographyfromewkt(%2)" :
|
421
|
+ "%1=%2" )
|
422
|
.arg( quotedIdentifier( fld.name() ) )
|
423
|
.arg( quotedValue( siter->toString() ) );
|
424
|
}
|
425
|
@@ -2779,6 +2811,9 @@
|
426
|
|
427
|
QgsRectangle QgsPostgresProvider::extent()
|
428
|
{
|
429
|
+ if ( isGeography )
|
430
|
+ return QgsRectangle( -180.0, -90.0, 180.0, 90.0 );
|
431
|
+
|
432
|
if ( layerExtent.isEmpty() )
|
433
|
{
|
434
|
QString sql;
|
435
|
@@ -2986,7 +3021,6 @@
|
436
|
.arg( quotedValue( schemaName ) );
|
437
|
|
438
|
QgsDebugMsg( "Getting geometry column: " + sql );
|
439
|
-
|
440
|
result = connectionRO->PQexec( sql );
|
441
|
|
442
|
QgsDebugMsg( "geometry column query returned " + QString::number( PQntuples( result ) ) );
|
443
|
@@ -2999,6 +3033,28 @@
|
444
|
|
445
|
if ( srid.isEmpty() || fType.isEmpty() )
|
446
|
{
|
447
|
+ sql = QString( "select upper(type),srid from geography_columns"
|
448
|
+ " where f_table_name=%1 and f_geography_column=%2 and f_table_schema=%3" )
|
449
|
+ .arg( quotedValue( tableName ) )
|
450
|
+ .arg( quotedValue( geomCol ) )
|
451
|
+ .arg( quotedValue( schemaName ) );
|
452
|
+
|
453
|
+ QgsDebugMsg( "Getting geography column: " + sql );
|
454
|
+ result = connectionRO->PQexec( sql );
|
455
|
+
|
456
|
+ QgsDebugMsg( "geography column query returned " + QString::number( PQntuples( result ) ) );
|
457
|
+
|
458
|
+ if ( PQntuples( result ) > 0 )
|
459
|
+ {
|
460
|
+ fType = QString::fromUtf8( PQgetvalue( result, 0, 0 ) );
|
461
|
+ srid = QString::fromUtf8( PQgetvalue( result, 0, 1 ) );
|
462
|
+
|
463
|
+ isGeography = true;
|
464
|
+ }
|
465
|
+ }
|
466
|
+
|
467
|
+ if ( srid.isEmpty() || fType.isEmpty() )
|
468
|
+ {
|
469
|
// Didn't find what we need in the geometry_columns table, so
|
470
|
// get stuff from the relevant column instead. This may (will?)
|
471
|
// fail if there is no data in the relevant table.
|
472
|
@@ -3116,6 +3172,7 @@
|
473
|
QgsDebugMsg( "type is " + fType );
|
474
|
QgsDebugMsg( "Feature type is " + QString::number( geomType ) );
|
475
|
QgsDebugMsg( "Feature type name is " + QString( QGis::qgisFeatureTypes[geomType] ) );
|
476
|
+ QgsDebugMsg( "Geometry is geography " + isGeography );
|
477
|
}
|
478
|
else
|
479
|
{
|