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

       1                 : /******************************************************************************
       2                 :  * $Id: ogrmssqlspatialtablelayer.cpp 21943 2011-03-12 18:25:22Z tamas $
       3                 :  *
       4                 :  * Project:  MSSQL Spatial driver
       5                 :  * Purpose:  Implements OGRMSSQLSpatialTableLayer class, access to an existing table.
       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 "cpl_conv.h"
      31                 : #include "ogr_mssqlspatial.h"
      32                 : 
      33                 : CPL_CVSID("$Id: ogrmssqlspatialtablelayer.cpp 21943 2011-03-12 18:25:22Z tamas $");
      34                 : 
      35                 : /************************************************************************/
      36                 : /*                         OGRMSSQLAppendEscaped( )                     */
      37                 : /************************************************************************/
      38                 : 
      39               0 : void OGRMSSQLAppendEscaped( CPLODBCStatement* poStatement, const char* pszStrValue)
      40                 : {
      41               0 :     if (!pszStrValue)
      42               0 :         poStatement->Append("null");
      43                 :     
      44               0 :     size_t  iIn, iOut , nTextLen = strlen(pszStrValue);
      45               0 :     char    *pszEscapedText = (char *) VSIMalloc(nTextLen*2 + 3);
      46                 : 
      47               0 :     pszEscapedText[0] = '\'';
      48                 :     
      49               0 :     for( iIn = 0, iOut = 1; iIn < nTextLen; iIn++ )
      50                 :     {
      51               0 :         switch( pszStrValue[iIn] )
      52                 :         {
      53                 :             case '\'':
      54               0 :                 pszEscapedText[iOut++] = '\''; // double quote
      55               0 :                 pszEscapedText[iOut++] = pszStrValue[iIn];
      56               0 :                 break;
      57                 : 
      58                 :             default:
      59               0 :                 pszEscapedText[iOut++] = pszStrValue[iIn];
      60                 :                 break;
      61                 :         }
      62                 :     }
      63                 : 
      64               0 :     pszEscapedText[iOut++] = '\'';
      65                 : 
      66               0 :     pszEscapedText[iOut] = '\0';
      67                 : 
      68               0 :     poStatement->Append(pszEscapedText);
      69                 : 
      70               0 :     CPLFree( pszEscapedText );
      71               0 : }
      72                 : 
      73                 : /************************************************************************/
      74                 : /*                          OGRMSSQLSpatialTableLayer()                 */
      75                 : /************************************************************************/
      76                 : 
      77               0 : OGRMSSQLSpatialTableLayer::OGRMSSQLSpatialTableLayer( OGRMSSQLSpatialDataSource *poDSIn )
      78                 : 
      79                 : {
      80               0 :     poDS = poDSIn;
      81                 : 
      82               0 :     pszQuery = NULL;
      83                 : 
      84               0 :     bUpdateAccess = TRUE;
      85                 : 
      86               0 :     iNextShapeId = 0;
      87                 : 
      88               0 :     nSRSId = -1;
      89                 : 
      90               0 :     poFeatureDefn = NULL;
      91                 :     
      92               0 :     pszTableName = NULL;
      93               0 :     pszSchemaName = NULL;
      94               0 : }
      95                 : 
      96                 : /************************************************************************/
      97                 : /*                          ~OGRMSSQLSpatialTableLayer()                */
      98                 : /************************************************************************/
      99                 : 
     100               0 : OGRMSSQLSpatialTableLayer::~OGRMSSQLSpatialTableLayer()
     101                 : 
     102                 : {
     103               0 :     CPLFree( pszTableName );
     104               0 :     CPLFree( pszSchemaName );
     105                 : 
     106               0 :     CPLFree( pszQuery );
     107               0 :     ClearStatement();
     108               0 : }
     109                 : 
     110                 : /************************************************************************/
     111                 : /*                             Initialize()                             */
     112                 : /************************************************************************/
     113                 : 
     114               0 : CPLErr OGRMSSQLSpatialTableLayer::Initialize( const char *pszSchema,
     115                 :                                               const char *pszLayerName, 
     116                 :                                               const char *pszGeomCol,
     117                 :                                               int nCoordDimension, 
     118                 :                                               int nSRId,
     119                 :                                               OGRwkbGeometryType eType )
     120                 : 
     121                 : {
     122               0 :     CPLODBCSession *poSession = poDS->GetSession();
     123                 : 
     124               0 :     CPLFree( pszFIDColumn );
     125               0 :     pszFIDColumn = NULL;
     126                 : 
     127                 : /* -------------------------------------------------------------------- */
     128                 : /*      Parse out schema name if present in layer.  We assume a         */
     129                 : /*      schema is provided if there is a dot in the name, and that      */
     130                 : /*      it is in the form <schema>.<tablename>                          */
     131                 : /* -------------------------------------------------------------------- */
     132               0 :     const char *pszDot = strstr(pszLayerName,".");
     133               0 :     if( pszDot != NULL )
     134                 :     {
     135               0 :         pszTableName = CPLStrdup(pszDot + 1);
     136               0 :         pszSchemaName = CPLStrdup(pszLayerName);
     137               0 :         pszSchemaName[pszDot - pszLayerName] = '\0';
     138                 :     }
     139                 :     else
     140                 :     {
     141               0 :         pszTableName = CPLStrdup(pszLayerName);
     142               0 :         pszSchemaName = CPLStrdup(pszSchema);
     143                 :     }
     144                 : 
     145                 : /* -------------------------------------------------------------------- */
     146                 : /*      Do we have a simple primary key?                                */
     147                 : /* -------------------------------------------------------------------- */
     148               0 :     CPLODBCStatement oGetKey( poSession );
     149                 :     
     150               0 :     if( oGetKey.GetPrimaryKeys( pszTableName, poDS->GetCatalog(), pszSchemaName ) 
     151                 :         && oGetKey.Fetch() )
     152                 :     {
     153               0 :         pszFIDColumn = CPLStrdup(oGetKey.GetColData( 3 ));
     154                 :         
     155               0 :         if( oGetKey.Fetch() ) // more than one field in key! 
     156                 :         {
     157               0 :             CPLFree( pszFIDColumn );
     158               0 :             pszFIDColumn = NULL;
     159                 : 
     160                 :             CPLDebug( "OGR_MSSQLSpatial", "Table %s has multiple primary key fields, "
     161               0 :                       "ignoring them all.", pszTableName );
     162                 :         }
     163                 :     }
     164                 : 
     165                 : /* -------------------------------------------------------------------- */
     166                 : /*      Have we been provided a geometry column?                        */
     167                 : /* -------------------------------------------------------------------- */
     168               0 :     CPLFree( pszGeomColumn );
     169               0 :     if( pszGeomCol == NULL )
     170               0 :         pszGeomColumn = NULL;
     171                 :     else
     172               0 :         pszGeomColumn = CPLStrdup( pszGeomCol );
     173                 : 
     174                 : /* -------------------------------------------------------------------- */
     175                 : /*      Get the column definitions for this table.                      */
     176                 : /* -------------------------------------------------------------------- */
     177               0 :     CPLODBCStatement oGetCol( poSession );
     178                 :     CPLErr eErr;
     179                 : 
     180               0 :     if( !oGetCol.GetColumns( pszTableName, poDS->GetCatalog(), pszSchemaName ) )
     181               0 :         return CE_Failure;
     182                 : 
     183               0 :     eErr = BuildFeatureDefn( pszLayerName, &oGetCol );
     184               0 :     if( eErr != CE_None )
     185               0 :         return eErr;
     186                 :         
     187               0 :     poFeatureDefn->SetGeomType(eType);
     188                 : 
     189               0 :     if( poFeatureDefn->GetFieldCount() == 0 &&
     190                 :         pszFIDColumn == NULL && pszGeomColumn == NULL )
     191                 :     {
     192                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     193                 :                   "No column definitions found for table '%s', layer not usable.", 
     194               0 :                   pszLayerName );
     195               0 :         return CE_Failure;
     196                 :     }
     197                 :         
     198                 : /* -------------------------------------------------------------------- */
     199                 : /*      If we got a geometry column, does it exist?  Is it binary?      */
     200                 : /* -------------------------------------------------------------------- */
     201               0 :     if( pszGeomColumn != NULL )
     202                 :     {
     203               0 :         int iColumn = oGetCol.GetColId( pszGeomColumn );
     204               0 :         if( iColumn < 0 )
     205                 :         {
     206                 :             CPLError( CE_Failure, CPLE_AppDefined, 
     207                 :                       "Column %s requested for geometry, but it does not exist.", 
     208               0 :                       pszGeomColumn );
     209               0 :             CPLFree( pszGeomColumn );
     210               0 :             pszGeomColumn = NULL;
     211                 :         }
     212                 :         else
     213                 :         {
     214               0 :             if ( nGeomColumnType < 0 )
     215                 :             {
     216                 :                 /* last attempt to identify the geometry column type */
     217               0 :                 if ( EQUAL(oGetCol.GetColTypeName( iColumn ), "geometry") )
     218               0 :                     nGeomColumnType = MSSQLCOLTYPE_GEOMETRY;
     219               0 :                 else if ( EQUAL(oGetCol.GetColTypeName( iColumn ), "geography") )
     220               0 :                     nGeomColumnType = MSSQLCOLTYPE_GEOGRAPHY;
     221               0 :                 else if ( EQUAL(oGetCol.GetColTypeName( iColumn ), "varchar") )
     222               0 :                     nGeomColumnType = MSSQLCOLTYPE_TEXT;
     223               0 :                 else if ( EQUAL(oGetCol.GetColTypeName( iColumn ), "nvarchar") )
     224               0 :                     nGeomColumnType = MSSQLCOLTYPE_TEXT;
     225               0 :                 else if ( EQUAL(oGetCol.GetColTypeName( iColumn ), "text") )
     226               0 :                     nGeomColumnType = MSSQLCOLTYPE_TEXT;
     227               0 :                 else if ( EQUAL(oGetCol.GetColTypeName( iColumn ), "ntext") )
     228               0 :                     nGeomColumnType = MSSQLCOLTYPE_TEXT;
     229               0 :                 else if ( EQUAL(oGetCol.GetColTypeName( iColumn ), "image") )
     230               0 :                     nGeomColumnType = MSSQLCOLTYPE_BINARY; 
     231                 :                 else
     232                 :                 {
     233                 :                     CPLError( CE_Failure, CPLE_AppDefined, 
     234                 :                           "Column type %s is not supported for geometry column.", 
     235               0 :                           oGetCol.GetColTypeName( iColumn ) );
     236               0 :                     CPLFree( pszGeomColumn );
     237               0 :                     pszGeomColumn = NULL;
     238                 :                 }
     239                 :             }
     240                 :         }
     241                 :     }
     242                 : 
     243                 : /* -------------------------------------------------------------------- */
     244                 : /*             Try to find out the spatial reference                    */
     245                 : /* -------------------------------------------------------------------- */
     246                 :     
     247               0 :     nSRSId = nSRId;
     248                 : 
     249               0 :     if (nSRSId < 0)
     250               0 :         nSRSId = FetchSRSId();
     251                 : 
     252               0 :     GetSpatialRef();
     253                 : 
     254               0 :     return CE_None;
     255                 : }
     256                 : 
     257                 : /************************************************************************/
     258                 : /*                         FetchSRSId()                                 */
     259                 : /************************************************************************/
     260                 : 
     261               0 : int OGRMSSQLSpatialTableLayer::FetchSRSId()
     262                 : {
     263               0 :     CPLODBCStatement oStatement = CPLODBCStatement( poDS->GetSession() );
     264                 :     oStatement.Appendf( "select srid from geometry_columns "
     265                 :                     "where f_table_schema = '%s' and f_table_name = '%s'", 
     266               0 :                     pszSchemaName, pszTableName );
     267                 : 
     268               0 :     if( oStatement.ExecuteSQL() && oStatement.Fetch() )
     269                 :     {
     270               0 :         if ( oStatement.GetColData( 0 ) )
     271               0 :             nSRSId = atoi( oStatement.GetColData( 0 ) );
     272                 :     }
     273                 :         
     274               0 :     return nSRSId;
     275                 : }
     276                 : 
     277                 : /************************************************************************/
     278                 : /*                       CreateSpatialIndex()                           */
     279                 : /*                                                                      */
     280                 : /*      Create a spatial index on the geometry column of the layer      */
     281                 : /************************************************************************/
     282                 : 
     283               0 : OGRErr OGRMSSQLSpatialTableLayer::CreateSpatialIndex()
     284                 : {
     285               0 :     CPLODBCStatement oStatement( poDS->GetSession() );
     286                 : 
     287               0 :     if (nGeomColumnType == MSSQLCOLTYPE_GEOMETRY)
     288                 :     {
     289               0 :         OGREnvelope oExt;
     290               0 :         if (GetExtent(&oExt, TRUE) != OGRERR_NONE)
     291                 :         {
     292                 :             CPLError( CE_Failure, CPLE_AppDefined, 
     293               0 :                           "Failed to get extent for spatial index." );
     294               0 :             return OGRERR_FAILURE;
     295                 :         }
     296                 : 
     297                 :         oStatement.Appendf("CREATE SPATIAL INDEX [ogr_%s_sidx] ON [dbo].[%s] ( [%s] ) "
     298                 :             "USING GEOMETRY_GRID WITH (BOUNDING_BOX =(%.15g, %.15g, %.15g, %.15g))",
     299                 :                            pszGeomColumn, poFeatureDefn->GetName(), pszGeomColumn, 
     300               0 :                            oExt.MinX, oExt.MinY, oExt.MaxX, oExt.MaxY );
     301                 :     }
     302               0 :     else if (nGeomColumnType == MSSQLCOLTYPE_GEOGRAPHY)
     303                 :     {
     304                 :         oStatement.Appendf("CREATE SPATIAL INDEX [ogr_%s_sidx] ON [dbo].[%s] ( [%s] ) "
     305                 :             "USING GEOGRAPHY_GRID",
     306               0 :                            pszGeomColumn, poFeatureDefn->GetName(), pszGeomColumn );
     307                 :     }
     308                 :     else
     309                 :     {
     310                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     311               0 :             "Spatial index is not supported on the geometry column '%s'", pszGeomColumn);
     312               0 :         return OGRERR_FAILURE;
     313                 :     }
     314                 : 
     315                 :     //poDS->GetSession()->BeginTransaction();
     316                 :     
     317               0 :     if( !oStatement.ExecuteSQL() )
     318                 :     {
     319                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     320                 :                       "Failed to create the spatial index, %s.", 
     321               0 :                       poDS->GetSession()->GetLastError());
     322               0 :         return OGRERR_FAILURE;
     323                 :     } 
     324                 : 
     325                 :     //poDS->GetSession()->CommitTransaction();
     326                 : 
     327               0 :     return OGRERR_NONE;
     328                 : }
     329                 : 
     330                 : /************************************************************************/
     331                 : /*                       DropSpatialIndex()                             */
     332                 : /*                                                                      */
     333                 : /*      Drop the spatial index on the geometry column of the layer      */
     334                 : /************************************************************************/
     335                 : 
     336               0 : void OGRMSSQLSpatialTableLayer::DropSpatialIndex()
     337                 : {
     338               0 :     CPLODBCStatement oStatement( poDS->GetSession() );
     339                 : 
     340                 :     oStatement.Appendf("IF  EXISTS (SELECT * FROM sys.indexes "
     341                 :         "WHERE object_id = OBJECT_ID(N'[dbo].[%s]') AND name = N'ogr_%s_sidx') "
     342                 :         "DROP INDEX [ogr_%s_sidx] ON [dbo].[%s]",
     343                 :                        poFeatureDefn->GetName(), pszGeomColumn, 
     344               0 :                        pszGeomColumn, poFeatureDefn->GetName() );
     345                 :     
     346                 :     //poDS->GetSession()->BeginTransaction();
     347                 : 
     348               0 :     if( !oStatement.ExecuteSQL() )
     349                 :     {
     350                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     351                 :                       "Failed to drop the spatial index, %s.", 
     352               0 :                       poDS->GetSession()->GetLastError());
     353                 :         return;
     354               0 :     } 
     355                 : 
     356                 :     //poDS->GetSession()->CommitTransaction();
     357                 : }
     358                 : 
     359                 : /************************************************************************/
     360                 : /*                            BuildFields()                             */
     361                 : /*                                                                      */
     362                 : /*      Build list of fields to fetch, performing any required          */
     363                 : /*      transformations (such as on geometry).                          */
     364                 : /************************************************************************/
     365                 : 
     366               0 : CPLString OGRMSSQLSpatialTableLayer::BuildFields()
     367                 : 
     368                 : {
     369               0 :     int i = 0;
     370               0 :     int nColumn = 0;
     371               0 :     CPLString osFieldList;
     372                 : 
     373               0 :     if( pszFIDColumn && poFeatureDefn->GetFieldIndex( pszFIDColumn ) == -1 )
     374                 :     {
     375                 :         /* Always get the FID column */
     376               0 :         osFieldList += "[";
     377               0 :         osFieldList += pszFIDColumn;
     378               0 :         osFieldList += "]";
     379               0 :         ++nColumn;
     380                 :     }
     381                 : 
     382               0 :     if( pszGeomColumn )
     383                 :     {
     384               0 :         if( nColumn > 0 )
     385               0 :             osFieldList += ", ";
     386                 : 
     387               0 :         osFieldList += "[";
     388               0 :         osFieldList += pszGeomColumn;
     389               0 :         if (nGeomColumnType == MSSQLCOLTYPE_GEOMETRY || 
     390                 :                             nGeomColumnType == MSSQLCOLTYPE_GEOGRAPHY)
     391                 :         {
     392               0 :             if ( poDS->GetGeometryFormat() == MSSQLGEOMETRY_WKB )
     393                 :             {
     394               0 :                 osFieldList += "].STAsBinary() as [";
     395               0 :                 osFieldList += pszGeomColumn;
     396                 :             }
     397               0 :             else if ( poDS->GetGeometryFormat() == MSSQLGEOMETRY_WKT )
     398                 :             {
     399               0 :                 osFieldList += "].STAsText() as [";
     400               0 :                 osFieldList += pszGeomColumn;
     401                 :             }
     402                 :         }
     403               0 :         osFieldList += "]";
     404                 : 
     405               0 :         ++nColumn;
     406                 :     }
     407                 : 
     408               0 :     if (poFeatureDefn->GetFieldCount() > 0)
     409                 :     {
     410                 :         /* need to reconstruct the field ordinals list */
     411               0 :         CPLFree(panFieldOrdinals);
     412               0 :         panFieldOrdinals = (int *) CPLMalloc( sizeof(int) * poFeatureDefn->GetFieldCount() );
     413                 : 
     414               0 :         for( i = 0; i < poFeatureDefn->GetFieldCount(); i++ )
     415                 :         {
     416               0 :             const char *pszName = poFeatureDefn->GetFieldDefn(i)->GetNameRef();
     417                 : 
     418               0 :             if( nColumn > 0 )
     419               0 :                 osFieldList += ", ";
     420                 :         
     421               0 :             osFieldList += "[";
     422               0 :             osFieldList += pszName;
     423               0 :             osFieldList += "]";
     424                 : 
     425               0 :             panFieldOrdinals[i] = nColumn;
     426                 : 
     427               0 :             ++nColumn;
     428                 :         }
     429                 :     }
     430                 : 
     431               0 :     return osFieldList;
     432                 : }
     433                 : 
     434                 : /************************************************************************/
     435                 : /*                           ClearStatement()                           */
     436                 : /************************************************************************/
     437                 : 
     438               0 : void OGRMSSQLSpatialTableLayer::ClearStatement()
     439                 : 
     440                 : {
     441               0 :     if( poStmt != NULL )
     442                 :     {
     443               0 :         delete poStmt;
     444               0 :         poStmt = NULL;
     445                 :     }
     446               0 : }
     447                 : 
     448                 : /************************************************************************/
     449                 : /*                            GetStatement()                            */
     450                 : /************************************************************************/
     451                 : 
     452               0 : CPLODBCStatement *OGRMSSQLSpatialTableLayer::GetStatement()
     453                 : 
     454                 : {
     455               0 :     if( poStmt == NULL )
     456                 :     {
     457               0 :         poStmt = BuildStatement(BuildFields());
     458               0 :         iNextShapeId = 0;
     459                 :     }
     460                 : 
     461               0 :     return poStmt;
     462                 : }
     463                 : 
     464                 : 
     465                 : /************************************************************************/
     466                 : /*                           BuildStatement()                           */
     467                 : /************************************************************************/
     468                 : 
     469               0 : CPLODBCStatement* OGRMSSQLSpatialTableLayer::BuildStatement(const char* pszColumns)
     470                 : 
     471                 : {
     472               0 :     CPLODBCStatement* poStatement = new CPLODBCStatement( poDS->GetSession() );
     473               0 :     poStatement->Append( "select " );
     474               0 :     poStatement->Append( pszColumns );
     475               0 :     poStatement->Append( " from " );
     476               0 :     poStatement->Append( pszSchemaName );
     477               0 :     poStatement->Append( "." );
     478               0 :     poStatement->Append( pszTableName );
     479                 : 
     480                 :     /* Append attribute query if we have it */
     481               0 :     if( pszQuery != NULL )
     482               0 :         poStatement->Appendf( " where %s", pszQuery );
     483                 : 
     484                 :     /* If we have a spatial filter, query on it */
     485               0 :     if ( m_poFilterGeom != NULL )
     486                 :     {
     487               0 :         if (nGeomColumnType == MSSQLCOLTYPE_GEOMETRY 
     488                 :             || nGeomColumnType == MSSQLCOLTYPE_GEOGRAPHY)
     489                 :         {
     490               0 :             if( pszQuery == NULL )
     491               0 :                 poStatement->Append( " where" );
     492                 :             else
     493               0 :                 poStatement->Append( " and" );
     494                 : 
     495               0 :             poStatement->Appendf(" [%s].STIntersects(", pszGeomColumn );
     496                 : 
     497               0 :             if (nGeomColumnType == MSSQLCOLTYPE_GEOGRAPHY)
     498               0 :                 poStatement->Append( "geography::" );
     499                 :             else
     500               0 :                 poStatement->Append( "geometry::" );
     501                 :             
     502               0 :             if ( m_sFilterEnvelope.MinX == m_sFilterEnvelope.MaxX || 
     503                 :                  m_sFilterEnvelope.MinY == m_sFilterEnvelope.MaxY)
     504                 :                 poStatement->Appendf("STGeomFromText('POINT(%.15g %.15g)',%d)) = 1", 
     505               0 :                             m_sFilterEnvelope.MinX, m_sFilterEnvelope.MinY, nSRSId >= 0? nSRSId : 0);
     506                 :             else
     507                 :                 poStatement->Appendf( "STGeomFromText('POLYGON((%.15g %.15g,%.15g %.15g,%.15g %.15g,%.15g %.15g,%.15g %.15g))',%d)) = 1", 
     508                 :                                             m_sFilterEnvelope.MinX, m_sFilterEnvelope.MinY,
     509                 :                                             m_sFilterEnvelope.MaxX, m_sFilterEnvelope.MinY, 
     510                 :                                             m_sFilterEnvelope.MaxX, m_sFilterEnvelope.MaxY,
     511                 :                                             m_sFilterEnvelope.MinX, m_sFilterEnvelope.MaxY,
     512                 :                                             m_sFilterEnvelope.MinX, m_sFilterEnvelope.MinY,
     513               0 :                                             nSRSId >= 0? nSRSId : 0 );
     514                 :         }
     515                 :         else
     516                 :         {
     517                 :             CPLError( CE_Failure, CPLE_AppDefined, 
     518               0 :                       "Spatial filter is supported only on geometry and geography column types." );
     519                 :             
     520               0 :             delete poStatement;
     521               0 :             return NULL;
     522                 :         }
     523                 :     }
     524                 : 
     525               0 :     CPLDebug( "OGR_MSSQLSpatial", "ExecuteSQL(%s)", poStatement->GetCommand() );
     526               0 :     if( poStatement->ExecuteSQL() )
     527               0 :         return poStatement;
     528                 :     else
     529                 :     {
     530               0 :         delete poStatement;
     531               0 :         return NULL;
     532                 :     }
     533                 : }
     534                 : 
     535                 : /************************************************************************/
     536                 : /*                            ResetReading()                            */
     537                 : /************************************************************************/
     538                 : 
     539               0 : void OGRMSSQLSpatialTableLayer::ResetReading()
     540                 : 
     541                 : {
     542               0 :     ClearStatement();
     543               0 :     OGRMSSQLSpatialLayer::ResetReading();
     544               0 : }
     545                 : 
     546                 : /************************************************************************/
     547                 : /*                             GetFeature()                             */
     548                 : /************************************************************************/
     549                 : 
     550               0 : OGRFeature *OGRMSSQLSpatialTableLayer::GetFeature( long nFeatureId )
     551                 : 
     552                 : {
     553               0 :     if( pszFIDColumn == NULL )
     554               0 :         return OGRMSSQLSpatialLayer::GetFeature( nFeatureId );
     555                 : 
     556               0 :     ClearStatement();
     557                 : 
     558               0 :     iNextShapeId = nFeatureId;
     559                 : 
     560               0 :     poStmt = new CPLODBCStatement( poDS->GetSession() );
     561               0 :     CPLString osFields = BuildFields();
     562                 :     poStmt->Appendf( "select %s from %s where %s = %ld", osFields.c_str(), 
     563               0 :         poFeatureDefn->GetName(), pszFIDColumn, nFeatureId );
     564                 : 
     565               0 :     if( !poStmt->ExecuteSQL() )
     566                 :     {
     567               0 :         delete poStmt;
     568               0 :         poStmt = NULL;
     569               0 :         return NULL;
     570                 :     }
     571                 : 
     572               0 :     return GetNextRawFeature();
     573                 : }
     574                 : 
     575                 : /************************************************************************/
     576                 : /*                         SetAttributeFilter()                         */
     577                 : /************************************************************************/
     578                 : 
     579               0 : OGRErr OGRMSSQLSpatialTableLayer::SetAttributeFilter( const char *pszQuery )
     580                 : 
     581                 : {
     582               0 :     if( (pszQuery == NULL && this->pszQuery == NULL)
     583                 :         || (pszQuery != NULL && this->pszQuery != NULL 
     584                 :             && EQUAL(pszQuery,this->pszQuery)) )
     585               0 :         return OGRERR_NONE;
     586                 : 
     587               0 :     CPLFree( this->pszQuery );
     588               0 :     this->pszQuery = (pszQuery) ? CPLStrdup( pszQuery ) : NULL;
     589                 : 
     590               0 :     ClearStatement();
     591                 : 
     592               0 :     return OGRERR_NONE;
     593                 : }
     594                 : 
     595                 : 
     596                 : /************************************************************************/
     597                 : /*                           TestCapability()                           */
     598                 : /************************************************************************/
     599                 : 
     600               0 : int OGRMSSQLSpatialTableLayer::TestCapability( const char * pszCap )
     601                 : 
     602                 : {
     603               0 :     if ( bUpdateAccess )
     604                 :     {
     605               0 :         if( EQUAL(pszCap,OLCSequentialWrite) || EQUAL(pszCap,OLCCreateField) )
     606               0 :             return TRUE;
     607                 : 
     608               0 :         else if( EQUAL(pszCap,OLCRandomWrite) )
     609               0 :             return (pszFIDColumn != NULL);
     610                 :     }
     611                 : 
     612                 : #if (ODBCVER >= 0x0300)
     613               0 :     if( EQUAL(pszCap,OLCTransactions) )
     614               0 :         return TRUE;
     615                 : #else
     616                 :     if( EQUAL(pszCap,OLCTransactions) )
     617                 :         return FALSE;
     618                 : #endif
     619                 :     
     620               0 :     if( EQUAL(pszCap,OLCRandomRead) )
     621               0 :         return (pszFIDColumn != NULL);
     622               0 :     else if( EQUAL(pszCap,OLCFastFeatureCount) )
     623               0 :         return TRUE;
     624                 :     else 
     625               0 :         return OGRMSSQLSpatialLayer::TestCapability( pszCap );
     626                 : }
     627                 : 
     628                 : /************************************************************************/
     629                 : /*                          GetFeatureCount()                           */
     630                 : /************************************************************************/
     631                 : 
     632               0 : int OGRMSSQLSpatialTableLayer::GetFeatureCount( int bForce )
     633                 : 
     634                 : {
     635               0 :     GetLayerDefn();
     636                 : 
     637               0 :     if( TestCapability(OLCFastFeatureCount) == FALSE )
     638               0 :         return OGRMSSQLSpatialLayer::GetFeatureCount( bForce );
     639                 : 
     640               0 :     ClearStatement();
     641                 :         
     642               0 :     CPLODBCStatement* poStatement = BuildStatement( "count(*)" );
     643                 : 
     644               0 :     if (poStatement == NULL || !poStatement->Fetch())
     645                 :     {
     646               0 :         delete poStatement;
     647               0 :         return OGRMSSQLSpatialLayer::GetFeatureCount( bForce );
     648                 :     }
     649                 : 
     650               0 :     int nRet = atoi(poStatement->GetColData( 0 ));
     651               0 :     delete poStatement;
     652               0 :     return nRet;
     653                 : }
     654                 : 
     655                 : 
     656                 : /************************************************************************/
     657                 : /*                            CreateField()                             */
     658                 : /************************************************************************/
     659                 : 
     660               0 : OGRErr OGRMSSQLSpatialTableLayer::CreateField( OGRFieldDefn *poFieldIn, 
     661                 :                                          int bApproxOK )
     662                 : 
     663                 : {
     664                 :     char                szFieldType[256];
     665               0 :     OGRFieldDefn        oField( poFieldIn );
     666                 : 
     667               0 :     GetLayerDefn();
     668                 : 
     669                 : /* -------------------------------------------------------------------- */
     670                 : /*      Do we want to "launder" the column names into MSSQL             */
     671                 : /*      friendly format?                                                */
     672                 : /* -------------------------------------------------------------------- */
     673               0 :     if( bLaunderColumnNames )
     674                 :     {
     675               0 :         char    *pszSafeName = poDS->LaunderName( oField.GetNameRef() );
     676                 : 
     677               0 :         oField.SetName( pszSafeName );
     678               0 :         CPLFree( pszSafeName );
     679                 :     }
     680                 : 
     681                 : /* -------------------------------------------------------------------- */
     682                 : /*      Identify the MSSQL type.                                        */
     683                 : /* -------------------------------------------------------------------- */
     684                 :     
     685               0 :     if( oField.GetType() == OFTInteger )
     686                 :     {
     687               0 :         if( oField.GetWidth() > 0 && bPreservePrecision )
     688               0 :             sprintf( szFieldType, "numeric(%d,0)", oField.GetWidth() );
     689                 :         else
     690               0 :             strcpy( szFieldType, "int" );
     691                 :     }
     692               0 :     else if( oField.GetType() == OFTReal )
     693                 :     {
     694               0 :         if( oField.GetWidth() > 0 && oField.GetPrecision() > 0
     695                 :             && bPreservePrecision )
     696                 :             sprintf( szFieldType, "numeric(%d,%d)",
     697               0 :                      oField.GetWidth(), oField.GetPrecision() );
     698                 :         else
     699               0 :             strcpy( szFieldType, "float" );
     700                 :     }
     701               0 :     else if( oField.GetType() == OFTString )
     702                 :     {
     703               0 :         if( oField.GetWidth() == 0 || !bPreservePrecision )
     704               0 :             strcpy( szFieldType, "varchar(MAX)" );
     705                 :         else
     706               0 :             sprintf( szFieldType, "varchar(%d)", oField.GetWidth() );
     707                 :     }
     708               0 :     else if( oField.GetType() == OFTDate )
     709                 :     {
     710               0 :         strcpy( szFieldType, "date" );
     711                 :     }
     712               0 :     else if( oField.GetType() == OFTTime )
     713                 :     {
     714               0 :         strcpy( szFieldType, "time(7)" );
     715                 :     }
     716               0 :     else if( oField.GetType() == OFTDateTime )
     717                 :     {
     718               0 :         strcpy( szFieldType, "datetime" );
     719                 :     }
     720               0 :     else if( oField.GetType() == OFTBinary )
     721                 :     {
     722               0 :         strcpy( szFieldType, "image" );
     723                 :     }
     724               0 :     else if( bApproxOK )
     725                 :     {
     726                 :         CPLError( CE_Warning, CPLE_NotSupported,
     727                 :                   "Can't create field %s with type %s on MSSQL layers.  Creating as varchar.",
     728                 :                   oField.GetNameRef(),
     729               0 :                   OGRFieldDefn::GetFieldTypeName(oField.GetType()) );
     730               0 :         strcpy( szFieldType, "varchar" );
     731                 :     }
     732                 :     else
     733                 :     {
     734                 :         CPLError( CE_Failure, CPLE_NotSupported,
     735                 :                   "Can't create field %s with type %s on MSSQL layers.",
     736                 :                   oField.GetNameRef(),
     737               0 :                   OGRFieldDefn::GetFieldTypeName(oField.GetType()) );
     738                 : 
     739               0 :         return OGRERR_FAILURE;
     740                 :     }
     741                 : 
     742                 : /* -------------------------------------------------------------------- */
     743                 : /*      Create the new field.                                           */
     744                 : /* -------------------------------------------------------------------- */
     745                 :     
     746               0 :     CPLODBCStatement oStmt( poDS->GetSession() );
     747                 :             
     748                 :     oStmt.Appendf( "ALTER TABLE [%s].[%s] ADD [%s] %s", 
     749               0 :         pszSchemaName, pszTableName, oField.GetNameRef(), szFieldType);
     750                 : 
     751               0 :     if( !oStmt.ExecuteSQL() )
     752                 :     {
     753                 :         CPLError( CE_Failure, CPLE_AppDefined,
     754                 :                     "Error creating field %s, %s", oField.GetNameRef(), 
     755               0 :                     poDS->GetSession()->GetLastError() );
     756                 : 
     757               0 :         return OGRERR_FAILURE;
     758                 :     }
     759                 : 
     760                 : /* -------------------------------------------------------------------- */
     761                 : /*      Add the field to the OGRFeatureDefn.                            */
     762                 : /* -------------------------------------------------------------------- */
     763                 : 
     764               0 :     poFeatureDefn->AddFieldDefn( &oField );
     765                 : 
     766               0 :     return OGRERR_NONE;
     767                 : }
     768                 : 
     769                 : /************************************************************************/
     770                 : /*                             SetFeature()                             */
     771                 : /*                                                                      */
     772                 : /*      SetFeature() is implemented by an UPDATE SQL command            */
     773                 : /************************************************************************/
     774                 : 
     775               0 : OGRErr OGRMSSQLSpatialTableLayer::SetFeature( OGRFeature *poFeature )
     776                 : 
     777                 : {
     778               0 :     OGRErr              eErr = OGRERR_FAILURE;
     779                 : 
     780               0 :     GetLayerDefn();
     781                 : 
     782               0 :     if( NULL == poFeature )
     783                 :     {
     784                 :         CPLError( CE_Failure, CPLE_AppDefined,
     785               0 :                   "NULL pointer to OGRFeature passed to SetFeature()." );
     786               0 :         return eErr;
     787                 :     }
     788                 : 
     789               0 :     if( poFeature->GetFID() == OGRNullFID )
     790                 :     {
     791                 :         CPLError( CE_Failure, CPLE_AppDefined,
     792               0 :                   "FID required on features given to SetFeature()." );
     793               0 :         return eErr;
     794                 :     }
     795                 : 
     796               0 :     if( !pszFIDColumn )
     797                 :     {
     798                 :         CPLError( CE_Failure, CPLE_AppDefined,
     799                 :                   "Unable to update features in tables without\n"
     800               0 :                   "a recognised FID column.");
     801               0 :         return eErr;
     802                 : 
     803                 :     }
     804                 :     
     805               0 :     ClearStatement();
     806                 : 
     807                 : /* -------------------------------------------------------------------- */
     808                 : /*      Form the UPDATE command.                                        */
     809                 : /* -------------------------------------------------------------------- */
     810               0 :     CPLODBCStatement oStmt( poDS->GetSession() );
     811                 :             
     812               0 :     oStmt.Appendf( "UPDATE [%s].[%s] SET ", pszSchemaName, pszTableName);
     813                 : 
     814               0 :     OGRMSSQLGeometryValidator oValidator(poFeature->GetGeometryRef());
     815               0 :     OGRGeometry *poGeom = oValidator.GetValidGeometryRef();
     816                 : 
     817               0 :     if (poFeature->GetGeometryRef() != poGeom)
     818                 :     {
     819                 :         CPLError( CE_Warning, CPLE_NotSupported,
     820               0 :                   "Geometry with FID = %ld has been modified.", poFeature->GetFID() );
     821                 :     }
     822                 : 
     823               0 :     int bNeedComma = FALSE;
     824               0 :     if(pszGeomColumn != NULL)
     825                 :     {
     826               0 :         char    *pszWKT = NULL;
     827                 : 
     828               0 :         if (poGeom != NULL)
     829               0 :             poGeom->exportToWkt( &pszWKT );
     830                 : 
     831               0 :         oStmt.Appendf( "[%s] = ", pszGeomColumn );
     832                 : 
     833               0 :         if( pszWKT != NULL && (nGeomColumnType == MSSQLCOLTYPE_GEOMETRY 
     834                 :             || nGeomColumnType == MSSQLCOLTYPE_GEOGRAPHY))
     835                 :         {
     836               0 :             if (nGeomColumnType == MSSQLCOLTYPE_GEOGRAPHY)
     837                 :             {
     838               0 :                 oStmt.Append( "geography::STGeomFromText(" );
     839               0 :                 OGRMSSQLAppendEscaped(&oStmt, pszWKT);
     840               0 :                 oStmt.Appendf(",%d)", nSRSId );
     841                 :             }
     842                 :             else
     843                 :             {
     844               0 :                 oStmt.Append( "geometry::STGeomFromText(" );
     845               0 :                 OGRMSSQLAppendEscaped(&oStmt, pszWKT);
     846               0 :                 oStmt.Appendf(",%d).MakeValid()", nSRSId );
     847                 :             }
     848                 :         }
     849                 :         else
     850               0 :             oStmt.Append( "null" );
     851                 : 
     852               0 :         bNeedComma = TRUE;
     853               0 :         CPLFree(pszWKT);
     854                 :     }
     855                 : 
     856               0 :     int nFieldCount = poFeatureDefn->GetFieldCount();
     857                 :     int i;
     858               0 :     for( i = 0; i < nFieldCount; i++ )
     859                 :     {
     860               0 :         if (bNeedComma)
     861               0 :             oStmt.Appendf( ", [%s] = ", poFeatureDefn->GetFieldDefn(i)->GetNameRef() );
     862                 :         else
     863                 :         {
     864               0 :             oStmt.Appendf( "[%s] = ", poFeatureDefn->GetFieldDefn(i)->GetNameRef() );
     865               0 :             bNeedComma = TRUE;
     866                 :         }
     867                 : 
     868               0 :         if( !poFeature->IsFieldSet( i ) )
     869               0 :             oStmt.Append( "null" );
     870                 :         else
     871               0 :             AppendFieldValue(&oStmt, poFeature, i);
     872                 :     }
     873                 : 
     874                 :     /* Add the WHERE clause */
     875               0 :     oStmt.Appendf( " WHERE [%s] = %ld" , pszFIDColumn, poFeature->GetFID());
     876                 : 
     877                 : /* -------------------------------------------------------------------- */
     878                 : /*      Execute the update.                                             */
     879                 : /* -------------------------------------------------------------------- */
     880                 : 
     881               0 :     if( !oStmt.ExecuteSQL() )
     882                 :     {
     883                 :         CPLError( CE_Failure, CPLE_AppDefined,
     884                 :             "Error updating feature with FID:%ld, %s", poFeature->GetFID(), 
     885               0 :                     poDS->GetSession()->GetLastError() );
     886                 : 
     887               0 :         return OGRERR_FAILURE;
     888                 :     }
     889                 :     
     890               0 :     return OGRERR_NONE;
     891                 : }
     892                 : 
     893                 : /************************************************************************/
     894                 : /*                          DeleteFeature()                             */
     895                 : /************************************************************************/
     896                 : 
     897               0 : OGRErr OGRMSSQLSpatialTableLayer::DeleteFeature( long nFID )
     898                 : 
     899                 : {
     900               0 :     GetLayerDefn();
     901                 :     
     902               0 :     if( pszFIDColumn == NULL )
     903                 :     {
     904                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     905               0 :                   "DeleteFeature() without any FID column." );
     906               0 :         return OGRERR_FAILURE;
     907                 :     }
     908                 :     
     909               0 :     if( nFID == OGRNullFID )
     910                 :     {
     911                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     912               0 :                   "DeleteFeature() with unset FID fails." );
     913               0 :         return OGRERR_FAILURE;
     914                 :     }
     915                 :     
     916               0 :     ClearStatement();
     917                 : 
     918                 : /* -------------------------------------------------------------------- */
     919                 : /*      Drop the record with this FID.                                  */
     920                 : /* -------------------------------------------------------------------- */
     921               0 :     CPLODBCStatement oStatement( poDS->GetSession() );
     922                 : 
     923                 :     oStatement.Appendf("DELETE FROM [%s] WHERE [%s] = %ld", 
     924               0 :             poFeatureDefn->GetName(), pszFIDColumn, nFID);
     925                 :     
     926               0 :     if( !oStatement.ExecuteSQL() )
     927                 :     {
     928                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     929                 :                   "Attempt to delete feature with FID %ld failed. %s", 
     930               0 :                   nFID, poDS->GetSession()->GetLastError() );
     931                 : 
     932               0 :         return OGRERR_FAILURE;
     933                 :     }
     934                 :     
     935               0 :     return OGRERR_NONE;
     936                 : }
     937                 : 
     938                 : /************************************************************************/
     939                 : /*                           CreateFeature()                            */
     940                 : /************************************************************************/
     941                 : 
     942               0 : OGRErr OGRMSSQLSpatialTableLayer::CreateFeature( OGRFeature *poFeature )
     943                 : 
     944                 : {
     945               0 :     GetLayerDefn();
     946                 : 
     947               0 :     if( NULL == poFeature )
     948                 :     {
     949                 :         CPLError( CE_Failure, CPLE_AppDefined,
     950               0 :                   "NULL pointer to OGRFeature passed to CreateFeature()." );
     951               0 :         return OGRERR_FAILURE;
     952                 :     }
     953                 :     
     954               0 :     ClearStatement();
     955                 : 
     956               0 :     CPLODBCStatement oStatement( poDS->GetSession() );
     957                 : 
     958                 :     /* the fid values are retieved from the source layer */
     959               0 :     if( poFeature->GetFID() != OGRNullFID && pszFIDColumn != NULL )
     960               0 :         oStatement.Appendf("SET IDENTITY_INSERT [%s].[%s] ON;", pszSchemaName, pszTableName );
     961                 : 
     962                 : /* -------------------------------------------------------------------- */
     963                 : /*      Form the INSERT command.                                        */
     964                 : /* -------------------------------------------------------------------- */
     965                 : 
     966               0 :     oStatement.Appendf( "INSERT INTO [%s].[%s] (", pszSchemaName, pszTableName );
     967                 : 
     968               0 :     OGRMSSQLGeometryValidator oValidator(poFeature->GetGeometryRef());
     969               0 :     OGRGeometry *poGeom = oValidator.GetValidGeometryRef();
     970                 : 
     971               0 :     if (poFeature->GetGeometryRef() != poGeom)
     972                 :     {
     973                 :         CPLError( CE_Warning, CPLE_NotSupported,
     974               0 :                   "Geometry with FID = %ld has been modified.", poFeature->GetFID() );
     975                 :     }
     976                 : 
     977               0 :     int bNeedComma = FALSE;
     978                 : 
     979               0 :     if (poGeom != NULL && pszGeomColumn != NULL)
     980                 :     {
     981               0 :         oStatement.Append( pszGeomColumn );
     982               0 :         bNeedComma = TRUE;
     983                 :     }
     984                 : 
     985               0 :     if( poFeature->GetFID() != OGRNullFID && pszFIDColumn != NULL )
     986                 :     {
     987               0 :         if (bNeedComma)
     988               0 :             oStatement.Appendf( ", [%s]", pszFIDColumn );
     989                 :         else
     990                 :         {
     991               0 :             oStatement.Appendf( "[%s]", pszFIDColumn );
     992               0 :             bNeedComma = TRUE;
     993                 :         }
     994                 :     }
     995                 : 
     996               0 :     int nFieldCount = poFeatureDefn->GetFieldCount();
     997                 :     int i;
     998               0 :     for( i = 0; i < nFieldCount; i++ )
     999                 :     {
    1000               0 :         if( !poFeature->IsFieldSet( i ) )
    1001               0 :             continue;
    1002                 : 
    1003               0 :         if (bNeedComma)
    1004               0 :             oStatement.Appendf( ", [%s]", poFeatureDefn->GetFieldDefn(i)->GetNameRef() );
    1005                 :         else
    1006                 :         {
    1007               0 :             oStatement.Appendf( "[%s]", poFeatureDefn->GetFieldDefn(i)->GetNameRef() );
    1008               0 :             bNeedComma = TRUE;
    1009                 :         }
    1010                 :     }
    1011                 : 
    1012               0 :     oStatement.Appendf( ") VALUES (" );
    1013                 : 
    1014                 :     /* Set the geometry */
    1015               0 :     bNeedComma = FALSE;
    1016               0 :     if(poGeom != NULL && pszGeomColumn != NULL)
    1017                 :     {
    1018               0 :         char    *pszWKT = NULL;
    1019                 :     
    1020                 :         //poGeom->setCoordinateDimension( nCoordDimension );
    1021                 : 
    1022               0 :         poGeom->exportToWkt( &pszWKT );
    1023                 : 
    1024               0 :         if( pszWKT != NULL && (nGeomColumnType == MSSQLCOLTYPE_GEOMETRY 
    1025                 :             || nGeomColumnType == MSSQLCOLTYPE_GEOGRAPHY))
    1026                 :         {
    1027               0 :             if (nGeomColumnType == MSSQLCOLTYPE_GEOGRAPHY)
    1028                 :             {
    1029               0 :                 oStatement.Append( "geography::STGeomFromText(" );
    1030               0 :                 OGRMSSQLAppendEscaped(&oStatement, pszWKT);
    1031               0 :                 oStatement.Appendf(",%d)", nSRSId );
    1032                 :             }
    1033                 :             else
    1034                 :             {
    1035               0 :                 oStatement.Append( "geometry::STGeomFromText(" );
    1036               0 :                 OGRMSSQLAppendEscaped(&oStatement, pszWKT);
    1037               0 :                 oStatement.Appendf(",%d).MakeValid()", nSRSId );
    1038                 :             }     
    1039                 :         }
    1040                 :         else
    1041               0 :             oStatement.Append( "null" );
    1042                 : 
    1043               0 :         bNeedComma = TRUE;
    1044               0 :         CPLFree(pszWKT);
    1045                 :     }
    1046                 : 
    1047                 :     /* Set the FID */
    1048               0 :     if( poFeature->GetFID() != OGRNullFID && pszFIDColumn != NULL )
    1049                 :     {
    1050               0 :         if (bNeedComma)
    1051               0 :             oStatement.Appendf( ", %ld", poFeature->GetFID() );
    1052                 :         else
    1053                 :         {
    1054               0 :             oStatement.Appendf( "%ld", poFeature->GetFID() );
    1055               0 :             bNeedComma = TRUE;
    1056                 :         }
    1057                 :     }
    1058                 : 
    1059               0 :     for( i = 0; i < nFieldCount; i++ )
    1060                 :     {
    1061               0 :         if( !poFeature->IsFieldSet( i ) )
    1062               0 :             continue;
    1063                 : 
    1064               0 :         if (bNeedComma)
    1065               0 :             oStatement.Append( ", " );
    1066                 :         else
    1067               0 :             bNeedComma = TRUE;
    1068                 : 
    1069               0 :         AppendFieldValue(&oStatement, poFeature, i);
    1070                 :     }
    1071                 : 
    1072               0 :     oStatement.Append( ");" );
    1073                 : 
    1074               0 :     if( poFeature->GetFID() != OGRNullFID && pszFIDColumn != NULL )
    1075               0 :         oStatement.Appendf("SET IDENTITY_INSERT [%s].[%s] OFF;", pszSchemaName, pszTableName );
    1076                 : 
    1077                 : /* -------------------------------------------------------------------- */
    1078                 : /*      Execute the insert.                                             */
    1079                 : /* -------------------------------------------------------------------- */
    1080                 :     
    1081               0 :     if( !oStatement.ExecuteSQL() )
    1082                 :     {
    1083                 :         CPLError( CE_Failure, CPLE_AppDefined, 
    1084                 :                   "INSERT command for new feature failed. %s", 
    1085               0 :                    poDS->GetSession()->GetLastError() );
    1086                 : 
    1087               0 :         return OGRERR_FAILURE;
    1088                 :     }
    1089                 : 
    1090               0 :     return OGRERR_NONE;
    1091                 : }
    1092                 : 
    1093                 : /************************************************************************/
    1094                 : /*                          AppendFieldValue()                          */
    1095                 : /*                                                                      */
    1096                 : /* Used by CreateFeature() and SetFeature() to format a                 */
    1097                 : /* non-empty field value                                                */
    1098                 : /************************************************************************/
    1099                 : 
    1100               0 : void OGRMSSQLSpatialTableLayer::AppendFieldValue(CPLODBCStatement *poStatement,
    1101                 :                                        OGRFeature* poFeature, int i)
    1102                 : {
    1103               0 :     int nOGRFieldType = poFeatureDefn->GetFieldDefn(i)->GetType();
    1104                 : 
    1105                 :     // We need special formatting for integer list values.
    1106               0 :     if(  nOGRFieldType == OFTIntegerList )
    1107                 :     {
    1108                 :         //TODO
    1109               0 :         poStatement->Append( "null" );
    1110               0 :         return;
    1111                 :     }
    1112                 : 
    1113                 :     // We need special formatting for real list values.
    1114               0 :     else if( nOGRFieldType == OFTRealList )
    1115                 :     {
    1116                 :         //TODO
    1117               0 :         poStatement->Append( "null" );
    1118               0 :         return;
    1119                 :     }
    1120                 : 
    1121                 :     // We need special formatting for string list values.
    1122               0 :     else if( nOGRFieldType == OFTStringList )
    1123                 :     {
    1124                 :         //TODO
    1125               0 :         poStatement->Append( "null" );
    1126               0 :         return;
    1127                 :     }
    1128                 : 
    1129                 :     // Binary formatting
    1130               0 :     if( nOGRFieldType == OFTBinary )
    1131                 :     {
    1132               0 :         int nLen = 0;
    1133               0 :         GByte* pabyData = poFeature->GetFieldAsBinary( i, &nLen );
    1134               0 :         char* pszBytes = GByteArrayToHexString( pabyData, nLen);
    1135               0 :         poStatement->Append( pszBytes );
    1136               0 :         CPLFree(pszBytes);
    1137               0 :         return;
    1138                 :     }
    1139                 : 
    1140                 :     // Flag indicating NULL or not-a-date date value
    1141                 :     // e.g. 0000-00-00 - there is no year 0
    1142               0 :     OGRBoolean bIsDateNull = FALSE;
    1143                 : 
    1144               0 :     const char *pszStrValue = poFeature->GetFieldAsString(i);
    1145                 : 
    1146                 :     // Check if date is NULL: 0000-00-00
    1147               0 :     if( nOGRFieldType == OFTDate )
    1148                 :     {
    1149               0 :         if( EQUALN( pszStrValue, "0000", 4 ) )
    1150                 :         {
    1151               0 :             pszStrValue = "null";
    1152               0 :             bIsDateNull = TRUE;
    1153                 :         }
    1154                 :     }
    1155               0 :     else if ( nOGRFieldType == OFTReal )
    1156                 :     {
    1157               0 :         char* pszComma = strchr((char*)pszStrValue, ',');
    1158               0 :         if (pszComma)
    1159               0 :             *pszComma = '.';
    1160                 :     }
    1161                 : 
    1162               0 :     if( nOGRFieldType != OFTInteger && nOGRFieldType != OFTReal
    1163                 :         && !bIsDateNull )
    1164                 :     {
    1165               0 :         OGRMSSQLAppendEscaped(poStatement, pszStrValue);
    1166                 :     }
    1167                 :     else
    1168                 :     {
    1169               0 :         poStatement->Append( pszStrValue );
    1170                 :     }
    1171                 : }
    1172                 : 

Generated by: LCOV version 1.7