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: 2012-04-28 Functions: 24 0 0.0 %

       1                 : /******************************************************************************
       2                 :  * $Id: ogrmssqlspatialtablelayer.cpp 23942 2012-02-11 13:55:23Z rouault $
       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 23942 2012-02-11 13:55:23Z rouault $");
      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                 :             || EQUAL(pszCap,OLCDeleteFeature) )
     607               0 :             return TRUE;
     608                 : 
     609               0 :         else if( EQUAL(pszCap,OLCRandomWrite) )
     610               0 :             return (pszFIDColumn != NULL);
     611                 :     }
     612                 : 
     613                 : #if (ODBCVER >= 0x0300)
     614               0 :     if( EQUAL(pszCap,OLCTransactions) )
     615               0 :         return TRUE;
     616                 : #else
     617                 :     if( EQUAL(pszCap,OLCTransactions) )
     618                 :         return FALSE;
     619                 : #endif
     620                 :     
     621               0 :     if( EQUAL(pszCap,OLCRandomRead) )
     622               0 :         return (pszFIDColumn != NULL);
     623               0 :     else if( EQUAL(pszCap,OLCFastFeatureCount) )
     624               0 :         return TRUE;
     625                 :     else 
     626               0 :         return OGRMSSQLSpatialLayer::TestCapability( pszCap );
     627                 : }
     628                 : 
     629                 : /************************************************************************/
     630                 : /*                          GetFeatureCount()                           */
     631                 : /************************************************************************/
     632                 : 
     633               0 : int OGRMSSQLSpatialTableLayer::GetFeatureCount( int bForce )
     634                 : 
     635                 : {
     636               0 :     GetLayerDefn();
     637                 : 
     638               0 :     if( TestCapability(OLCFastFeatureCount) == FALSE )
     639               0 :         return OGRMSSQLSpatialLayer::GetFeatureCount( bForce );
     640                 : 
     641               0 :     ClearStatement();
     642                 :         
     643               0 :     CPLODBCStatement* poStatement = BuildStatement( "count(*)" );
     644                 : 
     645               0 :     if (poStatement == NULL || !poStatement->Fetch())
     646                 :     {
     647               0 :         delete poStatement;
     648               0 :         return OGRMSSQLSpatialLayer::GetFeatureCount( bForce );
     649                 :     }
     650                 : 
     651               0 :     int nRet = atoi(poStatement->GetColData( 0 ));
     652               0 :     delete poStatement;
     653               0 :     return nRet;
     654                 : }
     655                 : 
     656                 : 
     657                 : /************************************************************************/
     658                 : /*                            CreateField()                             */
     659                 : /************************************************************************/
     660                 : 
     661               0 : OGRErr OGRMSSQLSpatialTableLayer::CreateField( OGRFieldDefn *poFieldIn, 
     662                 :                                          int bApproxOK )
     663                 : 
     664                 : {
     665                 :     char                szFieldType[256];
     666               0 :     OGRFieldDefn        oField( poFieldIn );
     667                 : 
     668               0 :     GetLayerDefn();
     669                 : 
     670                 : /* -------------------------------------------------------------------- */
     671                 : /*      Do we want to "launder" the column names into MSSQL             */
     672                 : /*      friendly format?                                                */
     673                 : /* -------------------------------------------------------------------- */
     674               0 :     if( bLaunderColumnNames )
     675                 :     {
     676               0 :         char    *pszSafeName = poDS->LaunderName( oField.GetNameRef() );
     677                 : 
     678               0 :         oField.SetName( pszSafeName );
     679               0 :         CPLFree( pszSafeName );
     680                 :     }
     681                 : 
     682                 : /* -------------------------------------------------------------------- */
     683                 : /*      Identify the MSSQL type.                                        */
     684                 : /* -------------------------------------------------------------------- */
     685                 :     
     686               0 :     if( oField.GetType() == OFTInteger )
     687                 :     {
     688               0 :         if( oField.GetWidth() > 0 && bPreservePrecision )
     689               0 :             sprintf( szFieldType, "numeric(%d,0)", oField.GetWidth() );
     690                 :         else
     691               0 :             strcpy( szFieldType, "int" );
     692                 :     }
     693               0 :     else if( oField.GetType() == OFTReal )
     694                 :     {
     695               0 :         if( oField.GetWidth() > 0 && oField.GetPrecision() > 0
     696                 :             && bPreservePrecision )
     697                 :             sprintf( szFieldType, "numeric(%d,%d)",
     698               0 :                      oField.GetWidth(), oField.GetPrecision() );
     699                 :         else
     700               0 :             strcpy( szFieldType, "float" );
     701                 :     }
     702               0 :     else if( oField.GetType() == OFTString )
     703                 :     {
     704               0 :         if( oField.GetWidth() == 0 || !bPreservePrecision )
     705               0 :             strcpy( szFieldType, "varchar(MAX)" );
     706                 :         else
     707               0 :             sprintf( szFieldType, "varchar(%d)", oField.GetWidth() );
     708                 :     }
     709               0 :     else if( oField.GetType() == OFTDate )
     710                 :     {
     711               0 :         strcpy( szFieldType, "date" );
     712                 :     }
     713               0 :     else if( oField.GetType() == OFTTime )
     714                 :     {
     715               0 :         strcpy( szFieldType, "time(7)" );
     716                 :     }
     717               0 :     else if( oField.GetType() == OFTDateTime )
     718                 :     {
     719               0 :         strcpy( szFieldType, "datetime" );
     720                 :     }
     721               0 :     else if( oField.GetType() == OFTBinary )
     722                 :     {
     723               0 :         strcpy( szFieldType, "image" );
     724                 :     }
     725               0 :     else if( bApproxOK )
     726                 :     {
     727                 :         CPLError( CE_Warning, CPLE_NotSupported,
     728                 :                   "Can't create field %s with type %s on MSSQL layers.  Creating as varchar.",
     729                 :                   oField.GetNameRef(),
     730               0 :                   OGRFieldDefn::GetFieldTypeName(oField.GetType()) );
     731               0 :         strcpy( szFieldType, "varchar" );
     732                 :     }
     733                 :     else
     734                 :     {
     735                 :         CPLError( CE_Failure, CPLE_NotSupported,
     736                 :                   "Can't create field %s with type %s on MSSQL layers.",
     737                 :                   oField.GetNameRef(),
     738               0 :                   OGRFieldDefn::GetFieldTypeName(oField.GetType()) );
     739                 : 
     740               0 :         return OGRERR_FAILURE;
     741                 :     }
     742                 : 
     743                 : /* -------------------------------------------------------------------- */
     744                 : /*      Create the new field.                                           */
     745                 : /* -------------------------------------------------------------------- */
     746                 :     
     747               0 :     CPLODBCStatement oStmt( poDS->GetSession() );
     748                 :             
     749                 :     oStmt.Appendf( "ALTER TABLE [%s].[%s] ADD [%s] %s", 
     750               0 :         pszSchemaName, pszTableName, oField.GetNameRef(), szFieldType);
     751                 : 
     752               0 :     if( !oStmt.ExecuteSQL() )
     753                 :     {
     754                 :         CPLError( CE_Failure, CPLE_AppDefined,
     755                 :                     "Error creating field %s, %s", oField.GetNameRef(), 
     756               0 :                     poDS->GetSession()->GetLastError() );
     757                 : 
     758               0 :         return OGRERR_FAILURE;
     759                 :     }
     760                 : 
     761                 : /* -------------------------------------------------------------------- */
     762                 : /*      Add the field to the OGRFeatureDefn.                            */
     763                 : /* -------------------------------------------------------------------- */
     764                 : 
     765               0 :     poFeatureDefn->AddFieldDefn( &oField );
     766                 : 
     767               0 :     return OGRERR_NONE;
     768                 : }
     769                 : 
     770                 : /************************************************************************/
     771                 : /*                             SetFeature()                             */
     772                 : /*                                                                      */
     773                 : /*      SetFeature() is implemented by an UPDATE SQL command            */
     774                 : /************************************************************************/
     775                 : 
     776               0 : OGRErr OGRMSSQLSpatialTableLayer::SetFeature( OGRFeature *poFeature )
     777                 : 
     778                 : {
     779               0 :     OGRErr              eErr = OGRERR_FAILURE;
     780                 : 
     781               0 :     GetLayerDefn();
     782                 : 
     783               0 :     if( NULL == poFeature )
     784                 :     {
     785                 :         CPLError( CE_Failure, CPLE_AppDefined,
     786               0 :                   "NULL pointer to OGRFeature passed to SetFeature()." );
     787               0 :         return eErr;
     788                 :     }
     789                 : 
     790               0 :     if( poFeature->GetFID() == OGRNullFID )
     791                 :     {
     792                 :         CPLError( CE_Failure, CPLE_AppDefined,
     793               0 :                   "FID required on features given to SetFeature()." );
     794               0 :         return eErr;
     795                 :     }
     796                 : 
     797               0 :     if( !pszFIDColumn )
     798                 :     {
     799                 :         CPLError( CE_Failure, CPLE_AppDefined,
     800                 :                   "Unable to update features in tables without\n"
     801               0 :                   "a recognised FID column.");
     802               0 :         return eErr;
     803                 : 
     804                 :     }
     805                 :     
     806               0 :     ClearStatement();
     807                 : 
     808                 : /* -------------------------------------------------------------------- */
     809                 : /*      Form the UPDATE command.                                        */
     810                 : /* -------------------------------------------------------------------- */
     811               0 :     CPLODBCStatement oStmt( poDS->GetSession() );
     812                 :             
     813               0 :     oStmt.Appendf( "UPDATE [%s].[%s] SET ", pszSchemaName, pszTableName);
     814                 : 
     815               0 :     OGRMSSQLGeometryValidator oValidator(poFeature->GetGeometryRef());
     816               0 :     OGRGeometry *poGeom = oValidator.GetValidGeometryRef();
     817                 : 
     818               0 :     if (poFeature->GetGeometryRef() != poGeom)
     819                 :     {
     820                 :         CPLError( CE_Warning, CPLE_NotSupported,
     821               0 :                   "Geometry with FID = %ld has been modified.", poFeature->GetFID() );
     822                 :     }
     823                 : 
     824               0 :     int bNeedComma = FALSE;
     825               0 :     if(pszGeomColumn != NULL)
     826                 :     {
     827               0 :         char    *pszWKT = NULL;
     828                 : 
     829               0 :         if (poGeom != NULL)
     830               0 :             poGeom->exportToWkt( &pszWKT );
     831                 : 
     832               0 :         oStmt.Appendf( "[%s] = ", pszGeomColumn );
     833                 : 
     834               0 :         if( pszWKT != NULL && (nGeomColumnType == MSSQLCOLTYPE_GEOMETRY 
     835                 :             || nGeomColumnType == MSSQLCOLTYPE_GEOGRAPHY))
     836                 :         {
     837               0 :             if (nGeomColumnType == MSSQLCOLTYPE_GEOGRAPHY)
     838                 :             {
     839               0 :                 oStmt.Append( "geography::STGeomFromText(" );
     840               0 :                 OGRMSSQLAppendEscaped(&oStmt, pszWKT);
     841               0 :                 oStmt.Appendf(",%d)", nSRSId );
     842                 :             }
     843                 :             else
     844                 :             {
     845               0 :                 oStmt.Append( "geometry::STGeomFromText(" );
     846               0 :                 OGRMSSQLAppendEscaped(&oStmt, pszWKT);
     847               0 :                 oStmt.Appendf(",%d).MakeValid()", nSRSId );
     848                 :             }
     849                 :         }
     850                 :         else
     851               0 :             oStmt.Append( "null" );
     852                 : 
     853               0 :         bNeedComma = TRUE;
     854               0 :         CPLFree(pszWKT);
     855                 :     }
     856                 : 
     857               0 :     int nFieldCount = poFeatureDefn->GetFieldCount();
     858                 :     int i;
     859               0 :     for( i = 0; i < nFieldCount; i++ )
     860                 :     {
     861               0 :         if (bNeedComma)
     862               0 :             oStmt.Appendf( ", [%s] = ", poFeatureDefn->GetFieldDefn(i)->GetNameRef() );
     863                 :         else
     864                 :         {
     865               0 :             oStmt.Appendf( "[%s] = ", poFeatureDefn->GetFieldDefn(i)->GetNameRef() );
     866               0 :             bNeedComma = TRUE;
     867                 :         }
     868                 : 
     869               0 :         if( !poFeature->IsFieldSet( i ) )
     870               0 :             oStmt.Append( "null" );
     871                 :         else
     872               0 :             AppendFieldValue(&oStmt, poFeature, i);
     873                 :     }
     874                 : 
     875                 :     /* Add the WHERE clause */
     876               0 :     oStmt.Appendf( " WHERE [%s] = %ld" , pszFIDColumn, poFeature->GetFID());
     877                 : 
     878                 : /* -------------------------------------------------------------------- */
     879                 : /*      Execute the update.                                             */
     880                 : /* -------------------------------------------------------------------- */
     881                 : 
     882               0 :     if( !oStmt.ExecuteSQL() )
     883                 :     {
     884                 :         CPLError( CE_Failure, CPLE_AppDefined,
     885                 :             "Error updating feature with FID:%ld, %s", poFeature->GetFID(), 
     886               0 :                     poDS->GetSession()->GetLastError() );
     887                 : 
     888               0 :         return OGRERR_FAILURE;
     889                 :     }
     890                 :     
     891               0 :     return OGRERR_NONE;
     892                 : }
     893                 : 
     894                 : /************************************************************************/
     895                 : /*                          DeleteFeature()                             */
     896                 : /************************************************************************/
     897                 : 
     898               0 : OGRErr OGRMSSQLSpatialTableLayer::DeleteFeature( long nFID )
     899                 : 
     900                 : {
     901               0 :     GetLayerDefn();
     902                 :     
     903               0 :     if( pszFIDColumn == NULL )
     904                 :     {
     905                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     906               0 :                   "DeleteFeature() without any FID column." );
     907               0 :         return OGRERR_FAILURE;
     908                 :     }
     909                 :     
     910               0 :     if( nFID == OGRNullFID )
     911                 :     {
     912                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     913               0 :                   "DeleteFeature() with unset FID fails." );
     914               0 :         return OGRERR_FAILURE;
     915                 :     }
     916                 :     
     917               0 :     ClearStatement();
     918                 : 
     919                 : /* -------------------------------------------------------------------- */
     920                 : /*      Drop the record with this FID.                                  */
     921                 : /* -------------------------------------------------------------------- */
     922               0 :     CPLODBCStatement oStatement( poDS->GetSession() );
     923                 : 
     924                 :     oStatement.Appendf("DELETE FROM [%s] WHERE [%s] = %ld", 
     925               0 :             poFeatureDefn->GetName(), pszFIDColumn, nFID);
     926                 :     
     927               0 :     if( !oStatement.ExecuteSQL() )
     928                 :     {
     929                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     930                 :                   "Attempt to delete feature with FID %ld failed. %s", 
     931               0 :                   nFID, poDS->GetSession()->GetLastError() );
     932                 : 
     933               0 :         return OGRERR_FAILURE;
     934                 :     }
     935                 :     
     936               0 :     return OGRERR_NONE;
     937                 : }
     938                 : 
     939                 : /************************************************************************/
     940                 : /*                           CreateFeature()                            */
     941                 : /************************************************************************/
     942                 : 
     943               0 : OGRErr OGRMSSQLSpatialTableLayer::CreateFeature( OGRFeature *poFeature )
     944                 : 
     945                 : {
     946               0 :     GetLayerDefn();
     947                 : 
     948               0 :     if( NULL == poFeature )
     949                 :     {
     950                 :         CPLError( CE_Failure, CPLE_AppDefined,
     951               0 :                   "NULL pointer to OGRFeature passed to CreateFeature()." );
     952               0 :         return OGRERR_FAILURE;
     953                 :     }
     954                 :     
     955               0 :     ClearStatement();
     956                 : 
     957               0 :     CPLODBCStatement oStatement( poDS->GetSession() );
     958                 : 
     959                 :     /* the fid values are retieved from the source layer */
     960               0 :     if( poFeature->GetFID() != OGRNullFID && pszFIDColumn != NULL )
     961               0 :         oStatement.Appendf("SET IDENTITY_INSERT [%s].[%s] ON;", pszSchemaName, pszTableName );
     962                 : 
     963                 : /* -------------------------------------------------------------------- */
     964                 : /*      Form the INSERT command.                                        */
     965                 : /* -------------------------------------------------------------------- */
     966                 : 
     967               0 :     oStatement.Appendf( "INSERT INTO [%s].[%s] (", pszSchemaName, pszTableName );
     968                 : 
     969               0 :     OGRMSSQLGeometryValidator oValidator(poFeature->GetGeometryRef());
     970               0 :     OGRGeometry *poGeom = oValidator.GetValidGeometryRef();
     971                 : 
     972               0 :     if (poFeature->GetGeometryRef() != poGeom)
     973                 :     {
     974                 :         CPLError( CE_Warning, CPLE_NotSupported,
     975               0 :                   "Geometry with FID = %ld has been modified.", poFeature->GetFID() );
     976                 :     }
     977                 : 
     978               0 :     int bNeedComma = FALSE;
     979                 : 
     980               0 :     if (poGeom != NULL && pszGeomColumn != NULL)
     981                 :     {
     982               0 :         oStatement.Append( pszGeomColumn );
     983               0 :         bNeedComma = TRUE;
     984                 :     }
     985                 : 
     986               0 :     if( poFeature->GetFID() != OGRNullFID && pszFIDColumn != NULL )
     987                 :     {
     988               0 :         if (bNeedComma)
     989               0 :             oStatement.Appendf( ", [%s]", pszFIDColumn );
     990                 :         else
     991                 :         {
     992               0 :             oStatement.Appendf( "[%s]", pszFIDColumn );
     993               0 :             bNeedComma = TRUE;
     994                 :         }
     995                 :     }
     996                 : 
     997               0 :     int nFieldCount = poFeatureDefn->GetFieldCount();
     998                 :     int i;
     999               0 :     for( i = 0; i < nFieldCount; i++ )
    1000                 :     {
    1001               0 :         if( !poFeature->IsFieldSet( i ) )
    1002               0 :             continue;
    1003                 : 
    1004               0 :         if (bNeedComma)
    1005               0 :             oStatement.Appendf( ", [%s]", poFeatureDefn->GetFieldDefn(i)->GetNameRef() );
    1006                 :         else
    1007                 :         {
    1008               0 :             oStatement.Appendf( "[%s]", poFeatureDefn->GetFieldDefn(i)->GetNameRef() );
    1009               0 :             bNeedComma = TRUE;
    1010                 :         }
    1011                 :     }
    1012                 : 
    1013               0 :     oStatement.Appendf( ") VALUES (" );
    1014                 : 
    1015                 :     /* Set the geometry */
    1016               0 :     bNeedComma = FALSE;
    1017               0 :     if(poGeom != NULL && pszGeomColumn != NULL)
    1018                 :     {
    1019               0 :         char    *pszWKT = NULL;
    1020                 :     
    1021                 :         //poGeom->setCoordinateDimension( nCoordDimension );
    1022                 : 
    1023               0 :         poGeom->exportToWkt( &pszWKT );
    1024                 : 
    1025               0 :         if( pszWKT != NULL && (nGeomColumnType == MSSQLCOLTYPE_GEOMETRY 
    1026                 :             || nGeomColumnType == MSSQLCOLTYPE_GEOGRAPHY))
    1027                 :         {
    1028               0 :             if (nGeomColumnType == MSSQLCOLTYPE_GEOGRAPHY)
    1029                 :             {
    1030               0 :                 oStatement.Append( "geography::STGeomFromText(" );
    1031               0 :                 OGRMSSQLAppendEscaped(&oStatement, pszWKT);
    1032               0 :                 oStatement.Appendf(",%d)", nSRSId );
    1033                 :             }
    1034                 :             else
    1035                 :             {
    1036               0 :                 oStatement.Append( "geometry::STGeomFromText(" );
    1037               0 :                 OGRMSSQLAppendEscaped(&oStatement, pszWKT);
    1038               0 :                 oStatement.Appendf(",%d).MakeValid()", nSRSId );
    1039                 :             }     
    1040                 :         }
    1041                 :         else
    1042               0 :             oStatement.Append( "null" );
    1043                 : 
    1044               0 :         bNeedComma = TRUE;
    1045               0 :         CPLFree(pszWKT);
    1046                 :     }
    1047                 : 
    1048                 :     /* Set the FID */
    1049               0 :     if( poFeature->GetFID() != OGRNullFID && pszFIDColumn != NULL )
    1050                 :     {
    1051               0 :         if (bNeedComma)
    1052               0 :             oStatement.Appendf( ", %ld", poFeature->GetFID() );
    1053                 :         else
    1054                 :         {
    1055               0 :             oStatement.Appendf( "%ld", poFeature->GetFID() );
    1056               0 :             bNeedComma = TRUE;
    1057                 :         }
    1058                 :     }
    1059                 : 
    1060               0 :     for( i = 0; i < nFieldCount; i++ )
    1061                 :     {
    1062               0 :         if( !poFeature->IsFieldSet( i ) )
    1063               0 :             continue;
    1064                 : 
    1065               0 :         if (bNeedComma)
    1066               0 :             oStatement.Append( ", " );
    1067                 :         else
    1068               0 :             bNeedComma = TRUE;
    1069                 : 
    1070               0 :         AppendFieldValue(&oStatement, poFeature, i);
    1071                 :     }
    1072                 : 
    1073               0 :     oStatement.Append( ");" );
    1074                 : 
    1075               0 :     if( poFeature->GetFID() != OGRNullFID && pszFIDColumn != NULL )
    1076               0 :         oStatement.Appendf("SET IDENTITY_INSERT [%s].[%s] OFF;", pszSchemaName, pszTableName );
    1077                 : 
    1078                 : /* -------------------------------------------------------------------- */
    1079                 : /*      Execute the insert.                                             */
    1080                 : /* -------------------------------------------------------------------- */
    1081                 :     
    1082               0 :     if( !oStatement.ExecuteSQL() )
    1083                 :     {
    1084                 :         CPLError( CE_Failure, CPLE_AppDefined, 
    1085                 :                   "INSERT command for new feature failed. %s", 
    1086               0 :                    poDS->GetSession()->GetLastError() );
    1087                 : 
    1088               0 :         return OGRERR_FAILURE;
    1089                 :     }
    1090                 : 
    1091               0 :     return OGRERR_NONE;
    1092                 : }
    1093                 : 
    1094                 : /************************************************************************/
    1095                 : /*                          AppendFieldValue()                          */
    1096                 : /*                                                                      */
    1097                 : /* Used by CreateFeature() and SetFeature() to format a                 */
    1098                 : /* non-empty field value                                                */
    1099                 : /************************************************************************/
    1100                 : 
    1101               0 : void OGRMSSQLSpatialTableLayer::AppendFieldValue(CPLODBCStatement *poStatement,
    1102                 :                                        OGRFeature* poFeature, int i)
    1103                 : {
    1104               0 :     int nOGRFieldType = poFeatureDefn->GetFieldDefn(i)->GetType();
    1105                 : 
    1106                 :     // We need special formatting for integer list values.
    1107               0 :     if(  nOGRFieldType == OFTIntegerList )
    1108                 :     {
    1109                 :         //TODO
    1110               0 :         poStatement->Append( "null" );
    1111               0 :         return;
    1112                 :     }
    1113                 : 
    1114                 :     // We need special formatting for real list values.
    1115               0 :     else if( nOGRFieldType == OFTRealList )
    1116                 :     {
    1117                 :         //TODO
    1118               0 :         poStatement->Append( "null" );
    1119               0 :         return;
    1120                 :     }
    1121                 : 
    1122                 :     // We need special formatting for string list values.
    1123               0 :     else if( nOGRFieldType == OFTStringList )
    1124                 :     {
    1125                 :         //TODO
    1126               0 :         poStatement->Append( "null" );
    1127               0 :         return;
    1128                 :     }
    1129                 : 
    1130                 :     // Binary formatting
    1131               0 :     if( nOGRFieldType == OFTBinary )
    1132                 :     {
    1133               0 :         int nLen = 0;
    1134               0 :         GByte* pabyData = poFeature->GetFieldAsBinary( i, &nLen );
    1135               0 :         char* pszBytes = GByteArrayToHexString( pabyData, nLen);
    1136               0 :         poStatement->Append( pszBytes );
    1137               0 :         CPLFree(pszBytes);
    1138               0 :         return;
    1139                 :     }
    1140                 : 
    1141                 :     // Flag indicating NULL or not-a-date date value
    1142                 :     // e.g. 0000-00-00 - there is no year 0
    1143               0 :     OGRBoolean bIsDateNull = FALSE;
    1144                 : 
    1145               0 :     const char *pszStrValue = poFeature->GetFieldAsString(i);
    1146                 : 
    1147                 :     // Check if date is NULL: 0000-00-00
    1148               0 :     if( nOGRFieldType == OFTDate )
    1149                 :     {
    1150               0 :         if( EQUALN( pszStrValue, "0000", 4 ) )
    1151                 :         {
    1152               0 :             pszStrValue = "null";
    1153               0 :             bIsDateNull = TRUE;
    1154                 :         }
    1155                 :     }
    1156               0 :     else if ( nOGRFieldType == OFTReal )
    1157                 :     {
    1158               0 :         char* pszComma = strchr((char*)pszStrValue, ',');
    1159               0 :         if (pszComma)
    1160               0 :             *pszComma = '.';
    1161                 :     }
    1162                 : 
    1163               0 :     if( nOGRFieldType != OFTInteger && nOGRFieldType != OFTReal
    1164                 :         && !bIsDateNull )
    1165                 :     {
    1166               0 :         OGRMSSQLAppendEscaped(poStatement, pszStrValue);
    1167                 :     }
    1168                 :     else
    1169                 :     {
    1170               0 :         poStatement->Append( pszStrValue );
    1171                 :     }
    1172                 : }
    1173                 : 

Generated by: LCOV version 1.7