QGIS API Documentation  2.3.0-Master
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
qgsdatasourceuri.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsdatasourceuri.h - Structure to contain the component parts
3  of a data source URI
4  -------------------
5  begin : Dec 5, 2004
6  copyright : (C) 2004 by Gary E.Sherman
7  email : sherman at mrcc.com
8  ***************************************************************************/
9 
10 /***************************************************************************
11  * *
12  * This program is free software; you can redistribute it and/or modify *
13  * it under the terms of the GNU General Public License as published by *
14  * the Free Software Foundation; either version 2 of the License, or *
15  * (at your option) any later version. *
16  * *
17  ***************************************************************************/
18 
19 #include "qgsdatasourceuri.h"
20 #include "qgslogger.h"
21 
22 #include <QStringList>
23 #include <QRegExp>
24 #include <QUrl>
25 
27  : mSSLmode( SSLprefer )
28  , mKeyColumn( "" )
29  , mUseEstimatedMetadata( false )
30  , mSelectAtIdDisabled( false )
31  , mWkbType( QGis::WKBUnknown )
32 {
33  // do nothing
34 }
35 
37  : mSSLmode( SSLprefer )
38  , mKeyColumn( "" )
39  , mUseEstimatedMetadata( false )
40  , mSelectAtIdDisabled( false )
41  , mWkbType( QGis::WKBUnknown )
42 {
43  int i = 0;
44  while ( i < uri.length() )
45  {
46  skipBlanks( uri, i );
47 
48  if ( uri[i] == '=' )
49  {
50  QgsDebugMsg( "parameter name expected before =" );
51  i++;
52  continue;
53  }
54 
55  int start = i;
56 
57  while ( i < uri.length() && uri[i] != '=' && !uri[i].isSpace() )
58  i++;
59 
60  QString pname = uri.mid( start, i - start );
61 
62  skipBlanks( uri, i );
63 
64  if ( uri[i] != '=' )
65  {
66  QgsDebugMsg( "= expected after parameter name" );
67  return;
68  }
69 
70  i++;
71 
72  if ( pname == "sql" )
73  {
74  // rest of line is a sql where clause
75  skipBlanks( uri, i );
76  mSql = uri.mid( i );
77  break;
78  }
79  else
80  {
81  QString pval = getValue( uri, i );
82 
83  if ( pname == "table" )
84  {
85  if ( uri[i] == '.' )
86  {
87  i++;
88 
89  mSchema = pval;
90  mTable = getValue( uri, i );
91  }
92  else
93  {
94  mSchema = "";
95  mTable = pval;
96  }
97 
98  if ( uri[i] == '(' )
99  {
100  i++;
101 
102  int start = i;
103  QString col;
104  while ( i < uri.length() && uri[i] != ')' )
105  {
106  if ( uri[i] == '\\' )
107  i++;
108  i++;
109  }
110 
111  if ( i == uri.length() )
112  {
113  QgsDebugMsg( "closing parenthesis missing" );
114  }
115 
116  mGeometryColumn = uri.mid( start, i - start );
117  mGeometryColumn.replace( "\\)", ")" );
118  mGeometryColumn.replace( "\\\\", "\\" );
119 
120  i++;
121  }
122  else
123  {
124  mGeometryColumn = QString::null;
125  }
126  }
127  else if ( pname == "key" )
128  {
129  mKeyColumn = pval;
130  }
131  else if ( pname == "estimatedmetadata" )
132  {
133  mUseEstimatedMetadata = pval == "true";
134  }
135  else if ( pname == "srid" )
136  {
137  mSrid = pval;
138  }
139  else if ( pname == "type" )
140  {
141  QString geomTypeUpper = pval.toUpper();
142  if ( geomTypeUpper == "POINT" )
143  {
145  }
146  else if ( geomTypeUpper == "LINESTRING" || geomTypeUpper == "LINE" )
147  {
149  }
150  else if ( geomTypeUpper == "POLYGON" )
151  {
153  }
154  else if ( geomTypeUpper == "MULTIPOINT" )
155  {
157  }
158  else if ( geomTypeUpper == "MULTILINESTRING" )
159  {
161  }
162  else if ( geomTypeUpper == "MULTIPOLYGON" )
163  {
165  }
166  else
167  {
169  }
170  }
171  else if ( pname == "selectatid" )
172  {
173  mSelectAtIdDisabled = pval == "false";
174  }
175  else if ( pname == "service" )
176  {
177  mService = pval;
178  }
179  else if ( pname == "user" )
180  {
181  mUsername = pval;
182  }
183  else if ( pname == "password" )
184  {
185  mPassword = pval;
186  }
187  else if ( pname == "connect_timeout" )
188  {
189  QgsDebugMsg( "connection timeout ignored" );
190  }
191  else if ( pname == "dbname" )
192  {
193  mDatabase = pval;
194  }
195  else if ( pname == "host" )
196  {
197  mHost = pval;
198  }
199  else if ( pname == "hostaddr" )
200  {
201  QgsDebugMsg( "database host ip address ignored" );
202  }
203  else if ( pname == "port" )
204  {
205  mPort = pval;
206  }
207  else if ( pname == "tty" )
208  {
209  QgsDebugMsg( "backend debug tty ignored" );
210  }
211  else if ( pname == "options" )
212  {
213  QgsDebugMsg( "backend debug options ignored" );
214  }
215  else if ( pname == "sslmode" )
216  {
217  if ( pval == "disable" )
219  else if ( pval == "allow" )
220  mSSLmode = SSLallow;
221  else if ( pval == "prefer" )
223  else if ( pval == "require" )
225  }
226  else if ( pname == "requiressl" )
227  {
228  if ( pval == "0" )
230  else
232  }
233  else if ( pname == "krbsrvname" )
234  {
235  QgsDebugMsg( "kerberos server name ignored" );
236  }
237  else if ( pname == "gsslib" )
238  {
239  QgsDebugMsg( "gsslib ignored" );
240  }
241  else
242  {
243  QgsDebugMsg( "invalid connection option \"" + pname + "\" ignored" );
244  }
245  }
246  }
247 }
248 
249 QString QgsDataSourceURI::removePassword( const QString& aUri )
250 {
251  QRegExp regexp;
252  regexp.setMinimal( true );
253  QString safeName( aUri );
254  if ( aUri.contains( " password=" ) )
255  {
256  regexp.setPattern( " password=.* " );
257  safeName.replace( regexp, " " );
258  }
259  else if ( aUri.contains( ",password=" ) )
260  {
261  regexp.setPattern( ",password=.*," );
262  safeName.replace( regexp, "," );
263  }
264  else if ( aUri.contains( "IDB:" ) )
265  {
266  regexp.setPattern( " pass=.* " );
267  safeName.replace( regexp, " " );
268  }
269  else if (( aUri.contains( "OCI:" ) )
270  || ( aUri.contains( "ODBC:" ) ) )
271  {
272  regexp.setPattern( "/.*@" );
273  safeName.replace( regexp, "/@" );
274  }
275  else if ( aUri.contains( "SDE:" ) )
276  {
277  QStringList strlist = aUri.split( "," );
278  safeName = strlist[0] + "," + strlist[1] + "," + strlist[2] + "," + strlist[3];
279  }
280  return safeName;
281 }
282 
284 {
285  return mUsername;
286 }
287 
288 void QgsDataSourceURI::setUsername( QString username )
289 {
291 }
292 
294 {
295  return mService;
296 }
297 
298 QString QgsDataSourceURI::host() const
299 {
300  return mHost;
301 }
302 
304 {
305  return mDatabase;
306 }
307 
309 {
310  return mPassword;
311 }
312 
313 void QgsDataSourceURI::setPassword( QString password )
314 {
316 }
317 
318 QString QgsDataSourceURI::port() const
319 {
320  return mPort;
321 }
322 
324 {
325  return mSSLmode;
326 }
327 
329 {
330  return mSchema;
331 }
332 
333 QString QgsDataSourceURI::table() const
334 {
335  return mTable;
336 }
337 
338 QString QgsDataSourceURI::sql() const
339 {
340  return mSql;
341 }
342 
344 {
345  return mGeometryColumn;
346 }
347 
349 {
350  return mKeyColumn;
351 }
352 
353 void QgsDataSourceURI::setKeyColumn( QString column )
354 {
355  mKeyColumn = column;
356 }
357 
358 
360 {
361  mUseEstimatedMetadata = theFlag;
362 }
363 
365 {
366  return mUseEstimatedMetadata;
367 }
368 
370 {
371  mSelectAtIdDisabled = theFlag;
372 }
373 
375 {
376  return mSelectAtIdDisabled;
377 }
378 
379 void QgsDataSourceURI::setSql( QString sql )
380 {
381  mSql = sql;
382 }
383 
385 {
386  mSchema = "";
387 }
388 
389 QString QgsDataSourceURI::escape( const QString &theVal, QChar delim = '\'' ) const
390 {
391  QString val = theVal;
392 
393  val.replace( "\\", "\\\\" );
394  val.replace( delim, QString( "\\%1" ).arg( delim ) );
395 
396  return val;
397 }
398 
399 void QgsDataSourceURI::skipBlanks( const QString &uri, int &i )
400 {
401  // skip space before value
402  while ( i < uri.length() && uri[i].isSpace() )
403  i++;
404 }
405 
406 QString QgsDataSourceURI::getValue( const QString &uri, int &i )
407 {
408  skipBlanks( uri, i );
409 
410  // Get the parameter value
411  QString pval;
412  if ( uri[i] == '\'' || uri[i] == '"' )
413  {
414  QChar delim = uri[i];
415 
416  i++;
417 
418  // value is quoted
419  for ( ;; )
420  {
421  if ( i == uri.length() )
422  {
423  QgsDebugMsg( "unterminated quoted string in connection info string" );
424  return pval;
425  }
426 
427  if ( uri[i] == '\\' )
428  {
429  i++;
430  if ( i == uri.length() )
431  continue;
432  if ( uri[i] != delim && uri[i] != '\\' )
433  i--;
434  }
435  else if ( uri[i] == delim )
436  {
437  i++;
438  break;
439  }
440 
441  pval += uri[i++];
442  }
443  }
444  else
445  {
446  // value is not quoted
447  while ( i < uri.length() )
448  {
449  if ( uri[i].isSpace() )
450  {
451  // end of value
452  break;
453  }
454 
455  if ( uri[i] == '\\' )
456  {
457  i++;
458  if ( i == uri.length() )
459  break;
460  if ( uri[i] != '\\' && uri[i] != '\'' )
461  i--;
462  }
463 
464  pval += uri[i++];
465  }
466  }
467 
468  skipBlanks( uri, i );
469 
470  return pval;
471 }
472 
474 {
475  QStringList connectionItems;
476 
477  if ( mDatabase != "" )
478  {
479  connectionItems << "dbname='" + escape( mDatabase ) + "'";
480  }
481 
482  if ( mService != "" )
483  {
484  connectionItems << "service='" + escape( mService ) + "'";
485  }
486  else if ( mHost != "" )
487  {
488  connectionItems << "host=" + mHost;
489  }
490 
491  if ( mService.isEmpty() )
492  {
493  if ( mPort != "" )
494  connectionItems << "port=" + mPort;
495  }
496 
497  if ( mUsername != "" )
498  {
499  connectionItems << "user='" + escape( mUsername ) + "'";
500 
501  if ( mPassword != "" )
502  {
503  connectionItems << "password='" + escape( mPassword ) + "'";
504  }
505  }
506 
507  if ( mSSLmode == SSLdisable )
508  connectionItems << "sslmode=disable";
509  else if ( mSSLmode == SSLallow )
510  connectionItems << "sslmode=allow";
511  else if ( mSSLmode == SSLrequire )
512  connectionItems << "sslmode=require";
513 #if 0
514  else if ( mSSLmode == SSLprefer )
515  connectionItems << "sslmode=prefer";
516 #endif
517 
518  return connectionItems.join( " " );
519 }
520 
521 QString QgsDataSourceURI::uri() const
522 {
523  QString theUri = connectionInfo();
524 
525  if ( !mKeyColumn.isEmpty() )
526  {
527  theUri += QString( " key='%1'" ).arg( escape( mKeyColumn ) );
528  }
529 
530  if ( mUseEstimatedMetadata )
531  {
532  theUri += QString( " estimatedmetadata=true" );
533  }
534 
535  if ( !mSrid.isEmpty() )
536  {
537  theUri += QString( " srid=%1" ).arg( mSrid );
538  }
539 
541  {
542  theUri += " type=";
543 
544  switch ( mWkbType )
545  {
546  case QGis::WKBPoint:
547  theUri += "POINT";
548  break;
549  case QGis::WKBLineString:
550  theUri += "LINESTRING";
551  break;
552  case QGis::WKBPolygon:
553  theUri += "POLYGON";
554  break;
555  case QGis::WKBMultiPoint:
556  theUri += "MULTIPOINT";
557  break;
559  theUri += "MULTILINESTRING";
560  break;
562  theUri += "MULTIPOLYGON";
563  break;
564  case QGis::WKBPoint25D:
565  theUri += "POINTM";
566  break;
568  theUri += "LINESTRINGM";
569  break;
570  case QGis::WKBPolygon25D:
571  theUri += "POLYGONM";
572  break;
574  theUri += "MULTIPOINTM";
575  break;
577  theUri += "MULTILINESTRINGM";
578  break;
580  theUri += "MULTIPOLYGONM";
581  break;
582  case QGis::WKBUnknown:
583  case QGis::WKBNoGeometry:
584  break;
585  }
586  }
587 
588  if ( mSelectAtIdDisabled )
589  {
590  theUri += QString( " selectatid=false" );
591  }
592 
593  QString columnName( mGeometryColumn );
594  columnName.replace( "\\", "\\\\" );
595  columnName.replace( ")", "\\)" );
596 
597  theUri += QString( " table=%1%2 sql=%3" )
598  .arg( quotedTablename() )
599  .arg( mGeometryColumn.isNull() ? QString() : QString( " (%1)" ).arg( columnName ) )
600  .arg( mSql );
601 
602  return theUri;
603 }
604 
606 {
607  QUrl url;
608  foreach ( QString key, mParams.uniqueKeys() )
609  {
610  foreach ( QString value, mParams.values( key ) )
611  {
612  url.addQueryItem( key, value );
613  }
614  }
615  return url.encodedQuery();
616 }
617 
618 void QgsDataSourceURI::setEncodedUri( const QByteArray & uri )
619 {
620  mParams.clear();
621  QUrl url;
622  url.setEncodedQuery( uri );
623  QPair<QString, QString> item;
624  foreach ( item, url.queryItems() )
625  {
626  mParams.insertMulti( item.first, item.second );
627  }
628 }
629 
630 void QgsDataSourceURI::setEncodedUri( const QString & uri )
631 {
632  setEncodedUri( uri.toAscii() );
633 }
634 
636 {
637  if ( !mSchema.isEmpty() )
638  return QString( "\"%1\".\"%2\"" )
639  .arg( escape( mSchema, '"' ) )
640  .arg( escape( mTable, '"' ) );
641  else
642  return QString( "\"%1\"" )
643  .arg( escape( mTable, '"' ) );
644 }
645 
646 void QgsDataSourceURI::setConnection( const QString &host,
647  const QString &port,
648  const QString &database,
649  const QString &username,
650  const QString &password,
651  SSLmode sslmode )
652 {
653  mHost = host;
655  mPort = port;
658  mSSLmode = sslmode;
659 }
660 
661 void QgsDataSourceURI::setConnection( const QString &service,
662  const QString &database,
663  const QString &username,
664  const QString &password,
665  SSLmode sslmode )
666 {
667  mService = service;
671  mSSLmode = sslmode;
672 }
673 
674 void QgsDataSourceURI::setDataSource( const QString &schema,
675  const QString &table,
676  const QString &geometryColumn,
677  const QString &sql,
678  const QString &keyColumn )
679 {
680  mSchema = schema;
681  mTable = table;
683  mSql = sql;
685 }
686 
687 void QgsDataSourceURI::setDatabase( const QString &database )
688 {
690 }
691 
693 {
694  return mWkbType;
695 }
696 
698 {
699  mWkbType = wkbType;
700 }
701 
702 QString QgsDataSourceURI::srid() const
703 {
704  return mSrid;
705 }
706 
707 void QgsDataSourceURI::setSrid( QString srid )
708 {
709  mSrid = srid;
710 }
711 
712 void QgsDataSourceURI::setParam( const QString &key, const QString &value )
713 {
714  // may be multiple
715  mParams.insertMulti( key, value );
716 }
717 
718 void QgsDataSourceURI::setParam( const QString &key, const QStringList &value )
719 {
720  foreach ( QString val, value )
721  {
722  mParams.insertMulti( key, val );
723  }
724 }
725 
726 int QgsDataSourceURI::removeParam( const QString &key )
727 {
728  return mParams.remove( key );
729 }
730 
731 QString QgsDataSourceURI::param( const QString &key ) const
732 {
733  return mParams.value( key );
734 }
735 
736 QStringList QgsDataSourceURI::params( const QString &key ) const
737 {
738  return mParams.values( key );
739 }
740 
741 bool QgsDataSourceURI::hasParam( const QString &key ) const
742 {
743  return mParams.contains( key );
744 }
QString srid() const
QString database() const
QString mService
service name
QgsDataSourceURI()
default constructor
int removeParam(const QString &key)
Remove generic param (generic mode)
QString quotedTablename() const
quoted table name
QString geometryColumn() const
QString mSql
SQL query or where clause used to limit features returned from the layer.
void setEncodedUri(const QByteArray &uri)
set complete encoded uri (generic mode)
#define QgsDebugMsg(str)
Definition: qgslogger.h:36
static QString removePassword(const QString &aUri)
Removes password element from uris.
QString mGeometryColumn
geometry column
QString password() const
void setDatabase(const QString &database)
Set database.
QString connectionInfo() const
return connection part of URI
WkbType
Used for symbology operations.
Definition: qgis.h:53
QString mSrid
SRID or a null string if not specified.
The QGis class provides global constants for use throughout the application.
Definition: qgis.h:34
bool mSelectAtIdDisabled
Disable SelectAtId capability (eg. to trigger the attribute table memory model for expensive views) ...
QString mTable
spatial table
bool useEstimatedMetadata() const
QStringList params(const QString &key) const
Get multiple generic param (generic mode)
QString keyColumn() const
QString mPort
port the database server listens on
void setConnection(const QString &aHost, const QString &aPort, const QString &aDatabase, const QString &aUsername, const QString &aPassword, SSLmode sslmode=SSLprefer)
Set all connection related members at once.
QString getValue(const QString &uri, int &i)
void setPassword(QString password)
set password
void disableSelectAtId(bool theFlag)
QString mSchema
schema
QGis::WkbType wkbType() const
void skipBlanks(const QString &uri, int &i)
QString uri() const
return complete uri
void setParam(const QString &key, const QString &value)
Set generic param (generic mode)
void setUseEstimatedMetadata(bool theFlag)
set use Estimated Metadata
enum SSLmode sslMode() const
bool hasParam(const QString &key) const
Test if param exists (generic mode)
void setSrid(QString srid)
QString host() const
QString mPassword
password
QString mHost
host name
QString schema() const
QString param(const QString &key) const
Get generic param (generic mode)
enum SSLmode mSSLmode
ssl mode
QString service() const
void setKeyColumn(QString column)
void setUsername(QString username)
set username
QMap< QString, QString > mParams
Generic params store.
QString mDatabase
database name
void setWkbType(QGis::WkbType type)
QString table() const
QGis::WkbType mWkbType
geometry type (or QGis::WKBUnknown if not specified)
QString mKeyColumn
key column
bool selectAtIdDisabled() const
QString sql() const
QByteArray encodedUri() const
return complete encoded uri (generic mode)
bool mUseEstimatedMetadata
Use estimated metadata flag.
void setSql(QString sql)
QString username() const
QString mUsername
username
QString port() const
QString escape(const QString &uri, QChar delim) const
void setDataSource(const QString &aSchema, const QString &aTable, const QString &aGeometryColumn, const QString &aSql=QString(), const QString &aKeyColumn=QString())
Set all data source related members at once.