LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/mssqlspatial - ogrmssqlspatiallayer.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 183 0 0.0 %
Date: 2012-12-26 Functions: 18 0 0.0 %

       1                 : /******************************************************************************
       2                 :  * $Id: ogrmssqlspatiallayer.cpp 24967 2012-09-24 21:51:46Z tamas $
       3                 :  *
       4                 :  * Project:  MSSQL Spatial driver
       5                 :  * Purpose:  Definition of classes for OGR MSSQL Spatial driver.
       6                 :  * Author:   Tamas Szekeres, szekerest at gmail.com
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2010, Tamas Szekeres
      10                 :  *
      11                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      12                 :  * copy of this software and associated documentation files (the "Software"),
      13                 :  * to deal in the Software without restriction, including without limitation
      14                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15                 :  * and/or sell copies of the Software, and to permit persons to whom the
      16                 :  * Software is furnished to do so, subject to the following conditions:
      17                 :  *
      18                 :  * The above copyright notice and this permission notice shall be included
      19                 :  * in all copies or substantial portions of the Software.
      20                 :  *
      21                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27                 :  * DEALINGS IN THE SOFTWARE.
      28                 :  ****************************************************************************/
      29                 : 
      30                 : #include "ogr_mssqlspatial.h"
      31                 : 
      32                 : CPL_CVSID("$Id: ogrmssqlspatiallayer.cpp 24967 2012-09-24 21:51:46Z tamas $");
      33                 : /************************************************************************/
      34                 : /*                        OGRMSSQLSpatialLayer()                        */
      35                 : /************************************************************************/
      36                 : 
      37               0 : OGRMSSQLSpatialLayer::OGRMSSQLSpatialLayer()
      38                 : 
      39                 : {
      40               0 :     poDS = NULL;
      41                 : 
      42               0 :     nGeomColumnType = -1;
      43               0 :     pszGeomColumn = NULL;
      44               0 :     pszFIDColumn = NULL;
      45               0 :     panFieldOrdinals = NULL;
      46                 : 
      47               0 :     poStmt = NULL;
      48                 : 
      49               0 :     iNextShapeId = 0;
      50                 : 
      51               0 :     poSRS = NULL;
      52               0 :     nSRSId = -1; // we haven't even queried the database for it yet. 
      53               0 : }
      54                 : 
      55                 : /************************************************************************/
      56                 : /*                      ~OGRMSSQLSpatialLayer()                         */
      57                 : /************************************************************************/
      58                 : 
      59               0 : OGRMSSQLSpatialLayer::~OGRMSSQLSpatialLayer()
      60                 : 
      61                 : {
      62               0 :     if( m_nFeaturesRead > 0 && poFeatureDefn != NULL )
      63                 :     {
      64                 :         CPLDebug( "OGR_MSSQLSpatial", "%d features read on layer '%s'.",
      65                 :                   (int) m_nFeaturesRead, 
      66               0 :                   poFeatureDefn->GetName() );
      67                 :     }
      68                 : 
      69               0 :     if( poStmt )
      70                 :     {
      71               0 :         delete poStmt;
      72               0 :         poStmt = NULL;
      73                 :     }
      74                 : 
      75               0 :     CPLFree( pszGeomColumn );
      76               0 :     CPLFree( pszFIDColumn );
      77               0 :     CPLFree( panFieldOrdinals );
      78                 : 
      79               0 :     if( poFeatureDefn )
      80                 :     {
      81               0 :         poFeatureDefn->Release();
      82               0 :         poFeatureDefn = NULL;
      83                 :     }
      84                 : 
      85               0 :     if( poSRS )
      86               0 :         poSRS->Release();
      87               0 : }
      88                 : 
      89                 : /************************************************************************/
      90                 : /*                          BuildFeatureDefn()                          */
      91                 : /*                                                                      */
      92                 : /*      Build feature definition from a set of column definitions       */
      93                 : /*      set on a statement.  Sift out geometry and FID fields.          */
      94                 : /************************************************************************/
      95                 : 
      96               0 : CPLErr OGRMSSQLSpatialLayer::BuildFeatureDefn( const char *pszLayerName, 
      97                 :                                     CPLODBCStatement *poStmt )
      98                 : 
      99                 : {
     100               0 :     poFeatureDefn = new OGRFeatureDefn( pszLayerName );
     101               0 :     int    nRawColumns = poStmt->GetColCount();
     102                 : 
     103               0 :     poFeatureDefn->Reference();
     104                 : 
     105               0 :     CPLFree(panFieldOrdinals);
     106               0 :     panFieldOrdinals = (int *) CPLMalloc( sizeof(int) * nRawColumns );
     107                 : 
     108               0 :     for( int iCol = 0; iCol < nRawColumns; iCol++ )
     109                 :     {
     110               0 :         if ( pszGeomColumn == NULL )
     111                 :         {
     112                 :             /* need to identify the geometry column */
     113               0 :             if ( EQUAL(poStmt->GetColTypeName( iCol ), "geometry") )
     114                 :             {
     115               0 :                 nGeomColumnType = MSSQLCOLTYPE_GEOMETRY;
     116               0 :                 pszGeomColumn = CPLStrdup( poStmt->GetColName(iCol) );
     117               0 :                 continue;
     118                 :             }
     119               0 :             else if ( EQUAL(poStmt->GetColTypeName( iCol ), "geography") )
     120                 :             {
     121               0 :                 nGeomColumnType = MSSQLCOLTYPE_GEOGRAPHY;
     122               0 :                 pszGeomColumn = CPLStrdup( poStmt->GetColName(iCol) );
     123               0 :                 continue;
     124                 :             }
     125               0 :             else if ( EQUAL(poStmt->GetColTypeName( iCol ), "image") )
     126                 :             {
     127                 :                 /* for the select layers we get image type */
     128               0 :                 nGeomColumnType = MSSQLCOLTYPE_BINARY;
     129               0 :                 pszGeomColumn = CPLStrdup( poStmt->GetColName(iCol) );
     130               0 :                 continue;
     131                 :             }
     132                 :         }
     133                 :         else
     134                 :         {
     135               0 :             if( EQUAL(poStmt->GetColName(iCol),pszGeomColumn) )
     136               0 :                 continue;
     137                 :         }
     138                 : 
     139               0 :         if( pszFIDColumn != NULL &&
     140                 :         EQUAL(poStmt->GetColName(iCol), pszFIDColumn) )
     141                 :         {
     142                 :             /* skip FID */
     143               0 :             continue;
     144                 :         }
     145                 : 
     146               0 :         OGRFieldDefn    oField( poStmt->GetColName(iCol), OFTString );
     147               0 :         oField.SetWidth( MAX(0,poStmt->GetColSize( iCol )) );
     148                 : 
     149               0 :         switch( CPLODBCStatement::GetTypeMapping(poStmt->GetColType(iCol)) )
     150                 :         {
     151                 :             case SQL_C_SSHORT:
     152                 :             case SQL_C_USHORT:
     153                 :             case SQL_C_SLONG:
     154                 :             case SQL_C_ULONG:
     155               0 :                 oField.SetType( OFTInteger );
     156               0 :                 break;
     157                 : 
     158                 :             case SQL_C_BINARY:
     159               0 :                 oField.SetType( OFTBinary );
     160               0 :                 break;
     161                 : 
     162                 :             case SQL_C_NUMERIC:
     163               0 :                 oField.SetType( OFTReal );
     164               0 :                 oField.SetPrecision( poStmt->GetColPrecision(iCol) );
     165               0 :                 break;
     166                 : 
     167                 :             case SQL_C_FLOAT:
     168                 :             case SQL_C_DOUBLE:
     169               0 :                 oField.SetType( OFTReal );
     170               0 :                 oField.SetWidth( 0 );
     171               0 :                 break;
     172                 : 
     173                 :             case SQL_C_DATE:
     174               0 :                 oField.SetType( OFTDate );
     175               0 :                 break;
     176                 : 
     177                 :             case SQL_C_TIME:
     178               0 :                 oField.SetType( OFTTime );
     179               0 :                 break;
     180                 : 
     181                 :             case SQL_C_TIMESTAMP:
     182               0 :                 oField.SetType( OFTDateTime );
     183                 :                 break;
     184                 : 
     185                 :             default:
     186                 :                 /* leave it as OFTString */;
     187                 :         }
     188                 : 
     189               0 :         poFeatureDefn->AddFieldDefn( &oField );
     190               0 :         panFieldOrdinals[poFeatureDefn->GetFieldCount() - 1] = iCol;
     191                 :     }
     192                 : 
     193                 : /* -------------------------------------------------------------------- */
     194                 : /*      If we don't already have an FID, check if there is a special    */
     195                 : /*      FID named column available.                                     */
     196                 : /* -------------------------------------------------------------------- */
     197               0 :     if( pszFIDColumn == NULL )
     198                 :     {
     199               0 :         const char *pszOGR_FID = CPLGetConfigOption("MSSQLSPATIAL_OGR_FID","OGR_FID");
     200               0 :         if( poFeatureDefn->GetFieldIndex( pszOGR_FID ) != -1 )
     201               0 :             pszFIDColumn = CPLStrdup(pszOGR_FID);
     202                 :     }
     203                 : 
     204               0 :     if( pszFIDColumn != NULL )
     205                 :         CPLDebug( "OGR_MSSQLSpatial", "Using column %s as FID for table %s.",
     206               0 :                   pszFIDColumn, poFeatureDefn->GetName() );
     207                 :     else
     208                 :         CPLDebug( "OGR_MSSQLSpatial", "Table %s has no identified FID column.",
     209               0 :                   poFeatureDefn->GetName() );
     210                 : 
     211               0 :     return CE_None;
     212                 : }
     213                 : 
     214                 : 
     215                 : /************************************************************************/
     216                 : /*                            ResetReading()                            */
     217                 : /************************************************************************/
     218                 : 
     219               0 : void OGRMSSQLSpatialLayer::ResetReading()
     220                 : 
     221                 : {
     222               0 :     iNextShapeId = 0;
     223               0 : }
     224                 : 
     225                 : /************************************************************************/
     226                 : /*                           GetNextFeature()                           */
     227                 : /************************************************************************/
     228                 : 
     229               0 : OGRFeature *OGRMSSQLSpatialLayer::GetNextFeature()
     230                 : 
     231                 : {
     232               0 :     while( TRUE )
     233                 :     {
     234                 :         OGRFeature      *poFeature;
     235                 : 
     236               0 :         poFeature = GetNextRawFeature();
     237               0 :         if( poFeature == NULL )
     238               0 :             return NULL;
     239                 : 
     240               0 :         if( (m_poFilterGeom == NULL
     241                 :             || FilterGeometry( poFeature->GetGeometryRef() ) )
     242                 :             && (m_poAttrQuery == NULL
     243                 :                 || m_poAttrQuery->Evaluate( poFeature )) )
     244               0 :             return poFeature;
     245                 : 
     246               0 :         delete poFeature;
     247                 :     }
     248                 : }
     249                 : 
     250                 : /************************************************************************/
     251                 : /*                         GetNextRawFeature()                          */
     252                 : /************************************************************************/
     253                 : 
     254               0 : OGRFeature *OGRMSSQLSpatialLayer::GetNextRawFeature()
     255                 : 
     256                 : {
     257               0 :     if( GetStatement() == NULL )
     258               0 :         return NULL;
     259                 : 
     260                 : /* -------------------------------------------------------------------- */
     261                 : /*      If we are marked to restart then do so, and fetch a record.     */
     262                 : /* -------------------------------------------------------------------- */
     263               0 :     if( !poStmt->Fetch() )
     264                 :     {
     265               0 :         delete poStmt;
     266               0 :         poStmt = NULL;
     267               0 :         return NULL;
     268                 :     }
     269                 : 
     270                 : /* -------------------------------------------------------------------- */
     271                 : /*      Create a feature from the current result.                       */
     272                 : /* -------------------------------------------------------------------- */
     273                 :     int         iField;
     274               0 :     OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
     275                 : 
     276               0 :     if( pszFIDColumn != NULL && poStmt->GetColId(pszFIDColumn) > -1 )
     277                 :         poFeature->SetFID( 
     278               0 :             atoi(poStmt->GetColData(poStmt->GetColId(pszFIDColumn))) );
     279                 :     else
     280               0 :         poFeature->SetFID( iNextShapeId );
     281                 : 
     282               0 :     iNextShapeId++;
     283               0 :     m_nFeaturesRead++;
     284                 : 
     285                 : /* -------------------------------------------------------------------- */
     286                 : /*      Set the fields.                                                 */
     287                 : /* -------------------------------------------------------------------- */
     288               0 :     for( iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
     289                 :     {
     290               0 :         int iSrcField = panFieldOrdinals[iField];
     291               0 :         const char *pszValue = poStmt->GetColData( iSrcField );
     292                 : 
     293               0 :         if( pszValue == NULL )
     294                 :             /* no value */;
     295               0 :         else if( poFeature->GetFieldDefnRef(iField)->GetType() == OFTBinary )
     296                 :             poFeature->SetField( iField, 
     297                 :                                  poStmt->GetColDataLength(iSrcField),
     298               0 :                                  (GByte *) pszValue );
     299                 :         else
     300               0 :             poFeature->SetField( iField, pszValue );
     301                 :     }
     302                 : 
     303                 : /* -------------------------------------------------------------------- */
     304                 : /*      Try to extract a geometry.                                      */
     305                 : /* -------------------------------------------------------------------- */
     306               0 :     if( pszGeomColumn != NULL )
     307                 :     {
     308               0 :         int iField = poStmt->GetColId( pszGeomColumn );
     309               0 :         const char *pszGeomText = poStmt->GetColData( iField );
     310               0 :         OGRGeometry *poGeom = NULL;
     311               0 :         OGRErr eErr = OGRERR_NONE;
     312                 : 
     313               0 :         if( pszGeomText != NULL )
     314                 :         {
     315               0 :             int nLength = poStmt->GetColDataLength( iField );
     316                 : 
     317               0 :             if ( nGeomColumnType == MSSQLCOLTYPE_GEOMETRY || 
     318                 :                  nGeomColumnType == MSSQLCOLTYPE_GEOGRAPHY ||
     319                 :                  nGeomColumnType == MSSQLCOLTYPE_BINARY)
     320                 :             {
     321               0 :                 switch ( poDS->GetGeometryFormat() )
     322                 :                 {
     323                 :                 case MSSQLGEOMETRY_NATIVE:
     324                 :                     {
     325               0 :                         OGRMSSQLGeometryParser oParser( nGeomColumnType ); 
     326                 :                         eErr = oParser.ParseSqlGeometry( 
     327               0 :                             (unsigned char *) pszGeomText, nLength, &poGeom );
     328               0 :                         nSRSId = oParser.GetSRSId();
     329                 :                     }
     330               0 :                     break;
     331                 :                 case MSSQLGEOMETRY_WKB:
     332                 :                 case MSSQLGEOMETRY_WKBZM:
     333                 :                     eErr = OGRGeometryFactory::createFromWkb((unsigned char *) pszGeomText,
     334               0 :                                                       NULL, &poGeom, nLength);
     335               0 :                     break;
     336                 :                 case MSSQLGEOMETRY_WKT:
     337                 :                     eErr = OGRGeometryFactory::createFromWkt((char **) &pszGeomText,
     338               0 :                                                       NULL, &poGeom);
     339                 :                     break;
     340                 :                 } 
     341                 :             }
     342               0 :             else if (nGeomColumnType == MSSQLCOLTYPE_TEXT)
     343                 :             {
     344                 :                 eErr = OGRGeometryFactory::createFromWkt((char **) &pszGeomText,
     345               0 :                                                       NULL, &poGeom);
     346                 :             }    
     347                 :         }
     348                 :         
     349               0 :         if ( eErr != OGRERR_NONE )
     350                 :         {
     351                 :             const char *pszMessage;
     352                 : 
     353               0 :             switch ( eErr )
     354                 :             {
     355                 :                 case OGRERR_NOT_ENOUGH_DATA:
     356               0 :                     pszMessage = "Not enough data to deserialize";
     357               0 :                     break;
     358                 :                 case OGRERR_UNSUPPORTED_GEOMETRY_TYPE:
     359               0 :                     pszMessage = "Unsupported geometry type";
     360               0 :                     break;
     361                 :                 case OGRERR_CORRUPT_DATA:
     362               0 :                     pszMessage = "Corrupt data";
     363               0 :                     break;
     364                 :                 default:
     365               0 :                     pszMessage = "Unrecognized error";
     366                 :             }
     367                 :             CPLError(CE_Failure, CPLE_AppDefined,
     368               0 :                      "GetNextRawFeature(): %s", pszMessage);
     369                 :         }
     370                 : 
     371               0 :         if( poGeom != NULL )
     372                 :         {
     373               0 :             if ( GetSpatialRef() )
     374               0 :                 poGeom->assignSpatialReference( poSRS );
     375                 : 
     376               0 :             poFeature->SetGeometryDirectly( poGeom );
     377                 :         }
     378                 :     }
     379                 : 
     380               0 :     return poFeature;
     381                 : }
     382                 : 
     383                 : /************************************************************************/
     384                 : /*                             GetFeature()                             */
     385                 : /************************************************************************/
     386                 : 
     387               0 : OGRFeature *OGRMSSQLSpatialLayer::GetFeature( long nFeatureId )
     388                 : 
     389                 : {
     390                 :     /* This should be implemented directly! */
     391                 : 
     392               0 :     return OGRLayer::GetFeature( nFeatureId );
     393                 : }
     394                 : 
     395                 : /************************************************************************/
     396                 : /*                           TestCapability()                           */
     397                 : /************************************************************************/
     398                 : 
     399               0 : int OGRMSSQLSpatialLayer::TestCapability( const char * pszCap )
     400                 : 
     401                 : {
     402               0 :     return FALSE;
     403                 : }
     404                 : 
     405                 : /************************************************************************/
     406                 : /*                          StartTransaction()                          */
     407                 : /************************************************************************/
     408                 : 
     409               0 : OGRErr OGRMSSQLSpatialLayer::StartTransaction()
     410                 : 
     411                 : {
     412               0 :     poDS->GetSession()->BeginTransaction();
     413               0 :     return OGRERR_NONE;
     414                 : }
     415                 : 
     416                 : /************************************************************************/
     417                 : /*                         CommitTransaction()                          */
     418                 : /************************************************************************/
     419                 : 
     420               0 : OGRErr OGRMSSQLSpatialLayer::CommitTransaction()
     421                 : 
     422                 : {
     423               0 :     poDS->GetSession()->CommitTransaction();
     424               0 :     return OGRERR_NONE;
     425                 : }
     426                 : 
     427                 : /************************************************************************/
     428                 : /*                        RollbackTransaction()                         */
     429                 : /************************************************************************/
     430                 : 
     431               0 : OGRErr OGRMSSQLSpatialLayer::RollbackTransaction()
     432                 : 
     433                 : {
     434               0 :     poDS->GetSession()->RollbackTransaction();
     435               0 :     return OGRERR_NONE;
     436                 : }
     437                 : 
     438                 : /************************************************************************/
     439                 : /*                           GetSpatialRef()                            */
     440                 : /************************************************************************/
     441                 : 
     442               0 : OGRSpatialReference *OGRMSSQLSpatialLayer::GetSpatialRef()
     443                 : 
     444                 : {
     445               0 :     if( poSRS == NULL && nSRSId > 0 )
     446                 :     {
     447               0 :         poSRS = poDS->FetchSRS( nSRSId );
     448               0 :         if( poSRS != NULL )
     449               0 :             poSRS->Reference();
     450                 :         else
     451               0 :             nSRSId = 0;
     452                 :     }
     453                 : 
     454               0 :     return poSRS;
     455                 : }
     456                 : 
     457                 : /************************************************************************/
     458                 : /*                            GetFIDColumn()                            */
     459                 : /************************************************************************/
     460                 : 
     461               0 : const char *OGRMSSQLSpatialLayer::GetFIDColumn() 
     462                 : 
     463                 : {
     464               0 :     GetLayerDefn();
     465                 : 
     466               0 :     if( pszFIDColumn != NULL )
     467               0 :         return pszFIDColumn;
     468                 :     else
     469               0 :         return "";
     470                 : }
     471                 : 
     472                 : /************************************************************************/
     473                 : /*                         GetGeometryColumn()                          */
     474                 : /************************************************************************/
     475                 : 
     476               0 : const char *OGRMSSQLSpatialLayer::GetGeometryColumn() 
     477                 : 
     478                 : {
     479               0 :     GetLayerDefn();
     480                 : 
     481               0 :     if( pszGeomColumn != NULL )
     482               0 :         return pszGeomColumn;
     483                 :     else
     484               0 :         return "";
     485                 : }
     486                 : 
     487                 : /************************************************************************/
     488                 : /*                        GByteArrayToHexString()                       */
     489                 : /************************************************************************/
     490                 : 
     491               0 : char* OGRMSSQLSpatialLayer::GByteArrayToHexString( const GByte* pabyData, int nLen)
     492                 : {
     493                 :     char* pszTextBuf;
     494                 : 
     495               0 :     pszTextBuf = (char *) CPLMalloc(nLen*2+3);
     496                 : 
     497               0 :     int  iSrc, iDst=0;
     498                 : 
     499               0 :     for( iSrc = 0; iSrc < nLen; iSrc++ )
     500                 :     {
     501               0 :         if( iSrc == 0 )
     502                 :         {
     503               0 :             sprintf( pszTextBuf+iDst, "0x%02x", pabyData[iSrc] );
     504               0 :             iDst += 4;
     505                 :         }
     506                 :         else
     507                 :         {
     508               0 :             sprintf( pszTextBuf+iDst, "%02x", pabyData[iSrc] );
     509               0 :             iDst += 2;
     510                 :         }
     511                 :     }
     512               0 :     pszTextBuf[iDst] = 0;
     513                 : 
     514               0 :     return pszTextBuf;
     515                 : }
     516                 : 

Generated by: LCOV version 1.7