56 changes: 48 additions & 8 deletions src/providers/mssql/qgsmssqlfeatureiterator.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,57 @@
#ifndef QGSMSSQLFEATUREITERATOR_H
#define QGSMSSQLFEATUREITERATOR_H

#include "qgsmssqlprovider.h"
#include "qgsmssqlgeometryparser.h"
#include "qgsfeatureiterator.h"
#include <QtSql/QSqlDatabase>
#include <QtSql/QSqlQuery>
#include <QtSql/QSqlError>

class QgsMssqlProvider;

class QgsMssqlFeatureIterator : public QgsAbstractFeatureIterator
class QgsMssqlFeatureSource : public QgsAbstractFeatureSource
{
public:
QgsMssqlFeatureIterator( QgsMssqlProvider* provider, const QgsFeatureRequest& request );
QgsMssqlFeatureSource( const QgsMssqlProvider* p );
~QgsMssqlFeatureSource();

virtual QgsFeatureIterator getFeatures( const QgsFeatureRequest& request );

protected:
QgsFields mFields;
QString mFidColName;
long mSRId;

/* sql geo type */
bool mIsGeography;

QString mGeometryColName;
QString mGeometryColType;

// current layer name
QString mSchemaName;
QString mTableName;

// login
QString mUserName;
QString mPassword;

// server access
QString mService;
QString mDriver;
QString mDatabaseName;
QString mHost;

// SQL statement used to limit the features retrieved
QString mSqlWhereClause;

friend class QgsMssqlFeatureIterator;
};

class QgsMssqlFeatureIterator : public QgsAbstractFeatureIteratorFromSource<QgsMssqlFeatureSource>
{
public:
QgsMssqlFeatureIterator( QgsMssqlFeatureSource* source, bool ownSource, const QgsFeatureRequest& request );

~QgsMssqlFeatureIterator();

Expand All @@ -40,10 +79,11 @@ class QgsMssqlFeatureIterator : public QgsAbstractFeatureIterator
virtual bool close();

protected:
QgsMssqlProvider* mProvider;


void BuildStatement( const QgsFeatureRequest& request );

QSqlDatabase GetDatabase(QString driver, QString host, QString database, QString username, QString password);

private:
//! fetch next feature, return true on success
virtual bool fetchFeature( QgsFeature& feature );
Expand All @@ -60,9 +100,6 @@ class QgsMssqlFeatureIterator : public QgsAbstractFeatureIterator
// The current sql statement
QString mStatement;

// Open connection flag
bool mIsOpen;

// Field index of FID column
long mFidCol;

Expand All @@ -71,6 +108,9 @@ class QgsMssqlFeatureIterator : public QgsAbstractFeatureIterator

// List of attribute indices to fetch with nextFeature calls
QgsAttributeList mAttributesToFetch;

// for parsing sql geometries
QgsMssqlGeometryParser mParser;
};

#endif // QGSMSSQLFEATUREITERATOR_H
2 changes: 1 addition & 1 deletion src/providers/mssql/qgsmssqlgeometryparser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
* *
***************************************************************************/

#include "qgsmssqlprovider.h"
#include "qgsmssqlgeometryparser.h"
#include "qgsgeometry.h"
#include "qgslogger.h"
#include "qgsapplication.h"
Expand Down
75 changes: 75 additions & 0 deletions src/providers/mssql/qgsmssqlgeometryparser.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/***************************************************************************
qgsmssqlgeometryparser.h - description
-------------------
begin : 2014-03-16
copyright : (C) 2014 by Tamas Szekeres
email : szekerest at gmail.com
***************************************************************************/

/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#ifndef QGSMSSQLGEOMETRYPARSER_H
#define QGSMSSQLGEOMETRYPARSER_H


/**
\class QgsMssqlGeometryParser
\brief Geometry parser for SqlGeometry/SqlGeography.
*
*/

class QgsMssqlGeometryParser
{

protected:
unsigned char* pszData;
unsigned char* pszWkb;
int nWkbLen;
int nWkbMaxLen;
/* byte order */
char chByteOrder;
/* serialization properties */
char chProps;
/* point array */
int nPointSize;
int nPointPos;
int nNumPoints;
/* figure array */
int nFigurePos;
int nNumFigures;
/* shape array */
int nShapePos;
int nNumShapes;
int nSRSId;

protected:
void CopyBytes( void* src, int len );
void CopyCoordinates( int iPoint );
void CopyPoint( int iPoint );
void ReadPoint( int iShape );
void ReadMultiPoint( int iShape );
void ReadLineString( int iShape );
void ReadMultiLineString( int iShape );
void ReadPolygon( int iShape );
void ReadMultiPolygon( int iShape );
void ReadGeometryCollection( int iShape );

public:
QgsMssqlGeometryParser();
unsigned char* ParseSqlGeometry( unsigned char* pszInput, int nLen );
int GetSRSId() { return nSRSId; };
int GetWkbLen() { return nWkbLen; };
void DumpMemoryToLog( const char* pszMsg, unsigned char* pszInput, int nLen );
/* sql geo type */
bool IsGeography;
};


#endif // QGSMSSQLGEOMETRYPARSER_H
31 changes: 24 additions & 7 deletions src/providers/mssql/qgsmssqlprovider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,17 @@ QgsMssqlProvider::QgsMssqlProvider( QString uri )
mUseWkb = false;
mSkipFailures = false;

mUserName = anUri.username();
mPassword = anUri.password();
mService = anUri.service();
mDatabaseName = anUri.database();
mHost = anUri.host();

mUseEstimatedMetadata = anUri.useEstimatedMetadata();

mSqlWhereClause = anUri.sql();

mDatabase = GetDatabase( anUri.service(), anUri.host(), anUri.database(), anUri.username(), anUri.password() );
mDatabase = QgsMssqlProvider::GetDatabase(mDriver, mHost, mDatabaseName, mUserName, mPassword);

if ( !OpenDatabase( mDatabase ) )
{
Expand Down Expand Up @@ -161,6 +167,13 @@ QgsMssqlProvider::QgsMssqlProvider( QString uri )

QgsMssqlProvider::~QgsMssqlProvider()
{
if (mDatabase.isOpen())
mDatabase.close();
}

QgsAbstractFeatureSource* QgsMssqlProvider::featureSource() const
{
return new QgsMssqlFeatureSource( this );
}

QgsFeatureIterator QgsMssqlProvider::getFeatures( const QgsFeatureRequest& request )
Expand All @@ -171,7 +184,7 @@ QgsFeatureIterator QgsMssqlProvider::getFeatures( const QgsFeatureRequest& reque
return QgsFeatureIterator();
}

return QgsFeatureIterator( new QgsMssqlFeatureIterator( this, request ) );
return QgsFeatureIterator( new QgsMssqlFeatureIterator( new QgsMssqlFeatureSource( this ), true, request ) );
}

bool QgsMssqlProvider::OpenDatabase( QSqlDatabase db )
Expand All @@ -186,10 +199,14 @@ bool QgsMssqlProvider::OpenDatabase( QSqlDatabase db )
return true;
}

QSqlDatabase QgsMssqlProvider::GetDatabase( QString driver, QString host, QString database, QString username, QString password )
QSqlDatabase QgsMssqlProvider::GetDatabase(QString driver, QString host, QString database, QString username, QString password)
{
QSqlDatabase db;
QString connectionName;

// create a separate database connection for each feature source
QgsDebugMsg( "Creating a separate database connection" );

if ( driver.isEmpty() )
{
if ( host.isEmpty() )
Expand Down Expand Up @@ -353,7 +370,7 @@ void QgsMssqlProvider::loadFields()
{
mGeometryColName = query.value( 3 ).toString();
mGeometryColType = sqlTypeName;
parser.IsGeography = sqlTypeName == "geography";
mParser.IsGeography = sqlTypeName == "geography";
}
else
{
Expand Down Expand Up @@ -649,10 +666,10 @@ void QgsMssqlProvider::UpdateStatistics( bool estimate )
while ( query.next() )
{
QByteArray ar = query.value( 0 ).toByteArray();
unsigned char* wkb = parser.ParseSqlGeometry(( unsigned char* )ar.data(), ar.size() );
unsigned char* wkb = mParser.ParseSqlGeometry(( unsigned char* )ar.data(), ar.size() );
if ( wkb )
{
geom.fromWkb( wkb, parser.GetWkbLen() );
geom.fromWkb( wkb, mParser.GetWkbLen() );
QgsRectangle rect = geom.boundingBox();

if ( rect.xMinimum() < mExtent.xMinimum() )
Expand All @@ -665,7 +682,7 @@ void QgsMssqlProvider::UpdateStatistics( bool estimate )
mExtent.setYMaximum( rect.yMaximum() );

mWkbType = geom.wkbType();
mSRId = parser.GetSRSId();
mSRId = mParser.GetSRSId();
}
}
}
Expand Down
73 changes: 17 additions & 56 deletions src/providers/mssql/qgsmssqlprovider.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,60 +37,7 @@ class QgsMssqlFeatureIterator;

#include "qgsdatasourceuri.h"
#include "qgsgeometry.h"


/**
\class QgsMssqlGeometryParser
\brief Geometry parser for SqlGeometry/SqlGeography.
*
*/

class QgsMssqlGeometryParser
{

protected:
unsigned char* pszData;
unsigned char* pszWkb;
int nWkbLen;
int nWkbMaxLen;
/* byte order */
char chByteOrder;
/* serialization properties */
char chProps;
/* point array */
int nPointSize;
int nPointPos;
int nNumPoints;
/* figure array */
int nFigurePos;
int nNumFigures;
/* shape array */
int nShapePos;
int nNumShapes;
int nSRSId;

protected:
void CopyBytes( void* src, int len );
void CopyCoordinates( int iPoint );
void CopyPoint( int iPoint );
void ReadPoint( int iShape );
void ReadMultiPoint( int iShape );
void ReadLineString( int iShape );
void ReadMultiLineString( int iShape );
void ReadPolygon( int iShape );
void ReadMultiPolygon( int iShape );
void ReadGeometryCollection( int iShape );

public:
QgsMssqlGeometryParser();
unsigned char* ParseSqlGeometry( unsigned char* pszInput, int nLen );
int GetSRSId() { return nSRSId; };
int GetWkbLen() { return nWkbLen; };
void DumpMemoryToLog( const char* pszMsg, unsigned char* pszInput, int nLen );
/* sql geo type */
bool IsGeography;
};

#include "qgsmssqlgeometryparser.h"

/**
\class QgsMssqlProvider
Expand All @@ -108,6 +55,9 @@ class QgsMssqlProvider : public QgsVectorDataProvider
virtual ~QgsMssqlProvider();

static QSqlDatabase GetDatabase( QString driver, QString host, QString database, QString username, QString password );

virtual QgsAbstractFeatureSource* featureSource() const;

static bool OpenDatabase( QSqlDatabase db );

/* Implementation of functions from QgsVectorDataProvider */
Expand Down Expand Up @@ -304,7 +254,7 @@ class QgsMssqlProvider : public QgsVectorDataProvider
QgsFields mAttributeFields;
QMap<int, QVariant> mDefaultValues;

QgsMssqlGeometryParser parser;
QgsMssqlGeometryParser mParser;

//! Layer extent
QgsRectangle mExtent;
Expand Down Expand Up @@ -343,6 +293,17 @@ class QgsMssqlProvider : public QgsVectorDataProvider
// current layer name
QString mSchemaName;
QString mTableName;

// login
QString mUserName;
QString mPassword;

// server access
QString mService;
QString mDriver;
QString mDatabaseName;
QString mHost;

// available tables
QStringList mTables;

Expand All @@ -358,7 +319,7 @@ class QgsMssqlProvider : public QgsVectorDataProvider
static void mssqlWkbTypeAndDimension( QGis::WkbType wkbType, QString &geometryType, int &dim );
static QGis::WkbType getWkbType( QString geometryType, int dim );

friend class QgsMssqlFeatureIterator;
friend class QgsMssqlFeatureSource;
};

#endif // QGSMSSQLPROVIDER_H