patch_for_bug_964.txt

Steven Mizuno, 2008-03-08 06:59 AM

Download (68.1 KB)

 
1
Index: src/app/qgspgquerybuilder.cpp
2
===================================================================
3
--- src/app/qgspgquerybuilder.cpp	(revision 8182)
4
+++ src/app/qgspgquerybuilder.cpp	(working copy)
5
@@ -40,7 +40,7 @@
6
 
7
   QgsDebugMsg("Attempting connect using: " + connInfo); 
8
 
9
-  mPgConnection = PQconnectdb(connInfo.toLocal8Bit().data());
10
+  mPgConnection = PQconnectdb(connInfo.toLocal8Bit().data());	// use what is set based on locale; after connecting, use Utf8
11
   // check the connection status
12
   if (PQstatus(mPgConnection) == CONNECTION_OK) {
13
     QString datasource = QString(tr("Table <b>%1</b> in database <b>%2</b> on host <b>%3</b>, user <b>%4</b>"))
14
@@ -57,7 +57,7 @@
15
   }
16
   else
17
   {
18
-    QString err = PQerrorMessage(mPgConnection);
19
+    QString err = QString::fromLocal8Bit(PQerrorMessage(mPgConnection));
20
     QMessageBox::critical(this, tr("Connection Failed"), tr("Connection to the database failed:") + "\n" + err);
21
   }
22
 }
23
@@ -96,22 +96,21 @@
24
   // Populate the field vector for this layer. The field vector contains
25
   // field name, type, length, and precision (if numeric)
26
   QString sql = "select * from " + mUri->quotedTablename() + " limit 1";
27
-  PGresult *result = PQexec(mPgConnection, (const char *) (sql.utf8()));
28
+  PGresult *result = PQexec(mPgConnection, sql.toUtf8());
29
   QgsLogger::debug("Query executed: " + sql);
30
   if (PQresultStatus(result) == PGRES_TUPLES_OK) 
31
   {
32
     //--std::cout << "Field: Name, Type, Size, Modifier:" << std::endl;
33
     for (int i = 0; i < PQnfields(result); i++) {
34
 
35
-      QString fieldName = PQfname(result, i);
36
+      QString fieldName = QString::fromUtf8(PQfname(result, i));
37
       int fldtyp = PQftype(result, i);
38
       QString typOid = QString().setNum(fldtyp);
39
       QgsLogger::debug("typOid is: " + typOid); 
40
       //int fieldModifier = PQfmod(result, i);
41
       QString sql = "select typelem from pg_type where typelem = " + typOid + " and typlen = -1";
42
       //  //--std::cout << sql << std::endl;
43
-      PGresult *oidResult = PQexec(mPgConnection, 
44
-				   (const char *) (sql.utf8()));
45
+      PGresult *oidResult = PQexec(mPgConnection, sql.toUtf8());
46
       if (PQresultStatus(oidResult) == PGRES_TUPLES_OK) 
47
         QgsLogger::debug("Ok fetching typelem using\n" + sql); 
48
 
49
@@ -123,7 +122,7 @@
50
       PQclear(oidResult);
51
       sql = "select typname, typlen from pg_type where oid = " + poid;
52
       // //--std::cout << sql << std::endl;
53
-      oidResult = PQexec(mPgConnection, (const char *) (sql.utf8()));
54
+      oidResult = PQexec(mPgConnection, sql.toUtf8());
55
       if (PQresultStatus(oidResult) == PGRES_TUPLES_OK) 
56
         QgsLogger::debug("Ok fetching typenam,etc\n");
57
 
58
@@ -180,9 +179,9 @@
59
   
60
   // determine the field type
61
   QgsField field = mFieldMap[mModelFields->data(lstFields->currentIndex()).toString()];
62
-  bool mActualFieldIsChar = field.typeName().find("char") > -1;
63
+  mActualFieldIsChar = field.typeName().find("char") > -1 || field.typeName().find("text") > -1 ;	// really should be: field.type()==QVariant::String - but is not set correctly above
64
   
65
-  PGresult *result = PQexec(mPgConnection, (const char *) (theSQL.utf8()));
66
+  PGresult *result = PQexec(mPgConnection, theSQL.toUtf8());
67
 
68
   if (PQresultStatus(result) == PGRES_TUPLES_OK) 
69
   {
70
@@ -196,7 +195,7 @@
71
     }
72
   }else
73
   {
74
-    QMessageBox::warning(this, tr("Database error"), tr("<p>Failed to get sample of field values using SQL:</p><p>") + theSQL + "</p><p>Error message was: "+ QString(PQerrorMessage(mPgConnection)) + "</p>");
75
+    QMessageBox::warning(this, tr("Database error"), tr("<p>Failed to get sample of field values using SQL:</p><p>") + theSQL + "</p><p>Error message was: "+ QString::fromUtf8(PQerrorMessage(mPgConnection)) + "</p>");
76
   }
77
   // free the result set
78
   PQclear(result);
79
@@ -210,7 +209,6 @@
80
       return;
81
   
82
   QgsField field = mFieldMap[mModelFields->data(lstFields->currentIndex()).toString()];
83
-  bool mActualFieldIsChar = field.typeName().find("char") > -1;
84
   
85
   QString sql = "SELECT DISTINCT \"" + myFieldName + "\" " +
86
       "FROM (SELECT \"" + myFieldName + "\" " +
87
@@ -268,7 +266,7 @@
88
     QString numRows;
89
     QString sql = "select count(*) from " + mUri->quotedTablename() 
90
       + " where " + txtSQL->text();
91
-    PGresult *result = PQexec(mPgConnection, (const char *)(sql.utf8()));
92
+    PGresult *result = PQexec(mPgConnection, sql.toUtf8());
93
     if (PQresultStatus(result) == PGRES_TUPLES_OK) 
94
     {
95
       numRows = QString::fromUtf8(PQgetvalue(result, 0, 0));
96
@@ -280,7 +278,7 @@
97
     {
98
       QMessageBox::warning(this, tr("Query Failed"), 
99
           tr("An error occurred when executing the query:") 
100
-          + "\n" + QString(PQresultErrorMessage(result)));
101
+          + "\n" + QString::fromUtf8(PQresultErrorMessage(result)));
102
     }
103
     // free the result set
104
     PQclear(result);
105
@@ -294,7 +292,7 @@
106
   QString sql = "select count(*) from " + mUri->quotedTablename() + " where " + where;
107
 
108
   long numRows;
109
-  PGresult *result = PQexec(mPgConnection, (const char *)(sql.utf8()));
110
+  PGresult *result = PQexec(mPgConnection, sql.toUtf8());
111
   if (PQresultStatus(result) == PGRES_TUPLES_OK) 
112
   {
113
     QString rowCount = QString::fromUtf8(PQgetvalue(result, 0, 0));
114
@@ -303,7 +301,7 @@
115
   else
116
   {
117
     numRows = -1;
118
-    mPgErrorMessage = PQresultErrorMessage(result);
119
+    mPgErrorMessage = QString::fromUtf8(PQresultErrorMessage(result));
120
 
121
   }
122
   // free the result set
123
Index: src/app/qgsnewconnection.cpp
124
===================================================================
125
--- src/app/qgsnewconnection.cpp	(revision 8182)
126
+++ src/app/qgsnewconnection.cpp	(working copy)
127
@@ -130,7 +130,14 @@
128
   settings.writeEntry(baseKey + "/database", txtDatabase->text());
129
   settings.writeEntry(baseKey + "/port", txtPort->text());
130
   settings.writeEntry(baseKey + "/username", txtUsername->text());
131
-  settings.writeEntry(baseKey + "/password", txtPassword->text());
132
+  if (chkStorePassword->isChecked())
133
+  {
134
+    settings.writeEntry(baseKey + "/password", txtPassword->text());
135
+  }
136
+  else
137
+  {
138
+    settings.writeEntry(baseKey + "/password", "");
139
+  }
140
   settings.writeEntry(baseKey + "/publicOnly", cb_publicSchemaOnly->isChecked());
141
   settings.writeEntry(baseKey + "/geometryColumnsOnly", cb_geometryColumnsOnly->isChecked());
142
   if (chkStorePassword->isChecked())
143
Index: src/app/qgsdbsourceselect.cpp
144
===================================================================
145
--- src/app/qgsdbsourceselect.cpp	(revision 8182)
146
+++ src/app/qgsdbsourceselect.cpp	(working copy)
147
@@ -181,7 +181,7 @@
148
 		  " when geometrytype(%1) IN ('LINESTRING','MULTILINESTRING') THEN 'LINESTRING'"
149
 		  " when geometrytype(%1) IN ('POLYGON','MULTIPOLYGON') THEN 'POLYGON'"
150
 		  " end "
151
-		  "from \"%2\".\"%3\"").arg(column).arg(schema).arg(table);
152
+		  "from \"%2\".\"%3\"").arg("\""+column+"\"").arg(schema).arg(table);
153
 }
154
 
155
 QgsDbSourceSelect::~QgsDbSourceSelect()
156
@@ -361,11 +361,11 @@
157
   QString username = settings.readEntry(key + "/username");
158
   QString password = settings.readEntry(key + "/password");
159
 
160
-  if (password == QString::null)
161
+  if ( password.isEmpty() )
162
   {
163
     // get password from user 
164
     makeConnection = false;
165
-    QString password = QInputDialog::getText(tr("Password for ") + username,
166
+    password = QInputDialog::getText(tr("Password for ") + username,
167
         tr("Please enter your password:"),
168
         QLineEdit::Password, QString::null, &makeConnection, this);
169
     // allow null password entry in case its valid for the database
170
@@ -393,13 +393,13 @@
171
     if (pd != 0)
172
       PQfinish(pd);
173
 
174
-    pd = PQconnectdb(m_connInfo.toLocal8Bit().data());
175
+    pd = PQconnectdb(m_connInfo.toLocal8Bit());		// use what is set based on locale; after connecting, use Utf8
176
     //  std::cout << pd->ErrorMessage();
177
     if (PQstatus(pd) == CONNECTION_OK)
178
     {
179
       //qDebug("Connection succeeded");
180
       // tell the DB that we want text encoded in UTF8
181
-      PQsetClientEncoding(pd, "UNICODE");
182
+      PQsetClientEncoding(pd, QString("UNICODE").toLocal8Bit());
183
 
184
       // get the list of suitable tables and columns and populate the UI
185
       geomCol details;
186
@@ -434,7 +434,7 @@
187
       QMessageBox::warning(this, tr("Connection failed"),
188
           tr
189
           ("Connection to %1 on %2 failed. Either the database is down or your settings are incorrect.%3Check your username and password and try again.%4The database said:%5%6").
190
-          arg(settings.readEntry(key + "/database")).arg(settings.readEntry(key + "/host")).arg("\n\n").arg("\n\n").arg("\n").arg(PQerrorMessage(pd)));
191
+          arg(settings.readEntry(key + "/database")).arg(settings.readEntry(key + "/host")).arg("\n\n").arg("\n\n").arg("\n").arg(QString::fromLocal8Bit(PQerrorMessage(pd))));
192
     }
193
   }
194
 
195
@@ -526,43 +526,33 @@
196
   bool ok = false;
197
   QApplication::setOverrideCursor(Qt::waitCursor);
198
   
199
-  QString sql = "select * from geometry_columns";
200
-  sql += " order by f_table_schema,f_table_name";
201
+    // The following query returns only tables that exist and the user has SELECT privilege on.
202
+    // Can't use regclass here because table must exist, else error occurs.
203
+    QString sql = "select * from geometry_columns,pg_class,pg_namespace "
204
+      "where relname=f_table_name and f_table_schema=nspname "
205
+      "and pg_namespace.oid = pg_class.relnamespace "
206
+      "and has_table_privilege('\"'||pg_namespace.nspname||'\".\"'||pg_class.relname||'\"','select')"	// user has select privilege
207
+      "order by f_table_schema,f_table_name";
208
 
209
-  PGresult *result = PQexec(pg, sql.toLocal8Bit().data());
210
+  PGresult *result = PQexec(pg, sql.toUtf8());
211
   if (result)
212
   {
213
     for (int idx = 0; idx < PQntuples(result); idx++)
214
     {
215
-      // Be a bit paranoid and check that the table actually
216
-      // exists. This is not done as a subquery in the query above
217
-      // because I can't get it to work correctly when there are tables
218
-      // with capital letters in the name.
219
+      QString tableName = QString::fromUtf8(PQgetvalue(result, idx, PQfnumber(result, QString("f_table_name").toUtf8())));
220
+      QString schemaName = QString::fromUtf8(PQgetvalue(result, idx, PQfnumber(result, QString("f_table_schema").toUtf8())));
221
 
222
-      // Take care to deal with tables with the same name but in different schema.
223
-      QString tableName = PQgetvalue(result, idx, PQfnumber(result, "f_table_name"));
224
-      QString schemaName = PQgetvalue(result, idx, PQfnumber(result, "f_table_schema"));
225
-      sql = "select oid from pg_class where relname = '" + tableName + "'";
226
-      if (schemaName.length() > 0)
227
-	sql +=" and relnamespace = (select oid from pg_namespace where nspname = '" +
228
-	  schemaName + "')";
229
+      QString column = QString::fromUtf8(PQgetvalue(result, idx, PQfnumber(result, QString("f_geometry_column").toUtf8())));
230
+      QString type = QString::fromUtf8(PQgetvalue(result, idx, PQfnumber(result, QString("type").toUtf8())));
231
 
232
-      PGresult* exists = PQexec(pg, sql.toLocal8Bit().data());
233
-      if (PQntuples(exists) == 1)
234
+      QString as = "";
235
+      if(type=="GEOMETRY" && !searchGeometryColumnsOnly) 
236
       {
237
-        QString column = PQgetvalue(result, idx, PQfnumber(result, "f_geometry_column"));
238
-        QString type = PQgetvalue(result, idx, PQfnumber(result, "type"));
239
-        
240
-	QString as = "";
241
-	if(type=="GEOMETRY" && !searchGeometryColumnsOnly) 
242
-	  {
243
-	    addSearchGeometryColumn(schemaName, tableName,  column);
244
-	    as=type="WAITING";
245
-	  }
246
-
247
-	mTableModel.addTableEntry(type, schemaName, tableName, column, "");
248
+        addSearchGeometryColumn(schemaName, tableName,  column);
249
+        as=type="WAITING";
250
       }
251
-      PQclear(exists);
252
+
253
+      mTableModel.addTableEntry(type, schemaName, tableName, column, "");
254
     }
255
     ok = true;
256
   }
257
@@ -581,20 +571,21 @@
258
   // geometry_columns table. This code is specific to postgresql,
259
   // but an equivalent query should be possible in other
260
   // databases.
261
-  sql = "select pg_class.relname, pg_namespace.nspname, pg_attribute.attname, "
262
-    "pg_class.relkind from "
263
-    "pg_attribute, pg_class, pg_type, pg_namespace where pg_type.typname = 'geometry' and "
264
-    "pg_attribute.atttypid = pg_type.oid and pg_attribute.attrelid = pg_class.oid ";
265
-
266
+  sql = "select pg_class.relname, pg_namespace.nspname, pg_attribute.attname,  pg_class.relkind "
267
+    "from pg_attribute, pg_class, pg_namespace "
268
+    "where pg_namespace.oid = pg_class.relnamespace "
269
+    "and pg_attribute.atttypid = regtype('geometry') "
270
+    "and pg_attribute.attrelid = pg_class.oid "
271
+    "and has_table_privilege('\"'||pg_namespace.nspname||'\".\"'||pg_class.relname||'\"','select') ";
272
+	// user has select privilege
273
   if (searchPublicOnly)
274
     sql += "and pg_namespace.nspname = 'public' ";
275
 
276
-  sql += "and cast(pg_class.relname as character varying) not in "
277
-    "(select f_table_name from geometry_columns) "
278
-    "and pg_namespace.oid = pg_class.relnamespace "
279
+  sql += "and pg_namespace.nspname||'.'||pg_class.relname not in "	//  needs to be table and schema
280
+    "(select f_table_schema||'.'||f_table_name from geometry_columns) "
281
     "and pg_class.relkind in ('v', 'r')"; // only from views and relations (tables)
282
   
283
-  result = PQexec(pg, sql.toLocal8Bit().data());
284
+  result = PQexec(pg, sql.toUtf8());
285
 
286
   for (int i = 0; i < PQntuples(result); i++)
287
   {
288
@@ -605,10 +596,10 @@
289
     // Make the assumption that the geometry type for the first
290
     // row is the same as for all other rows. 
291
 
292
-    QString table  = PQgetvalue(result, i, 0); // relname
293
-    QString schema = PQgetvalue(result, i, 1); // nspname
294
-    QString column = PQgetvalue(result, i, 2); // attname
295
-    QString relkind = PQgetvalue(result, i, 3); // relation kind
296
+    QString table  = QString::fromUtf8(PQgetvalue(result, i, 0)); // relname
297
+    QString schema = QString::fromUtf8(PQgetvalue(result, i, 1)); // nspname
298
+    QString column = QString::fromUtf8(PQgetvalue(result, i, 2)); // attname
299
+    QString relkind = QString::fromUtf8(PQgetvalue(result, i, 3)); // relation kind
300
 
301
     addSearchGeometryColumn(schema, table, column);
302
     //details.push_back(geomPair(fullDescription(schema, table, column, "WAITING"), "WAITING"));
303
@@ -620,6 +611,7 @@
304
   return ok;
305
 }
306
 
307
+#if 0	// this function is never called - smizuno
308
 bool QgsDbSourceSelect::getGeometryColumnInfo(PGconn *pg, 
309
                 geomCol& details, bool searchGeometryColumnsOnly,
310
                                               bool searchPublicOnly)
311
@@ -632,7 +624,7 @@
312
   // where f_table_schema ='" + settings.readEntry(key + "/database") + "'";
313
   sql += " order by f_table_schema,f_table_name";
314
   //qDebug("Fetching tables using: " + sql);
315
-  PGresult *result = PQexec(pg, sql.toLocal8Bit().data());
316
+  PGresult *result = PQexec(pg, sql.toUtf8());
317
   if (result)
318
   {
319
     QString msg;
320
@@ -646,18 +638,18 @@
321
       // with capital letters in the name.
322
 
323
       // Take care to deal with tables with the same name but in different schema.
324
-      QString tableName = PQgetvalue(result, idx, PQfnumber(result, "f_table_name"));
325
-      QString schemaName = PQgetvalue(result, idx, PQfnumber(result, "f_table_schema"));
326
+      QString tableName = QString::fromUtf8(PQgetvalue(result, idx, PQfnumber(result, "f_table_name")));
327
+      QString schemaName = QString::fromUtf8(PQgetvalue(result, idx, PQfnumber(result, "f_table_schema")));
328
       sql = "select oid from pg_class where relname = '" + tableName + "'";
329
       if (schemaName.length() > 0)
330
 	sql +=" and relnamespace = (select oid from pg_namespace where nspname = '" +
331
 	  schemaName + "')";
332
 
333
-      PGresult* exists = PQexec(pg, sql.toLocal8Bit().data());
334
+      PGresult* exists = PQexec(pg, sql.toUtf8());
335
       if (PQntuples(exists) == 1)
336
       {
337
-        QString column = PQgetvalue(result, idx, PQfnumber(result, "f_geometry_column"));
338
-        QString type = PQgetvalue(result, idx, PQfnumber(result, "type"));
339
+        QString column = QString::fromUtf8(PQgetvalue(result, idx, PQfnumber(result, "f_geometry_column")));
340
+        QString type = QString::fromUtf8(PQgetvalue(result, idx, PQfnumber(result, "type")));
341
         
342
 	QString as = "";
343
 	if(type=="GEOMETRY" && !searchGeometryColumnsOnly) {
344
@@ -695,7 +687,7 @@
345
     "and pg_namespace.oid = pg_class.relnamespace "
346
     "and pg_class.relkind in ('v', 'r')"; // only from views and relations (tables)
347
   
348
-  result = PQexec(pg, sql.toLocal8Bit().data());
349
+  result = PQexec(pg, sql.toUtf8());
350
 
351
   for (int i = 0; i < PQntuples(result); i++)
352
   {
353
@@ -706,10 +698,10 @@
354
     // Make the assumption that the geometry type for the first
355
     // row is the same as for all other rows. 
356
 
357
-    QString table  = PQgetvalue(result, i, 0); // relname
358
-    QString schema = PQgetvalue(result, i, 1); // nspname
359
-    QString column = PQgetvalue(result, i, 2); // attname
360
-    QString relkind = PQgetvalue(result, i, 3); // relation kind
361
+    QString table  = QString::fromUtf8(PQgetvalue(result, i, 0)); // relname
362
+    QString schema = QString::fromUtf8(PQgetvalue(result, i, 1)); // nspname
363
+    QString column = QString::fromUtf8(PQgetvalue(result, i, 2)); // attname
364
+    QString relkind = QString::fromUtf8(PQgetvalue(result, i, 3)); // relation kind
365
 
366
     addSearchGeometryColumn(schema, table, column);
367
     details.push_back(geomPair(fullDescription(schema, table, column, "WAITING"), "WAITING"));
368
@@ -720,6 +712,7 @@
369
 
370
   return ok;
371
 }
372
+#endif
373
 
374
 void QgsDbSourceSelect::showHelp()
375
 {
376
@@ -800,23 +793,23 @@
377
 {
378
   mStopped=false;
379
 
380
-  PGconn *pd = PQconnectdb(mConnInfo.toLocal8Bit().data());
381
+  PGconn *pd = PQconnectdb(mConnInfo.toLocal8Bit());
382
   if (PQstatus(pd) == CONNECTION_OK)
383
   {
384
-    PQsetClientEncoding(pd, "UNICODE");
385
+    PQsetClientEncoding(pd, QString("UNICODE").toLocal8Bit());
386
 
387
     for (uint i = 0; i<schemas.size(); i++)
388
     {
389
       QString query = QgsDbSourceSelect::makeGeomQuery(schemas[i],
390
                                                        tables[i],
391
                                                        columns[i]);
392
-      PGresult* gresult = PQexec(pd, query.toLocal8Bit().data());
393
+      PGresult* gresult = PQexec(pd, query.toUtf8());
394
       QString type;
395
       if (PQresultStatus(gresult) == PGRES_TUPLES_OK) {
396
 	QStringList types;
397
 
398
 	for(int j=0; j<PQntuples(gresult); j++) {
399
-		QString type = PQgetvalue(gresult, j, 0);
400
+		QString type = QString::fromUtf8(PQgetvalue(gresult, j, 0));
401
 		if(type!="")
402
 		  types += type;
403
 	}
404
Index: src/core/qgsdatasourceuri.cpp
405
===================================================================
406
--- src/core/qgsdatasourceuri.cpp	(revision 8182)
407
+++ src/core/qgsdatasourceuri.cpp	(working copy)
408
@@ -223,7 +223,7 @@
409
 
410
 QString QgsDataSourceURI::connInfo() const
411
 {
412
-  QString connInfo = "dbname="+mDatabase;
413
+  QString connInfo = "dbname='"+mDatabase+"'";
414
 
415
   if( mHost != "" )
416
   {
417
@@ -234,7 +234,7 @@
418
 
419
   if( mUsername != "" )
420
   {
421
-    connInfo += " user=" + mUsername;
422
+    connInfo += " user='" + mUsername + "'";	//needs to be escaped
423
 
424
     if( mPassword != "" )
425
     {
426
Index: src/providers/postgres/qgspostgresprovider.h
427
===================================================================
428
--- src/providers/postgres/qgspostgresprovider.h	(revision 8182)
429
+++ src/providers/postgres/qgspostgresprovider.h	(working copy)
430
@@ -327,6 +327,11 @@
431
     void repaintRequested();
432
 
433
   private:
434
+
435
+    /** Double quote a PostgreSQL identifier for placement in a SQL string.
436
+     */
437
+    QString quoteIdentifier( const QString &ident );
438
+
439
     /** Load the field list
440
     */
441
     void loadFields();
442
@@ -562,7 +567,7 @@
443
     	PGconn *conn;
444
     };
445
 
446
-    PGconn *connectDb(const char *conninfo);
447
+    PGconn *connectDb(const QString /*const char **/& conninfo);
448
     void disconnectDb();
449
 
450
     static QMap<QString, Conn *> connections;
451
Index: src/providers/postgres/qgspostgresprovider.cpp
452
===================================================================
453
--- src/providers/postgres/qgspostgresprovider.cpp	(revision 8182)
454
+++ src/providers/postgres/qgspostgresprovider.cpp	(working copy)
455
@@ -103,7 +103,7 @@
456
   //pLog.open((const char *)logFile);
457
   //QgsDebugMsg("Opened log file for " + mTableName);
458
 
459
-  connection = connectDb( (const char *)mUri.connInfo() );
460
+  connection = connectDb( mUri.connInfo() );
461
   if( connection==NULL ) {
462
     valid = false;
463
     return;
464
@@ -114,13 +114,13 @@
465
   // Check that we can read from the table (i.e., we have
466
   // select permission).
467
   QString sql = "select * from " + mSchemaTableName + " limit 1";
468
-  PGresult* testAccess = PQexec(connection, (const char*)(sql.utf8()));
469
+  PGresult* testAccess = PQexec(connection, sql.toUtf8());
470
   if (PQresultStatus(testAccess) != PGRES_TUPLES_OK)
471
   {
472
     showMessageBox(tr("Unable to access relation"),
473
         tr("Unable to access the ") + mSchemaTableName + 
474
         tr(" relation.\nThe error message from the database was:\n") +
475
-        QString(PQresultErrorMessage(testAccess)) + ".\n" + 
476
+        QString::fromUtf8(PQresultErrorMessage(testAccess)) + ".\n" + 
477
         "SQL: " + sql);
478
     PQclear(testAccess);
479
     valid = false;
480
@@ -129,10 +129,10 @@
481
   }
482
   PQclear(testAccess);
483
 
484
-  PGresult *schema = PQexec(connection, "SELECT current_schema()");
485
+  PGresult *schema = PQexec(connection, QString("SELECT current_schema()").toUtf8());
486
   if (PQresultStatus(schema) == PGRES_TUPLES_OK)
487
   {
488
-    mCurrentSchema = PQgetvalue(schema, 0, 0);
489
+    mCurrentSchema = QString::fromUtf8(PQgetvalue(schema, 0, 0));
490
     if(mCurrentSchema==mSchemaName) {
491
       mUri.clearSchema();
492
       setDataSourceUri( mUri.uri() );
493
@@ -167,7 +167,7 @@
494
   // Set the postgresql message level so that we don't get the
495
   // 'there is no transaction in progress' warning.
496
 #ifndef QGISDEBUG
497
-  PQexec(connection, "set client_min_messages to error");
498
+  PQexec(connection, QString("set client_min_messages to error").toUtf8());
499
 #endif
500
 
501
   // Kick off the long running threads
502
@@ -241,7 +241,7 @@
503
   //pLog.flush();
504
 }
505
 
506
-PGconn *QgsPostgresProvider::connectDb(const char *conninfo)
507
+PGconn *QgsPostgresProvider::connectDb(const QString & conninfo)
508
 {
509
   if( connections.contains(conninfo) ) 
510
   {
511
@@ -252,7 +252,7 @@
512
 
513
   QgsDebugMsg(QString("New postgres connection for ") + conninfo);
514
 
515
-  PGconn *pd = PQconnectdb(conninfo);
516
+  PGconn *pd = PQconnectdb(conninfo.toLocal8Bit());	// use what is set based on locale; after connecting, use Utf8
517
   // check the connection status
518
   if (PQstatus(pd) != CONNECTION_OK) 
519
   {
520
@@ -263,7 +263,7 @@
521
   //set client encoding to unicode because QString uses UTF-8 anyway
522
   QgsDebugMsg("setting client encoding to UNICODE");
523
 
524
-  int errcode=PQsetClientEncoding(pd, "UNICODE");
525
+  int errcode=PQsetClientEncoding(pd, QString("UNICODE").toLocal8Bit());
526
 
527
   if(errcode==0) 
528
   {
529
@@ -338,7 +338,7 @@
530
 
531
       if(mFirstFetch)
532
       {
533
-        if(PQsendQuery(connection, (const char *)fetch) == 0) //fetch features in asynchronously
534
+        if(PQsendQuery(connection, fetch.toUtf8()) == 0) //fetch features in asynchronously
535
         {
536
           qWarning("PQsendQuery failed (1)");
537
         }
538
@@ -353,15 +353,16 @@
539
       {
540
         QgsDebugMsg("End of features");
541
 
542
+        PQclear(queryResult);
543
         if (ready)
544
-          PQexec(connection, "end work");
545
+          PQexec(connection, QString("end work").toUtf8());
546
         ready = false;
547
         return false;
548
       }
549
 
550
       for (int row = 0; row < rows; row++)
551
       {
552
-        int oid = *(int *)PQgetvalue(queryResult, row, PQfnumber(queryResult,"\""+primaryKey+"\""));
553
+        int oid = *(int *)PQgetvalue(queryResult, row, PQfnumber(queryResult,quoteIdentifier(primaryKey).toUtf8()));
554
 
555
         if (swapEndian)
556
           oid = ntohl(oid); // convert oid to opposite endian
557
@@ -383,12 +384,14 @@
558
           }
559
           else
560
           {
561
-            char* attribute = PQgetvalue(queryResult, row, PQfnumber(queryResult,"\""+*name_it+"\""));
562
-            val = QString::fromUtf8(attribute);
563
+            val = QString::fromUtf8(PQgetvalue(queryResult, row, PQfnumber(queryResult,quoteIdentifier(*name_it).toUtf8())));
564
           }
565
 
566
           switch (attributeFields[*index_it].type())
567
           {
568
+            case QVariant::LongLong:
569
+              mFeatureQueue.back().addAttribute(*index_it, val.toLongLong());
570
+              break;
571
             case QVariant::Int:
572
               mFeatureQueue.back().addAttribute(*index_it, val.toInt());
573
               break;
574
@@ -411,7 +414,7 @@
575
           {
576
             unsigned char *featureGeom = new unsigned char[returnedLength + 1];
577
             memset(featureGeom, '\0', returnedLength + 1);
578
-            memcpy(featureGeom, PQgetvalue(queryResult, row, PQfnumber(queryResult,"qgs_feature_geometry")), returnedLength); 
579
+            memcpy(featureGeom, PQgetvalue(queryResult, row, PQfnumber(queryResult,QString("qgs_feature_geometry").toUtf8())), returnedLength); 
580
             mFeatureQueue.back().setGeometryAndOwnership(featureGeom, returnedLength + 1);
581
           }
582
           else
583
@@ -424,7 +427,7 @@
584
 
585
       PQclear(queryResult);
586
 
587
-      if(PQsendQuery(connection, (const char *)fetch) == 0) //already fetch the next couple of features asynchronously
588
+      if(PQsendQuery(connection, fetch.toUtf8()) == 0) //already fetch the next couple of features asynchronously
589
       {
590
         qWarning("PQsendQuery failed (2)");
591
       }
592
@@ -477,17 +480,17 @@
593
     }
594
   }
595
 
596
-  QString declare = "declare qgisf" + providerId + " binary cursor for select \"" + primaryKey + "\"";
597
+  QString declare = "declare qgisf" + providerId + " binary cursor for select " + quoteIdentifier(primaryKey);
598
 
599
   if(fetchGeometry)
600
   {
601
-    declare += QString(",asbinary(\"%1\",'%2') as qgs_feature_geometry").arg(geometryColumn).arg(endianString()); 
602
+    declare += QString(",asbinary(%1,'%2') as qgs_feature_geometry").arg(quoteIdentifier(geometryColumn)).arg(endianString()); 
603
   }
604
   for(std::list<QString>::const_iterator it = mFetchAttributeNames.begin(); it != mFetchAttributeNames.end(); ++it)
605
   {
606
     if( (*it) != primaryKey) //no need to fetch primary key again
607
     {
608
-      declare += ",\"" + *it + "\"::text";
609
+      declare += "," + quoteIdentifier(*it) + "::text";
610
     }
611
   }
612
 
613
@@ -504,12 +507,12 @@
614
     { 
615
       // Contributed by #qgis irc "creeping"
616
       // This version actually invokes PostGIS's use of spatial indexes
617
-      declare += " where " + geometryColumn;
618
+      declare += " where " + quoteIdentifier(geometryColumn);
619
       declare += " && setsrid('BOX3D(" + rect.asWKTCoords();
620
       declare += ")'::box3d,";
621
       declare += srid;
622
       declare += ")";
623
-      declare += " and intersects(" + geometryColumn;
624
+      declare += " and intersects(" + quoteIdentifier(geometryColumn);
625
       declare += ", setsrid('BOX3D(" + rect.asWKTCoords();
626
       declare += ")'::box3d,";
627
       declare += srid;
628
@@ -517,7 +520,7 @@
629
     }
630
     else
631
     {
632
-      declare += " where " + geometryColumn;
633
+      declare += " where " + quoteIdentifier(geometryColumn);
634
       declare += " && setsrid('BOX3D(" + rect.asWKTCoords();
635
       declare += ")'::box3d,";
636
       declare += srid;
637
@@ -540,11 +543,11 @@
638
 
639
   // set up the cursor
640
   if(ready){
641
-    PQexec(connection, "end work");
642
+    PQexec(connection, QString("end work").toUtf8());
643
   }
644
-  PQexec(connection,"begin work");
645
+  PQexec(connection,QString("begin work").toUtf8());
646
   ready = true;
647
-  PQexec(connection, (const char *)(declare.utf8()));
648
+  PQexec(connection, declare.toUtf8());
649
 
650
   while(!mFeatureQueue.empty())
651
     {
652
@@ -558,7 +561,6 @@
653
     bool fetchGeometry,
654
     QgsAttributeList fetchAttributes)
655
 {
656
-
657
   std::list<QString> attributeNames;
658
   QgsFieldMap fldMap = fields();
659
   QgsFieldMap::const_iterator fieldIt;
660
@@ -574,43 +576,44 @@
661
     }
662
   }
663
 
664
-  QString sql = "declare qgisfid" + providerId + " binary cursor for select \"" + primaryKey + "\"";
665
+  QString sql = "declare qgisfid" + providerId + " binary cursor for select " + quoteIdentifier(primaryKey);
666
 
667
   if(fetchGeometry)
668
   {
669
-    sql += QString(",asbinary(\"%1\",'%2') as qgs_feature_geometry").arg(geometryColumn).arg(endianString()); 
670
+    sql += QString(",asbinary(%1,'%2') as qgs_feature_geometry").arg(quoteIdentifier(geometryColumn)).arg(endianString()); 
671
   }
672
   for(namesIt = attributeNames.begin(); namesIt != attributeNames.end(); ++namesIt)
673
   {
674
     if( (*namesIt) != primaryKey) //no need to fetch primary key again
675
     {
676
-      sql += ",\"" + *namesIt + "\"::text";
677
+      sql += "," + quoteIdentifier(*namesIt) + "::text";
678
     }
679
   }
680
 
681
   sql += " " + QString("from %1").arg(mSchemaTableName);
682
 
683
-  sql += " where " + primaryKey + " = " + QString::number(featureId);
684
+  sql += " where " + quoteIdentifier(primaryKey) + " = " + QString::number(featureId);
685
 
686
   QgsDebugMsg("Selecting feature using: " + sql);
687
 
688
-  PQexec(connection,"begin work");
689
+  PQexec(connection,QString("begin work").toUtf8());
690
 
691
   // execute query
692
-  PQexec(connection, (const char *)(sql.utf8()));
693
+  PQexec(connection, sql.toUtf8());
694
 
695
-  PGresult *res = PQexec(connection, "fetch forward 1 from qgisfid" + providerId);
696
+  PGresult *res = PQexec(connection, ("fetch forward 1 from qgisfid" + providerId).toUtf8());
697
 
698
   int rows = PQntuples(res);
699
   if (rows == 0)
700
   {
701
-    PQexec(connection, "end work");
702
+    PQclear(res);
703
+    PQexec(connection, QString("end work").toUtf8());
704
     QgsDebugMsg("feature " + QString::number(featureId) + " not found");
705
     return FALSE;
706
   }
707
 
708
   // set ID
709
-  int oid = *(int *)PQgetvalue(res, 0, PQfnumber(res,"\""+primaryKey+"\""));
710
+  int oid = *(int *)PQgetvalue(res, 0, PQfnumber(res,quoteIdentifier(primaryKey).toUtf8()));
711
   if (swapEndian)
712
     oid = ntohl(oid); // convert oid to opposite endian
713
   feature.setFeatureId(oid);
714
@@ -627,12 +630,14 @@
715
     }
716
     else
717
     {
718
-      char* attribute = PQgetvalue(res, 0, PQfnumber(res,*namesIt));
719
-      val = QString::fromUtf8(attribute);
720
+      val = QString::fromUtf8(PQgetvalue(res, 0, PQfnumber(res,quoteIdentifier(*namesIt).toUtf8())));
721
     }
722
 
723
     switch (attributeFields[*it].type())
724
     {
725
+      case QVariant::LongLong:
726
+        feature.addAttribute(*it, val.toLongLong());
727
+        break;
728
       case QVariant::Int:
729
         feature.addAttribute(*it, val.toInt());
730
         break;
731
@@ -655,12 +660,13 @@
732
     {
733
       unsigned char *featureGeom = new unsigned char[returnedLength + 1];
734
       memset(featureGeom, '\0', returnedLength + 1);
735
-      memcpy(featureGeom, PQgetvalue(res, 0, PQfnumber(res,"qgs_feature_geometry")), returnedLength); 
736
+      memcpy(featureGeom, PQgetvalue(res, 0, PQfnumber(res,QString("qgs_feature_geometry").toUtf8())), returnedLength); 
737
       feature.setGeometryAndOwnership(featureGeom, returnedLength + 1);
738
     }
739
   }
740
 
741
-  PQexec(connection, "end work");
742
+  PQclear(res);
743
+  PQexec(connection, QString("end work").toUtf8());
744
 
745
   return TRUE;
746
 }
747
@@ -721,7 +727,7 @@
748
 void QgsPostgresProvider::reset()
749
 {
750
   QString move = "move 0 in qgisf" + providerId; //move cursor to first record
751
-  PQexec(connection, (const char *)(move.utf8()));
752
+  PQexec(connection, move.toUtf8());
753
   mFeatureQueue.empty();
754
   loadFields();
755
 }
756
@@ -747,25 +753,24 @@
757
   QgsDebugMsg("Loading fields for table " + mTableName);
758
 
759
   // Get the relation oid for use in later queries
760
-  QString sql = "SELECT oid FROM pg_class WHERE relname = '" + mTableName + "' AND relnamespace = ("
761
-    "SELECT oid FROM pg_namespace WHERE nspname = '" + mSchemaName + "')";
762
-  PGresult *tresult= PQexec(connection, (const char *)(sql.utf8()));
763
-  QString tableoid = PQgetvalue(tresult, 0, 0);
764
+  QString sql = "SELECT regclass('" + mSchemaTableName + "')::oid";
765
+  PGresult *tresult= PQexec(connection, sql.toUtf8());
766
+  QString tableoid = QString::fromUtf8(PQgetvalue(tresult, 0, 0));
767
   PQclear(tresult);
768
 
769
   // Get the table description
770
   sql = "SELECT description FROM pg_description WHERE "
771
     "objoid = " + tableoid + " AND objsubid = 0";
772
-  tresult = PQexec(connection, (const char*) sql.utf8());
773
+  tresult = PQexec(connection, sql.toUtf8());
774
   if (PQntuples(tresult) > 0)
775
-    mDataComment = PQgetvalue(tresult, 0, 0);
776
+    mDataComment = QString::fromUtf8(PQgetvalue(tresult, 0, 0));
777
   PQclear(tresult);
778
 
779
   // Populate the field vector for this layer. The field vector contains
780
   // field name, type, length, and precision (if numeric)
781
   sql = "select * from " + mSchemaTableName + " limit 0";
782
 
783
-  PGresult *result = PQexec(connection, (const char *) (sql.utf8()));
784
+  PGresult *result = PQexec(connection, sql.toUtf8());
785
   //--std::cout << "Field: Name, Type, Size, Modifier:" << std::endl;
786
 
787
   // The queries inside this loop could possibly be combined into one
788
@@ -773,32 +778,33 @@
789
 
790
   for (int i = 0; i < PQnfields(result); i++)
791
   {
792
-    QString fieldName = PQfname(result, i);
793
+    QString fieldName = QString::fromUtf8(PQfname(result, i));
794
     int fldtyp = PQftype(result, i);
795
     QString typOid = QString().setNum(fldtyp);
796
     int fieldModifier = PQfmod(result, i);
797
     QString fieldComment("");
798
 
799
-    sql = "SELECT typname, typlen FROM pg_type WHERE "
800
-      "oid = (SELECT typelem FROM pg_type WHERE "
801
-      "typelem = " + typOid + " AND typlen = -1)";
802
+    sql = "SELECT typname, typlen FROM pg_type WHERE " 
803
+      "oid="+typOid;	// just oid; needs more work to support array type
804
+//      "oid = (SELECT Distinct typelem FROM pg_type WHERE "	//needs DISTINCT to guard against 2 or more rows on int2
805
+//      "typelem = " + typOid + " AND typlen = -1)";
806
 
807
-    PGresult* oidResult = PQexec(connection, (const char *) sql);
808
-    QString fieldTypeName = PQgetvalue(oidResult, 0, 0);
809
-    QString fieldSize = PQgetvalue(oidResult, 0, 1);
810
+    PGresult* oidResult = PQexec(connection, sql.toUtf8());
811
+    QString fieldTypeName = QString::fromUtf8(PQgetvalue(oidResult, 0, 0));
812
+    QString fieldSize = QString::fromUtf8(PQgetvalue(oidResult, 0, 1));
813
     PQclear(oidResult);
814
 
815
     sql = "SELECT attnum FROM pg_attribute WHERE "
816
       "attrelid = " + tableoid + " AND attname = '" + fieldName + "'";
817
-    PGresult *tresult = PQexec(connection, (const char *)(sql.utf8()));
818
-    QString attnum = PQgetvalue(tresult, 0, 0);
819
+    PGresult *tresult = PQexec(connection, sql.toUtf8());
820
+    QString attnum = QString::fromUtf8(PQgetvalue(tresult, 0, 0));
821
     PQclear(tresult);
822
 
823
     sql = "SELECT description FROM pg_description WHERE "
824
       "objoid = " + tableoid + " AND objsubid = " + attnum;
825
-    tresult = PQexec(connection, (const char*)(sql.utf8()));
826
+    tresult = PQexec(connection, sql.toUtf8());
827
     if (PQntuples(tresult) > 0)
828
-      fieldComment = PQgetvalue(tresult, 0, 0);
829
+      fieldComment = QString::fromUtf8(PQgetvalue(tresult, 0, 0));
830
     PQclear(tresult);
831
 
832
     QgsDebugMsg("Field: " + attnum + " maps to " + QString::number(i) + " " + fieldName + ", " 
833
@@ -807,7 +813,9 @@
834
     if(fieldName!=geometryColumn)
835
     {
836
       QVariant::Type fieldType;
837
-      if (fieldTypeName.find("int") != -1 || fieldTypeName.find("serial") != -1)
838
+      if (fieldTypeName.find("int8") != -1)
839
+        fieldType = QVariant::LongLong;
840
+      else if (fieldTypeName.find("int") != -1 || fieldTypeName.find("serial") != -1)
841
         fieldType = QVariant::Int;
842
       else if (fieldTypeName == "real" || fieldTypeName == "double precision" || \
843
           fieldTypeName.find("float") != -1)
844
@@ -826,10 +834,8 @@
845
   // can be used as a key into the table. Primary keys are always
846
   // unique indices, so we catch them as well.
847
 
848
-  QString sql = "select indkey from pg_index where indisunique = 't' and "
849
-    "indrelid = (select oid from pg_class where relname = '"
850
-    + mTableName + "' and relnamespace = (select oid from pg_namespace where "
851
-    "nspname = '" + mSchemaName + "'))";
852
+  QString sql ="select indkey from pg_index where indisunique = 't' and "
853
+    "indrelid = regclass('" + mSchemaTableName + "')::oid"
854
 
855
   QgsDebugMsg("Getting unique index using '" + sql + "'");
856
 
857
@@ -849,11 +855,10 @@
858
     // If the relation is a view try to find a suitable column to use as
859
     // the primary key.
860
 
861
-    sql = "select relkind from pg_class where relname = '" + mTableName + 
862
-      "' and relnamespace = (select oid from pg_namespace where "
863
-      "nspname = '" + mSchemaName + "')";
864
+    sql = "SELECT relkind FROM pg_class WHERE oid = regclass('" + mSchemaTableName + 
865
+      "')::oid";
866
     PGresult* tableType = executeDbCommand(connection, sql);
867
-    QString type = PQgetvalue(tableType, 0, 0);
868
+    QString type = QString::fromUtf8(PQgetvalue(tableType, 0, 0));
869
     PQclear(tableType);
870
 
871
     primaryKey = "";
872
@@ -864,10 +869,9 @@
873
 
874
       // If there is an oid on the table, use that instead,
875
       // otherwise give up
876
-      sql = "select attname from pg_attribute where attname = 'oid' and "
877
-        "attrelid = (select oid from pg_class where relname = '" +
878
-        mTableName + "' and relnamespace = (select oid from pg_namespace "
879
-        "where nspname = '" + mSchemaName + "'))";
880
+      sql = "SELECT attname FROM pg_attribute WHERE attname = 'oid' AND "
881
+        "attrelid = regclass('" + mSchemaTableName + "')";
882
+
883
       PGresult* oidCheck = executeDbCommand(connection, sql);
884
 
885
       if (PQntuples(oidCheck) != 0)
886
@@ -909,22 +913,20 @@
887
     std::vector<std::pair<QString, QString> > suitableKeyColumns;
888
     for (int i = 0; i < PQntuples(pk); ++i)
889
     {
890
-      QString col = PQgetvalue(pk, i, 0);
891
+      QString col = QString::fromUtf8(PQgetvalue(pk, i, 0));
892
       QStringList columns = QStringList::split(" ", col);
893
       if (columns.count() == 1)
894
       {
895
         // Get the column name and data type
896
         sql = "select attname, pg_type.typname from pg_attribute, pg_type where "
897
           "atttypid = pg_type.oid and attnum = " +
898
-          col + " and attrelid = (select oid from pg_class where " +
899
-          "relname = '" + mTableName + "' and relnamespace = (select oid "
900
-          "from pg_namespace where nspname = '" + mSchemaName + "'))";
901
+          col + " and attrelid = regclass('" + mSchemaTableName + "')";
902
         PGresult* types = executeDbCommand(connection, sql);
903
 
904
         if( PQntuples(types) > 0 )
905
         {
906
-          QString columnName = PQgetvalue(types, 0, 0);
907
-          QString columnType = PQgetvalue(types, 0, 1);
908
+          QString columnName = QString::fromUtf8(PQgetvalue(types, 0, 0));
909
+          QString columnType = QString::fromUtf8(PQgetvalue(types, 0, 1));
910
 
911
           if (columnType != "int4")
912
             log.append(tr("The unique index on column") + 
913
@@ -946,9 +948,7 @@
914
         sql = "select attname from pg_attribute, pg_type where "
915
           "atttypid = pg_type.oid and attnum in (" +
916
           col.replace(" ", ",") 
917
-          + ") and attrelid = (select oid from pg_class where " +
918
-          "relname = '" + mTableName + "' and relnamespace = (select oid "
919
-          "from pg_namespace where nspname = '" + mSchemaName + "'))";
920
+          + ") and attrelid = regclass('" + mSchemaTableName + "')::oid";
921
         PGresult* types = executeDbCommand(connection, sql);
922
         QString colNames;
923
         int numCols = PQntuples(types);
924
@@ -956,7 +956,7 @@
925
         {
926
           if (j == numCols-1)
927
             colNames += tr("and ");
928
-          colNames += "'" + QString(PQgetvalue(types, j, 0)) 
929
+          colNames += "'" + QString::fromUtf8(PQgetvalue(types, j, 0)) 
930
             + (j < numCols-2 ? "', " : "' ");
931
         }
932
 
933
@@ -982,9 +982,7 @@
934
       // If there is an oid on the table, use that instead,
935
       // otherwise give up
936
       sql = "select attname from pg_attribute where attname = 'oid' and "
937
-        "attrelid = (select oid from pg_class where relname = '" +
938
-        mTableName + "' and relnamespace = (select oid from pg_namespace "
939
-        "where nspname = '" + mSchemaName + "'))";
940
+        "attrelid = regclass('" + mSchemaTableName + "')::oid";
941
       PGresult* oidCheck = executeDbCommand(connection, sql);
942
 
943
       if (PQntuples(oidCheck) != 0)
944
@@ -1051,10 +1049,8 @@
945
 
946
     // Get the oid from pg_class for the given schema.relation for use
947
     // in subsequent queries.
948
-    sql = "select oid from pg_class where relname = '" + tableName +
949
-      "' and relnamespace = (select oid from pg_namespace where "
950
-      " nspname = '" + schemaName + "')";
951
-    PGresult* result = PQexec(connection, (const char*)(sql.utf8()));
952
+    sql = "select regclass('" + quoteIdentifier(schemaName) + "." + quoteIdentifier(tableName) + "')::oid";
953
+    PGresult* result = PQexec(connection, sql.toUtf8());
954
     QString rel_oid;
955
     if (PQntuples(result) == 1)
956
     {
957
@@ -1086,7 +1082,7 @@
958
       "and (contype = 'p' or contype = 'u') "
959
       "and array_dims(conkey) = '[1:1]'";
960
 
961
-    result = PQexec(connection, (const char*)(sql.utf8()));
962
+    result = PQexec(connection, sql.toUtf8());
963
     if (PQntuples(result) == 1 && colType == "int4")
964
       suitable[viewCol] = iter->second;
965
 
966
@@ -1145,7 +1141,7 @@
967
     sql = "select * from pg_index where indrelid = " + rel_oid +
968
       " and indkey[0] = (select attnum from pg_attribute where "
969
       "attrelid = " +	rel_oid + " and attname = '" + i->second.column + "')";
970
-    PGresult* result = PQexec(connection, (const char*)(sql.utf8()));
971
+    PGresult* result = PQexec(connection, sql.toUtf8());
972
 
973
     if (PQntuples(result) > 0 && uniqueData(mSchemaName, mTableName, i->first))
974
     { // Got one. Use it.
975
@@ -1226,13 +1222,13 @@
976
 
977
   bool isUnique = false;
978
 
979
-  QString sql = "select count(distinct \"" + colName + "\") = count(\"" +
980
-    colName + "\") from \"" + schemaName + "\".\"" + tableName + "\"";
981
+  QString sql = "select count(distinct " + quoteIdentifier(colName) + ") = count(" +  quoteIdentifier(colName) + ") from " + quoteIdentifier(schemaName) + "." + quoteIdentifier(tableName);
982
 
983
-  PGresult* unique = PQexec(connection, (const char*) (sql.utf8()));
984
+  PGresult* unique = PQexec(connection, sql.toUtf8());
985
 
986
   if (PQntuples(unique) == 1)
987
-    if (strncmp(PQgetvalue(unique, 0, 0),"t", 1) == 0)
988
+//    if (strncmp(PQgetvalue(unique, 0, 0),"t", 1) == 0)
989
+    if (QString::fromUtf8(PQgetvalue(unique, 0, 0)).compare("t") == 0)	//really should compare just first character as original did
990
       isUnique = true;
991
 
992
   PQclear(unique);
993
@@ -1243,12 +1239,12 @@
994
 int QgsPostgresProvider::SRCFromViewColumn(const QString& ns, const QString& relname, const QString& attname_table, const QString& attname_view, const QString& viewDefinition, SRC& result) const
995
 {
996
   QString newViewDefSql = "SELECT definition FROM pg_views WHERE schemaname = '" + ns + "' AND viewname = '" + relname + "'";
997
-  PGresult* newViewDefResult = PQexec(connection, (const char*)(newViewDefSql.utf8()));
998
+  PGresult* newViewDefResult = PQexec(connection, newViewDefSql.toUtf8());
999
   int numEntries = PQntuples(newViewDefResult);
1000
 
1001
   if(numEntries > 0) //relation is a view
1002
   {
1003
-    QString newViewDefinition(PQgetvalue(newViewDefResult, 0, 0));
1004
+    QString newViewDefinition(QString::fromUtf8(PQgetvalue(newViewDefResult, 0, 0)));
1005
 
1006
     QString newAttNameView = attname_table;
1007
     QString newAttNameTable = attname_table;
1008
@@ -1263,12 +1259,15 @@
1009
       }
1010
     }
1011
 
1012
-    QString viewColumnSql = "SELECT table_schema, table_name, column_name FROM information_schema.view_column_usage WHERE view_schema = '" + ns + "' AND view_name = '" + relname + "' AND column_name = '" + newAttNameTable +"'";
1013
-    PGresult* viewColumnResult = PQexec(connection, (const char*)(viewColumnSql.utf8()));
1014
+    QString viewColumnSql = "SELECT table_schema, table_name, column_name FROM (SELECT DISTINCT current_database()::information_schema.sql_identifier AS view_catalog, nv.nspname::information_schema.sql_identifier AS view_schema, v.relname::information_schema.sql_identifier AS view_name, current_database()::information_schema.sql_identifier AS table_catalog, nt.nspname::information_schema.sql_identifier AS table_schema, t.relname::information_schema.sql_identifier AS table_name, a.attname::information_schema.sql_identifier AS column_name "
1015
+" FROM pg_namespace nv, pg_class v, pg_depend dv, pg_depend dt, pg_class t, pg_namespace nt, pg_attribute a "
1016
+" WHERE nv.oid = v.relnamespace AND v.relkind = 'v'::\"char\" AND v.oid = dv.refobjid AND dv.refclassid = 'pg_class'::regclass::oid AND dv.classid = 'pg_rewrite'::regclass::oid AND dv.deptype = 'i'::\"char\" AND dv.objid = dt.objid AND dv.refobjid <> dt.refobjid AND dt.classid = 'pg_rewrite'::regclass::oid AND dt.refclassid = 'pg_class'::regclass::oid AND dt.refobjid = t.oid AND t.relnamespace = nt.oid AND (t.relkind = ANY (ARRAY['r'::\"char\", 'v'::\"char\"])) AND t.oid = a.attrelid AND dt.refobjsubid = a.attnum "
1017
+"ORDER BY current_database()::information_schema.sql_identifier, nv.nspname::information_schema.sql_identifier, v.relname::information_schema.sql_identifier, current_database()::information_schema.sql_identifier, nt.nspname::information_schema.sql_identifier, t.relname::information_schema.sql_identifier, a.attname::information_schema.sql_identifier) x WHERE view_schema = '" + ns + "' AND view_name = '" + relname + "' AND column_name = '" + newAttNameTable +"'";
1018
+    PGresult* viewColumnResult = PQexec(connection, viewColumnSql.toUtf8());
1019
     if(PQntuples(viewColumnResult) > 0)
1020
     {
1021
-      QString newTableSchema = PQgetvalue(viewColumnResult, 0, 0);
1022
-      QString newTableName = PQgetvalue(viewColumnResult, 0, 1);
1023
+      QString newTableSchema = QString::fromUtf8(PQgetvalue(viewColumnResult, 0, 0));
1024
+      QString newTableName = QString::fromUtf8(PQgetvalue(viewColumnResult, 0, 1));
1025
       int retvalue = SRCFromViewColumn(newTableSchema, newTableName, newAttNameTable, newAttNameView, newViewDefinition, result);
1026
       PQclear(viewColumnResult);
1027
       return retvalue;
1028
@@ -1288,12 +1287,12 @@
1029
   QgsDebugMsg("***********************************************************************************");
1030
   QgsDebugMsg(typeSql);
1031
   QgsDebugMsg("***********************************************************************************");
1032
-  PGresult* typeSqlResult = PQexec(connection, (const char*)(typeSql.utf8()));
1033
+  PGresult* typeSqlResult = PQexec(connection, typeSql.toUtf8());
1034
   if(PQntuples(typeSqlResult) < 1)
1035
   {
1036
     return 1;
1037
   }
1038
-  QString type = PQgetvalue(typeSqlResult, 0, 0);
1039
+  QString type = QString::fromUtf8(PQgetvalue(typeSqlResult, 0, 0));
1040
   PQclear(typeSqlResult);
1041
 
1042
   result.schema=ns;
1043
@@ -1309,18 +1308,21 @@
1044
 
1045
 void QgsPostgresProvider::findColumns(tableCols& cols)
1046
 {
1047
-  QString viewColumnSql = "SELECT table_schema, table_name, column_name FROM information_schema.view_column_usage WHERE view_schema = '" + mSchemaName + "' AND view_name = '" + mTableName + "'";
1048
-  PGresult* viewColumnResult = PQexec(connection, (const char*)(viewColumnSql.utf8()));
1049
+  QString viewColumnSql = "SELECT table_schema, table_name, column_name FROM (SELECT DISTINCT current_database() AS view_catalog, nv.nspname AS view_schema, v.relname AS view_name, current_database() AS table_catalog, nt.nspname AS table_schema, t.relname AS table_name, a.attname AS column_name "
1050
+" FROM pg_namespace nv, pg_class v, pg_depend dv, pg_depend dt, pg_class t, pg_namespace nt, pg_attribute a "
1051
+" WHERE nv.oid = v.relnamespace AND v.relkind = 'v'::\"char\" AND v.oid = dv.refobjid AND dv.refclassid = 'pg_class'::regclass::oid AND dv.classid = 'pg_rewrite'::regclass::oid AND dv.deptype = 'i'::\"char\" AND dv.objid = dt.objid AND dv.refobjid <> dt.refobjid AND dt.classid = 'pg_rewrite'::regclass::oid AND dt.refclassid = 'pg_class'::regclass::oid AND dt.refobjid = t.oid AND t.relnamespace = nt.oid AND (t.relkind = ANY (ARRAY['r'::\"char\", 'v'::\"char\"])) AND t.oid = a.attrelid AND dt.refobjsubid = a.attnum "
1052
+"ORDER BY current_database(), nv.nspname, v.relname, current_database(), nt.nspname, t.relname, a.attname) x WHERE view_schema = '" + mSchemaName + "' AND view_name = '" + mTableName + "'";
1053
+  PGresult* viewColumnResult = PQexec(connection, viewColumnSql.toUtf8());
1054
 
1055
   //find out view definition
1056
   QString viewDefSql = "SELECT definition FROM pg_views WHERE schemaname = '" + mSchemaName + "' AND viewname = '" + mTableName + "'";
1057
-  PGresult* viewDefResult = PQexec(connection, (const char*)(viewDefSql.utf8()));
1058
+  PGresult* viewDefResult = PQexec(connection, viewDefSql.toUtf8());
1059
   if(PQntuples(viewDefResult) < 1)
1060
   {
1061
     PQclear(viewDefResult);
1062
     return;
1063
   }
1064
-  QString viewDefinition(PQgetvalue(viewDefResult, 0, 0));
1065
+  QString viewDefinition(QString::fromUtf8(PQgetvalue(viewDefResult, 0, 0)));
1066
   PQclear(viewDefResult);
1067
 
1068
   QString ns, relname, attname_table, attname_view;
1069
@@ -1328,9 +1330,9 @@
1070
 
1071
   for(int i = 0; i < PQntuples(viewColumnResult); ++i)
1072
   {
1073
-    ns = PQgetvalue(viewColumnResult, i, 0);
1074
-    relname = PQgetvalue(viewColumnResult, i, 1);
1075
-    attname_table = PQgetvalue(viewColumnResult, i, 2);
1076
+    ns = QString::fromUtf8(PQgetvalue(viewColumnResult, i, 0));
1077
+    relname = QString::fromUtf8(PQgetvalue(viewColumnResult, i, 1));
1078
+    attname_table = QString::fromUtf8(PQgetvalue(viewColumnResult, i, 2));
1079
 
1080
     //find out original attribute name
1081
     attname_view = attname_table;
1082
@@ -1574,14 +1576,14 @@
1083
   QString sql;
1084
   if(sqlWhereClause.isEmpty())
1085
   {
1086
-    sql = QString("select min(\"%1\") from %2").arg(fld.name()).arg(mSchemaTableName);
1087
+    sql = QString("select min(%1) from %2").arg(quoteIdentifier(fld.name())).arg(mSchemaTableName);
1088
   }
1089
   else
1090
   {
1091
-    sql = QString("select min(\"%1\") from %2").arg(fld.name()).arg(mSchemaTableName)+" where "+sqlWhereClause;
1092
+    sql = QString("select min(%1) from %2").arg(quoteIdentifier(fld.name())).arg(mSchemaTableName)+" where "+sqlWhereClause;
1093
   }
1094
-  PGresult *rmin = PQexec(connection,(const char *)(sql.utf8()));
1095
-  QString minValue = PQgetvalue(rmin,0,0);
1096
+  PGresult *rmin = PQexec(connection, sql.toUtf8());
1097
+  QString minValue = QString::fromUtf8(PQgetvalue(rmin,0,0));
1098
   PQclear(rmin);
1099
   return minValue.toDouble();
1100
 }
1101
@@ -1595,14 +1597,14 @@
1102
   QString sql;
1103
   if(sqlWhereClause.isEmpty())
1104
   {
1105
-    sql = QString("select max(\"%1\") from %2").arg(fld.name()).arg(mSchemaTableName);
1106
+    sql = QString("select max(%1) from %2").arg(quoteIdentifier(fld.name())).arg(mSchemaTableName);
1107
   }
1108
   else
1109
   {
1110
-    sql = QString("select max(\"%1\") from %2").arg(fld.name()).arg(mSchemaTableName)+" where "+sqlWhereClause;
1111
+    sql = QString("select max(%1) from %2").arg(quoteIdentifier(fld.name())).arg(mSchemaTableName)+" where "+sqlWhereClause;
1112
   } 
1113
-  PGresult *rmax = PQexec(connection,(const char *)(sql.utf8()));
1114
-  QString maxValue = PQgetvalue(rmax,0,0);
1115
+  PGresult *rmax = PQexec(connection, sql.toUtf8());
1116
+  QString maxValue = QString::fromUtf8(PQgetvalue(rmax,0,0));
1117
   PQclear(rmax);
1118
   return maxValue.toDouble();
1119
 }
1120
@@ -1612,12 +1614,12 @@
1121
 {
1122
   QString sql;
1123
 
1124
-  sql = QString("select max(\"%1\") from %2")
1125
-    .arg(primaryKey)
1126
+  sql = QString("select max(%1) from %2")
1127
+    .arg(quoteIdentifier(primaryKey))
1128
     .arg(mSchemaTableName);
1129
 
1130
-  PGresult *rmax = PQexec(connection,(const char *)(sql.utf8()));
1131
-  QString maxValue = PQgetvalue(rmax,0,0);
1132
+  PGresult *rmax = PQexec(connection, sql.toUtf8());
1133
+  QString maxValue = QString::fromUtf8(PQgetvalue(rmax,0,0));
1134
   PQclear(rmax);
1135
 
1136
   return maxValue.toInt();
1137
@@ -1656,11 +1658,11 @@
1138
   insert+=" (";
1139
 
1140
   // add the name of the geometry column to the insert statement
1141
-  insert += "\"" + geometryColumn;
1142
+  insert += quoteIdentifier(geometryColumn);
1143
 
1144
   // add the name of the primary key column to the insert statement
1145
-  insert += "\",\"";
1146
-  insert += primaryKey + "\"";
1147
+  insert += ",";
1148
+  insert += quoteIdentifier(primaryKey);
1149
 
1150
   QgsDebugMsg("Constructing insert SQL, currently at: " + insert);
1151
 
1152
@@ -1685,8 +1687,8 @@
1153
         (!(it->isNull()))
1154
        )
1155
     {
1156
-      insert+=",\"";
1157
-      insert+=fieldname +"\"";
1158
+      insert+=",";
1159
+      insert+=quoteIdentifier(fieldname);
1160
     }
1161
   }
1162
 
1163
@@ -1777,8 +1779,6 @@
1164
         }
1165
       }
1166
 
1167
-      // important: escape quotes in field value
1168
-      fieldvalue.replace("'", "''");
1169
 
1170
       //request default value explicitly if fieldvalue is an empty string
1171
       if(fieldvalue.isEmpty())
1172
@@ -1790,6 +1790,7 @@
1173
         // XXX isn't it better to always escape field value?
1174
         if(charactertype)
1175
         {
1176
+          fieldvalue.replace("'", "''");	// escape quotes on text type fields; needs more work as other characters like '\' may need it as well; really should use PQescapeStringConn()
1177
           insert+="'";
1178
         }
1179
 
1180
@@ -1808,7 +1809,7 @@
1181
   qWarning("insert statement is: "+insert);
1182
 
1183
   //send INSERT statement and do error handling
1184
-  PGresult* result=PQexec(connection, (const char *)(insert.utf8()));
1185
+  PGresult* result=PQexec(connection, insert.toUtf8());
1186
   if(result==0)
1187
   {
1188
     showMessageBox(tr("INSERT error"),tr("An error occured during feature insertion"));
1189
@@ -1817,7 +1818,7 @@
1190
   ExecStatusType message=PQresultStatus(result);
1191
   if(message==PGRES_FATAL_ERROR)
1192
   {
1193
-    showMessageBox(tr("INSERT error"),QString(PQresultErrorMessage(result)));
1194
+    showMessageBox(tr("INSERT error"),QString::fromUtf8(PQresultErrorMessage(result)));
1195
     return false;
1196
   }
1197
 
1198
@@ -1844,10 +1845,10 @@
1199
 
1200
   QString defaultValue("");
1201
 
1202
-  PGresult* result = PQexec(connection, (const char*)(sql.utf8()));
1203
+  PGresult* result = PQexec(connection, sql.toUtf8());
1204
 
1205
   if (PQntuples(result) == 1)
1206
-    defaultValue = PQgetvalue(result, 0, 0);
1207
+    defaultValue = QString::fromUtf8(PQgetvalue(result, 0, 0));
1208
 
1209
   PQclear(result);
1210
 
1211
@@ -1856,12 +1857,12 @@
1212
 
1213
 bool QgsPostgresProvider::deleteFeature(int id)
1214
 {
1215
-  QString sql("DELETE FROM "+mSchemaTableName+" WHERE \""+primaryKey+"\" = "+QString::number(id));
1216
+  QString sql("DELETE FROM "+mSchemaTableName+" WHERE "+quoteIdentifier(primaryKey)+" = "+QString::number(id));
1217
 
1218
   QgsDebugMsg("delete sql: "+sql);
1219
 
1220
   //send DELETE statement and do error handling
1221
-  PGresult* result=PQexec(connection, (const char *)(sql.utf8()));
1222
+  PGresult* result=PQexec(connection, sql.toUtf8());
1223
   if(result==0)
1224
   {
1225
     showMessageBox(tr("DELETE error"),tr("An error occured during deletion from disk"));
1226
@@ -1870,7 +1871,7 @@
1227
   ExecStatusType message=PQresultStatus(result);
1228
   if(message==PGRES_FATAL_ERROR)
1229
   {
1230
-    showMessageBox(tr("DELETE error"),QString(PQresultErrorMessage(result)));
1231
+    showMessageBox(tr("DELETE error"),QString::fromUtf8(PQresultErrorMessage(result)));
1232
     return false;
1233
   }
1234
 
1235
@@ -1890,8 +1891,8 @@
1236
 /* Functions for determining available features in postGIS */
1237
 QString QgsPostgresProvider::postgisVersion(PGconn *connection)
1238
 {
1239
-  PGresult *result = PQexec(connection, "select postgis_version()");
1240
-  postgisVersionInfo = PQgetvalue(result,0,0);
1241
+  PGresult *result = PQexec(connection, QString("select postgis_version()").toUtf8());
1242
+  postgisVersionInfo = QString::fromUtf8(PQgetvalue(result,0,0));
1243
 
1244
   QgsDebugMsg("PostGIS version info: " + postgisVersionInfo);
1245
 
1246
@@ -1932,7 +1933,7 @@
1247
 bool QgsPostgresProvider::addFeatures(QgsFeatureList & flist)
1248
 {
1249
   bool returnvalue=true;
1250
-  PQexec(connection,"BEGIN");
1251
+  PQexec(connection,QString("BEGIN").toUtf8());
1252
 
1253
   int primaryKeyHighWater = maxPrimaryKeyValue();
1254
 
1255
@@ -1945,7 +1946,7 @@
1256
       // TODO: exit loop here?
1257
     }
1258
   }
1259
-  PQexec(connection,"COMMIT");
1260
+  PQexec(connection,QString("COMMIT").toUtf8());
1261
   reset();
1262
   return returnvalue;
1263
 }
1264
@@ -1953,7 +1954,7 @@
1265
 bool QgsPostgresProvider::deleteFeatures(const QgsFeatureIds & id)
1266
 {
1267
   bool returnvalue=true;
1268
-  PQexec(connection,"BEGIN");
1269
+  PQexec(connection,QString("BEGIN").toUtf8());
1270
   for(QgsFeatureIds::const_iterator it=id.begin();it!=id.end();++it)
1271
   {
1272
     if(!deleteFeature(*it))
1273
@@ -1961,7 +1962,7 @@
1274
       returnvalue=false;
1275
     }
1276
   }
1277
-  PQexec(connection,"COMMIT");
1278
+  PQexec(connection,QString("COMMIT").toUtf8());
1279
   reset();
1280
   return returnvalue;
1281
 }
1282
@@ -1969,26 +1970,33 @@
1283
 bool QgsPostgresProvider::addAttributes(const QgsNewAttributesMap & name)
1284
 {
1285
   bool returnvalue=true;
1286
-  PQexec(connection,"BEGIN");
1287
+  PQexec(connection,QString("BEGIN").toUtf8());
1288
+
1289
   for(QgsNewAttributesMap::const_iterator iter=name.begin();iter!=name.end();++iter)
1290
   {
1291
-    QString sql="ALTER TABLE "+mSchemaTableName+" ADD COLUMN \""+iter.key()+"\" "+iter.value();
1292
+    QString sql="ALTER TABLE "+mSchemaTableName+" ADD COLUMN "+quoteIdentifier(iter.key())+" " +iter.value();
1293
 
1294
     QgsDebugMsg(sql);
1295
 
1296
     //send sql statement and do error handling
1297
-    PGresult* result=PQexec(connection, (const char *)(sql.utf8()));
1298
+    PGresult* result=PQexec(connection, sql.toUtf8());
1299
     if(result==0)
1300
     {
1301
+      // this condition is unlikely to occur; no message box is displayed
1302
       returnvalue=false;
1303
+    }
1304
+    else
1305
+    {
1306
       ExecStatusType message=PQresultStatus(result);
1307
       if(message==PGRES_FATAL_ERROR)
1308
       {
1309
-        showMessageBox("ALTER TABLE error",QString(PQresultErrorMessage(result)));
1310
+        showMessageBox("ALTER TABLE error",QString::fromUtf8(PQresultErrorMessage(result)));
1311
+        returnvalue=false;
1312
       } 
1313
     }
1314
+    if (false==returnvalue) break;		//break out of for loop on error
1315
   }
1316
-  PQexec(connection,"COMMIT");
1317
+  PQexec(connection,QString("COMMIT").toUtf8());
1318
   reset();
1319
   return returnvalue;
1320
 }
1321
@@ -1996,7 +2004,7 @@
1322
 bool QgsPostgresProvider::deleteAttributes(const QgsAttributeIds& ids)
1323
 {
1324
   bool returnvalue=true;
1325
-  PQexec(connection,"BEGIN");
1326
+  PQexec(connection,QString("BEGIN").toUtf8());
1327
 
1328
   for(QgsAttributeIds::const_iterator iter=ids.begin();iter != ids.end();++iter)
1329
   {
1330
@@ -2006,26 +2014,32 @@
1331
       continue;
1332
     }
1333
     QString column = field_it->name();
1334
-    QString sql="ALTER TABLE "+mSchemaTableName+" DROP COLUMN \""+column+"\"";
1335
+    QString sql="ALTER TABLE "+mSchemaTableName+" DROP COLUMN "+quoteIdentifier(column);
1336
 
1337
     //send sql statement and do error handling
1338
-    PGresult* result=PQexec(connection, (const char *)(sql.utf8()));
1339
+    PGresult* result=PQexec(connection, sql.toUtf8());
1340
     if(result==0)
1341
     {
1342
+      // this condition is unlikely to occur; no message box is displayed
1343
       returnvalue=false;
1344
+    }
1345
+    else
1346
+    {
1347
       ExecStatusType message=PQresultStatus(result);
1348
       if(message==PGRES_FATAL_ERROR)
1349
       {
1350
-        showMessageBox("ALTER TABLE error",QString(PQresultErrorMessage(result)));
1351
+        showMessageBox("ALTER TABLE error",QString::fromUtf8(PQresultErrorMessage(result)));
1352
+        returnvalue=false;
1353
       }
1354
-    }
1355
-    else
1356
-    {
1357
+      else
1358
+      {
1359
       //delete the attribute from attributeFields
1360
       attributeFields.remove(*iter);
1361
+      }
1362
     }
1363
+    if (false==returnvalue) break;		//break out of for loop on error
1364
   }
1365
-  PQexec(connection,"COMMIT");
1366
+  PQexec(connection,QString("COMMIT").toUtf8());
1367
   reset();
1368
   return returnvalue;
1369
 }
1370
@@ -2033,7 +2047,7 @@
1371
 bool QgsPostgresProvider::changeAttributeValues(const QgsChangedAttributesMap & attr_map)
1372
 {
1373
   bool returnvalue=true; 
1374
-  PQexec(connection,"BEGIN");
1375
+  PQexec(connection,QString("BEGIN").toUtf8());
1376
 
1377
   // cycle through the features
1378
   for(QgsChangedAttributesMap::const_iterator iter=attr_map.begin();iter!=attr_map.end();++iter)
1379
@@ -2050,12 +2064,12 @@
1380
       // escape quotes
1381
       val.replace("'", "''");
1382
 
1383
-      QString sql="UPDATE "+mSchemaTableName+" SET \""+fieldName+"\"='"+val+"' WHERE \"" +primaryKey+"\"="+QString::number(fid);
1384
+      QString sql="UPDATE "+mSchemaTableName+" SET "+quoteIdentifier(fieldName)+"='"+val+"' WHERE " +quoteIdentifier(primaryKey)+"="+QString::number(fid);
1385
       QgsDebugMsg(sql);
1386
 
1387
       // s end sql statement and do error handling
1388
       // TODO: Make all error handling like this one
1389
-      PGresult* result=PQexec(connection, (const char *)(sql.utf8()));
1390
+      PGresult* result=PQexec(connection, sql.toUtf8());
1391
       if (result==0)
1392
       {
1393
         showMessageBox(tr("PostGIS error"),
1394
@@ -2066,14 +2080,14 @@
1395
       if(message==PGRES_FATAL_ERROR)
1396
       {
1397
         showMessageBox(tr("PostGIS error"),tr("The PostgreSQL database returned: ")
1398
-            + QString(PQresultErrorMessage(result))
1399
+            + QString::fromUtf8(PQresultErrorMessage(result))
1400
             + "\n" + tr("When trying: ") + sql);
1401
         return false;
1402
       }
1403
 
1404
     }
1405
   }
1406
-  PQexec(connection,"COMMIT");
1407
+  PQexec(connection,QString("COMMIT").toUtf8());
1408
   reset();
1409
   return returnvalue;
1410
 }
1411
@@ -2104,7 +2118,7 @@
1412
 
1413
   // Start the PostGIS transaction
1414
 
1415
-  PQexec(connection,"BEGIN");
1416
+  PQexec(connection,QString("BEGIN").toUtf8());
1417
 
1418
   for(QgsGeometryMap::iterator iter  = geometry_map.begin();
1419
       iter != geometry_map.end();
1420
@@ -2117,8 +2131,8 @@
1421
     {
1422
       QgsDebugMsg("iterating over feature id " + QString::number(iter.key()));
1423
 
1424
-      QString sql = "UPDATE "+ mSchemaTableName +" SET \"" + 
1425
-        geometryColumn + "\"=";
1426
+      QString sql = "UPDATE "+ mSchemaTableName +" SET " + 
1427
+        quoteIdentifier(geometryColumn) + "=";
1428
 
1429
       sql += "GeomFromWKB('";
1430
 
1431
@@ -2169,13 +2183,13 @@
1432
         sql += "::bytea',"+srid+")";
1433
       }
1434
 
1435
-      sql += " WHERE \"" +primaryKey+"\"="+QString::number(iter.key());
1436
+      sql += " WHERE " +quoteIdentifier(primaryKey)+"="+QString::number(iter.key());
1437
 
1438
       QgsDebugMsg("Updating with: " + sql);
1439
 
1440
       // send sql statement and do error handling
1441
       // TODO: Make all error handling like this one
1442
-      PGresult* result=PQexec(connection, (const char *)(sql.utf8()));
1443
+      PGresult* result=PQexec(connection, sql.toUtf8());
1444
       if (result==0)
1445
       {
1446
         showMessageBox(tr("PostGIS error"), tr("An error occured contacting the PostgreSQL database"));
1447
@@ -2185,7 +2199,7 @@
1448
       if(message==PGRES_FATAL_ERROR)
1449
       {
1450
         showMessageBox(tr("PostGIS error"), tr("The PostgreSQL database returned: ")
1451
-            + QString(PQresultErrorMessage(result))
1452
+            + QString::fromUtf8(PQresultErrorMessage(result))
1453
             + "\n" + tr("When trying: ") + sql);
1454
         return false;
1455
       }
1456
@@ -2194,7 +2208,7 @@
1457
 
1458
   } // for each feature
1459
 
1460
-  PQexec(connection,"COMMIT");
1461
+  PQexec(connection,QString("COMMIT").toUtf8());
1462
 
1463
   // TODO: Reset Geometry dirty if commit was OK
1464
 
1465
@@ -2264,12 +2278,12 @@
1466
   }
1467
 #endif
1468
 
1469
-  PGresult *result = PQexec(connection, (const char *) (sql.utf8()));
1470
+  PGresult *result = PQexec(connection, sql.toUtf8());
1471
 
1472
   QgsDebugMsg("Approximate Number of features as text: " +
1473
-      QString(PQgetvalue(result, 0, 0)));
1474
+      QString::fromUtf8(PQgetvalue(result, 0, 0)));
1475
 
1476
-  numberFeatures = QString(PQgetvalue(result, 0, 0)).toLong();
1477
+  numberFeatures = QString::fromUtf8(PQgetvalue(result, 0, 0)).toLong();
1478
   PQclear(result);
1479
 
1480
   QgsDebugMsg("Approximate Number of features: " + QString::number(numberFeatures));
1481
@@ -2285,7 +2299,7 @@
1482
   // get the approximate extent by retreiving the bounding box
1483
   // of the first few items with a geometry
1484
 
1485
-  QString sql = "select box3d(" + geometryColumn + ") from " 
1486
+  QString sql = "select box3d(" + quoteIdentifier(geometryColumn) + ") from " 
1487
     + mSchemaTableName + " where ";
1488
 
1489
   if(sqlWhereClause.length() > 0)
1490
@@ -2293,20 +2307,20 @@
1491
     sql += "(" + sqlWhereClause + ") and ";
1492
   }
1493
 
1494
-  sql += "not IsEmpty(" + geometryColumn + ") limit 5";
1495
+  sql += "not IsEmpty(" + quoteIdentifier(geometryColumn) + ") limit 5";
1496
 
1497
 
1498
 #if WASTE_TIME
1499
-  sql = "select xmax(extent(\"" + geometryColumn + "\")) as xmax,"
1500
-    "xmin(extent(\"" + geometryColumn + "\")) as xmin,"
1501
-    "ymax(extent(\"" + geometryColumn + "\")) as ymax," 
1502
-    "ymin(extent(\"" + geometryColumn + "\")) as ymin" 
1503
+  sql = "select xmax(extent(" + quoteIdentifier(geometryColumn) + ")) as xmax,"
1504
+    "xmin(extent(" + quoteIdentifier(geometryColumn) + ")) as xmin,"
1505
+    "ymax(extent(" + quoteIdentifier(geometryColumn) + ")) as ymax," 
1506
+    "ymin(extent(" + quoteIdentifier(geometryColumn) + ")) as ymin" 
1507
     " from " + mSchemaTableName;
1508
 #endif
1509
 
1510
   QgsDebugMsg("Getting approximate extent using: '" + sql + "'");
1511
 
1512
-  PGresult *result = PQexec(connection, (const char *) (sql.utf8()));
1513
+  PGresult *result = PQexec(connection, sql.toUtf8());
1514
 
1515
   // TODO: Guard against the result having no rows
1516
 
1517
@@ -2338,7 +2352,7 @@
1518
 
1519
   // get the extents
1520
 
1521
-  QString sql = "select extent(\"" + geometryColumn + "\") from " + 
1522
+  QString sql = "select extent(" + quoteIdentifier(geometryColumn) + ") from " + 
1523
     mSchemaTableName;
1524
   if(sqlWhereClause.length() > 0)
1525
   {
1526
@@ -2346,16 +2360,16 @@
1527
   }
1528
 
1529
 #if WASTE_TIME
1530
-  sql = "select xmax(extent(\"" + geometryColumn + "\")) as xmax,"
1531
-    "xmin(extent(\"" + geometryColumn + "\")) as xmin,"
1532
-    "ymax(extent(\"" + geometryColumn + "\")) as ymax," 
1533
-    "ymin(extent(\"" + geometryColumn + "\")) as ymin" 
1534
+  sql = "select xmax(extent(" + quoteIdentifier(geometryColumn) + ")) as xmax,"
1535
+    "xmin(extent(" + quoteIdentifier(geometryColumn) + ")) as xmin,"
1536
+    "ymax(extent(" + quoteIdentifier(geometryColumn) + ")) as ymax," 
1537
+    "ymin(extent(" + quoteIdentifier(geometryColumn) + ")) as ymin" 
1538
     " from " + mSchemaTableName;
1539
 #endif
1540
 
1541
   QgsDebugMsg("Getting extents using schema.table: " + sql);
1542
 
1543
-  PGresult *result = PQexec(connection, (const char *) (sql.utf8()));
1544
+  PGresult *result = PQexec(connection, sql.toUtf8());
1545
   if(PQntuples(result)>0)
1546
   {
1547
     std::string box3d = PQgetvalue(result, 0, 0);
1548
@@ -2473,28 +2487,26 @@
1549
   // version 7.4, binary cursors return data in XDR whereas previous versions
1550
   // return data in the endian of the server
1551
 
1552
-  QString firstOid = "select oid from pg_class where relname = '" + 
1553
-    mTableName + "' and relnamespace = (select oid from pg_namespace where nspname = '"
1554
-    + mSchemaName + "')";
1555
-  PGresult * oidResult = PQexec(connection, (const char*)(firstOid.utf8()));
1556
+  QString firstOid = "select regclass('" + mSchemaTableName + "')::oid";
1557
+  PGresult * oidResult = PQexec(connection, firstOid.toUtf8());
1558
   // get the int value from a "normal" select
1559
-  QString oidValue = PQgetvalue(oidResult,0,0);
1560
+  QString oidValue = QString::fromUtf8(PQgetvalue(oidResult,0,0));
1561
   PQclear(oidResult);
1562
 
1563
   QgsDebugMsg("Creating binary cursor");
1564
 
1565
   // get the same value using a binary cursor
1566
 
1567
-  PQexec(connection,"begin work");
1568
-  QString oidDeclare = QString("declare oidcursor binary cursor for select oid from pg_class where relname = '%1' and relnamespace = (select oid from pg_namespace where nspname = '%2')").arg(mTableName).arg(mSchemaName);
1569
+  PQexec(connection,QString("begin work").toUtf8());
1570
+  QString oidDeclare = "declare oidcursor binary cursor for select regclass('" + mSchemaTableName + "')::oid";
1571
   // set up the cursor
1572
-  PQexec(connection, (const char *)oidDeclare);
1573
+  PQexec(connection, oidDeclare.toUtf8());
1574
   QString fetch = "fetch forward 1 from oidcursor";
1575
 
1576
   QgsDebugMsg("Fetching a record and attempting to get check endian-ness");
1577
 
1578
-  PGresult *fResult = PQexec(connection, (const char *)fetch);
1579
-  PQexec(connection, "end work");
1580
+  PGresult *fResult = PQexec(connection, fetch.toUtf8());
1581
+  PQexec(connection, QString("end work").toUtf8());
1582
   swapEndian = true;
1583
   if(PQntuples(fResult) > 0){
1584
     // get the oid value from the binary cursor
1585
@@ -2531,8 +2543,8 @@
1586
 
1587
   if (PQntuples(result) > 0)
1588
   {
1589
-    srid = PQgetvalue(result, 0, PQfnumber(result, "srid"));
1590
-    fType = PQgetvalue(result, 0, PQfnumber(result, "type"));
1591
+    srid = QString::fromUtf8(PQgetvalue(result, 0, PQfnumber(result, QString("srid").toUtf8())));
1592
+    fType = QString::fromUtf8(PQgetvalue(result, 0, PQfnumber(result, QString("type").toUtf8())));
1593
     PQclear(result);
1594
   }
1595
   else
1596
@@ -2542,8 +2554,8 @@
1597
     // fail if there is no data in the relevant table.
1598
     PQclear(result); // for the query just before the if() statement
1599
     sql = "select "
1600
-      "srid(\""         + geometryColumn + "\"), "
1601
-      "geometrytype(\"" + geometryColumn + "\") from " + 
1602
+      "srid(" + quoteIdentifier(geometryColumn) + "), "
1603
+      "geometrytype(" + quoteIdentifier(geometryColumn) + ") from " + 
1604
       mSchemaTableName;
1605
 
1606
     //it is possible that the where clause restricts the feature type
1607
@@ -2559,8 +2571,8 @@
1608
 
1609
     if (PQntuples(result) > 0)
1610
     {
1611
-      srid = PQgetvalue(result, 0, PQfnumber(result, "srid"));
1612
-      fType = PQgetvalue(result, 0, PQfnumber(result, "geometrytype"));
1613
+      srid = QString::fromUtf8(PQgetvalue(result, 0, PQfnumber(result, QString("srid").toUtf8())));
1614
+      fType = QString::fromUtf8(PQgetvalue(result, 0, PQfnumber(result, QString("geometrytype").toUtf8())));
1615
     }
1616
     PQclear(result);
1617
   }
1618
@@ -2577,7 +2589,7 @@
1619
           " when geometrytype(%1) IN ('LINESTRING','MULTILINESTRING') THEN 'LINESTRING'"
1620
           " when geometrytype(%1) IN ('POLYGON','MULTIPOLYGON') THEN 'POLYGON'"
1621
           " end "
1622
-          "from %2").arg(geometryColumn).arg(mSchemaTableName);
1623
+          "from %2").arg(quoteIdentifier(geometryColumn)).arg(mSchemaTableName);
1624
       if(mUri.sql()!="")
1625
         sql += " where " + mUri.sql();
1626
 
1627
@@ -2585,7 +2597,7 @@
1628
 
1629
       if (PQntuples(result)==1)
1630
       {
1631
-        fType = PQgetvalue(result, 0, 0);
1632
+        fType = QString::fromUtf8(PQgetvalue(result, 0, 0));
1633
       }
1634
       PQclear(result);
1635
     }
1636
@@ -2649,18 +2661,23 @@
1637
 PGresult* QgsPostgresProvider::executeDbCommand(PGconn* connection, 
1638
     const QString& sql)
1639
 {
1640
-  PGresult *result = PQexec(connection, (const char *) (sql.utf8()));
1641
+  PGresult *result = PQexec(connection, sql.toUtf8());
1642
 
1643
   QgsDebugMsg("Executed SQL: " + sql);
1644
   if (PQresultStatus(result) == PGRES_TUPLES_OK) {
1645
     QgsDebugMsg("Command was successful.");
1646
   } else {
1647
     QgsDebugMsg("Command was unsuccessful. The error message was: "
1648
-        + QString( PQresultErrorMessage(result) ) );
1649
+        + QString::fromUtf8( PQresultErrorMessage(result) ) );
1650
   }
1651
   return result;
1652
 }
1653
 
1654
+QString QgsPostgresProvider::quoteIdentifier( const QString &ident )
1655
+{
1656
+  return QString( ident ).prepend("\"").append("\"");
1657
+}	// QgsPostgresProvider::quoteIdentifier( const QString &ident )
1658
+
1659
 void QgsPostgresProvider::showMessageBox(const QString& title, 
1660
     const QString& text)
1661
 {