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

       1                 : /******************************************************************************
       2                 :  * $Id: ogrmssqlspatialtablelayer.cpp 24967 2012-09-24 21:51:46Z 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 24967 2012-09-24 21:51:46Z 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 += "].AsTextZM() as [";
     400               0 :                 osFieldList += pszGeomColumn;
     401                 :             }
     402               0 :             else if ( poDS->GetGeometryFormat() == MSSQLGEOMETRY_WKBZM )
     403                 :             {
     404                 :                 /* SQL Server 2012 */
     405               0 :                 osFieldList += "].AsBinaryZM() as [";
     406               0 :                 osFieldList += pszGeomColumn;
     407                 :             }
     408                 :         }
     409               0 :         osFieldList += "]";
     410                 : 
     411               0 :         ++nColumn;
     412                 :     }
     413                 : 
     414               0 :     if (poFeatureDefn->GetFieldCount() > 0)
     415                 :     {
     416                 :         /* need to reconstruct the field ordinals list */
     417               0 :         CPLFree(panFieldOrdinals);
     418               0 :         panFieldOrdinals = (int *) CPLMalloc( sizeof(int) * poFeatureDefn->GetFieldCount() );
     419                 : 
     420               0 :         for( i = 0; i < poFeatureDefn->GetFieldCount(); i++ )
     421                 :         {
     422               0 :             const char *pszName = poFeatureDefn->GetFieldDefn(i)->GetNameRef();
     423                 : 
     424               0 :             if( nColumn > 0 )
     425               0 :                 osFieldList += ", ";
     426                 :         
     427               0 :             osFieldList += "[";
     428               0 :             osFieldList += pszName;
     429               0 :             osFieldList += "]";
     430                 : 
     431               0 :             panFieldOrdinals[i] = nColumn;
     432                 : 
     433               0 :             ++nColumn;
     434                 :         }
     435                 :     }
     436                 : 
     437               0 :     return osFieldList;
     438                 : }
     439                 : 
     440                 : /************************************************************************/
     441                 : /*                           ClearStatement()                           */
     442                 : /************************************************************************/
     443                 : 
     444               0 : void OGRMSSQLSpatialTableLayer::ClearStatement()
     445                 : 
     446                 : {
     447               0 :     if( poStmt != NULL )
     448                 :     {
     449               0 :         delete poStmt;
     450               0 :         poStmt = NULL;
     451                 :     }
     452               0 : }
     453                 : 
     454                 : /************************************************************************/
     455                 : /*                            GetStatement()                            */
     456                 : /************************************************************************/
     457                 : 
     458               0 : CPLODBCStatement *OGRMSSQLSpatialTableLayer::GetStatement()
     459                 : 
     460                 : {
     461               0 :     if( poStmt == NULL )
     462                 :     {
     463               0 :         poStmt = BuildStatement(BuildFields());
     464               0 :         iNextShapeId = 0;
     465                 :     }
     466                 : 
     467               0 :     return poStmt;
     468                 : }
     469                 : 
     470                 : 
     471                 : /************************************************************************/
     472                 : /*                           BuildStatement()                           */
     473                 : /************************************************************************/
     474                 : 
     475               0 : CPLODBCStatement* OGRMSSQLSpatialTableLayer::BuildStatement(const char* pszColumns)
     476                 : 
     477                 : {
     478               0 :     CPLODBCStatement* poStatement = new CPLODBCStatement( poDS->GetSession() );
     479               0 :     poStatement->Append( "select " );
     480               0 :     poStatement->Append( pszColumns );
     481               0 :     poStatement->Append( " from " );
     482               0 :     poStatement->Append( pszSchemaName );
     483               0 :     poStatement->Append( "." );
     484               0 :     poStatement->Append( pszTableName );
     485                 : 
     486                 :     /* Append attribute query if we have it */
     487               0 :     if( pszQuery != NULL )
     488               0 :         poStatement->Appendf( " where (%s)", pszQuery );
     489                 : 
     490                 :     /* If we have a spatial filter, query on it */
     491               0 :     if ( m_poFilterGeom != NULL )
     492                 :     {
     493               0 :         if (nGeomColumnType == MSSQLCOLTYPE_GEOMETRY 
     494                 :             || nGeomColumnType == MSSQLCOLTYPE_GEOGRAPHY)
     495                 :         {
     496               0 :             if( pszQuery == NULL )
     497               0 :                 poStatement->Append( " where" );
     498                 :             else
     499               0 :                 poStatement->Append( " and" );
     500                 : 
     501               0 :             poStatement->Appendf(" [%s].STIntersects(", pszGeomColumn );
     502                 : 
     503               0 :             if (nGeomColumnType == MSSQLCOLTYPE_GEOGRAPHY)
     504               0 :                 poStatement->Append( "geography::" );
     505                 :             else
     506               0 :                 poStatement->Append( "geometry::" );
     507                 :             
     508               0 :             if ( m_sFilterEnvelope.MinX == m_sFilterEnvelope.MaxX || 
     509                 :                  m_sFilterEnvelope.MinY == m_sFilterEnvelope.MaxY)
     510                 :                 poStatement->Appendf("STGeomFromText('POINT(%.15g %.15g)',%d)) = 1", 
     511               0 :                             m_sFilterEnvelope.MinX, m_sFilterEnvelope.MinY, nSRSId >= 0? nSRSId : 0);
     512                 :             else
     513                 :                 poStatement->Appendf( "STGeomFromText('POLYGON((%.15g %.15g,%.15g %.15g,%.15g %.15g,%.15g %.15g,%.15g %.15g))',%d)) = 1", 
     514                 :                                             m_sFilterEnvelope.MinX, m_sFilterEnvelope.MinY,
     515                 :                                             m_sFilterEnvelope.MaxX, m_sFilterEnvelope.MinY, 
     516                 :                                             m_sFilterEnvelope.MaxX, m_sFilterEnvelope.MaxY,
     517                 :                                             m_sFilterEnvelope.MinX, m_sFilterEnvelope.MaxY,
     518                 :                                             m_sFilterEnvelope.MinX, m_sFilterEnvelope.MinY,
     519               0 :                                             nSRSId >= 0? nSRSId : 0 );
     520                 :         }
     521                 :         else
     522                 :         {
     523                 :             CPLError( CE_Failure, CPLE_AppDefined, 
     524               0 :                       "Spatial filter is supported only on geometry and geography column types." );
     525                 :             
     526               0 :             delete poStatement;
     527               0 :             return NULL;
     528                 :         }
     529                 :     }
     530                 : 
     531               0 :     CPLDebug( "OGR_MSSQLSpatial", "ExecuteSQL(%s)", poStatement->GetCommand() );
     532               0 :     if( poStatement->ExecuteSQL() )
     533               0 :         return poStatement;
     534                 :     else
     535                 :     {
     536               0 :         delete poStatement;
     537               0 :         return NULL;
     538                 :     }
     539                 : }
     540                 : 
     541                 : /************************************************************************/
     542                 : /*                            ResetReading()                            */
     543                 : /************************************************************************/
     544                 : 
     545               0 : void OGRMSSQLSpatialTableLayer::ResetReading()
     546                 : 
     547                 : {
     548               0 :     ClearStatement();
     549               0 :     OGRMSSQLSpatialLayer::ResetReading();
     550               0 : }
     551                 : 
     552                 : /************************************************************************/
     553                 : /*                             GetFeature()                             */
     554                 : /************************************************************************/
     555                 : 
     556               0 : OGRFeature *OGRMSSQLSpatialTableLayer::GetFeature( long nFeatureId )
     557                 : 
     558                 : {
     559               0 :     if( pszFIDColumn == NULL )
     560               0 :         return OGRMSSQLSpatialLayer::GetFeature( nFeatureId );
     561                 : 
     562               0 :     ClearStatement();
     563                 : 
     564               0 :     iNextShapeId = nFeatureId;
     565                 : 
     566               0 :     poStmt = new CPLODBCStatement( poDS->GetSession() );
     567               0 :     CPLString osFields = BuildFields();
     568                 :     poStmt->Appendf( "select %s from %s where %s = %ld", osFields.c_str(), 
     569               0 :         poFeatureDefn->GetName(), pszFIDColumn, nFeatureId );
     570                 : 
     571               0 :     if( !poStmt->ExecuteSQL() )
     572                 :     {
     573               0 :         delete poStmt;
     574               0 :         poStmt = NULL;
     575               0 :         return NULL;
     576                 :     }
     577                 : 
     578               0 :     return GetNextRawFeature();
     579                 : }
     580                 : 
     581                 : /************************************************************************/
     582                 : /*                         SetAttributeFilter()                         */
     583                 : /************************************************************************/
     584                 : 
     585               0 : OGRErr OGRMSSQLSpatialTableLayer::SetAttributeFilter( const char *pszQuery )
     586                 : 
     587                 : {
     588               0 :     if( (pszQuery == NULL && this->pszQuery == NULL)
     589                 :         || (pszQuery != NULL && this->pszQuery != NULL 
     590                 :             && EQUAL(pszQuery,this->pszQuery)) )
     591               0 :         return OGRERR_NONE;
     592                 : 
     593               0 :     CPLFree( this->pszQuery );
     594               0 :     this->pszQuery = (pszQuery) ? CPLStrdup( pszQuery ) : NULL;
     595                 : 
     596               0 :     ClearStatement();
     597                 : 
     598               0 :     return OGRERR_NONE;
     599                 : }
     600                 : 
     601                 : 
     602                 : /************************************************************************/
     603                 : /*                           TestCapability()                           */
     604                 : /************************************************************************/
     605                 : 
     606               0 : int OGRMSSQLSpatialTableLayer::TestCapability( const char * pszCap )
     607                 : 
     608                 : {
     609               0 :     if ( bUpdateAccess )
     610                 :     {
     611               0 :         if( EQUAL(pszCap,OLCSequentialWrite) || EQUAL(pszCap,OLCCreateField)
     612                 :             || EQUAL(pszCap,OLCDeleteFeature) )
     613               0 :             return TRUE;
     614                 : 
     615               0 :         else if( EQUAL(pszCap,OLCRandomWrite) )
     616               0 :             return (pszFIDColumn != NULL);
     617                 :     }
     618                 : 
     619                 : #if (ODBCVER >= 0x0300)
     620               0 :     if( EQUAL(pszCap,OLCTransactions) )
     621               0 :         return TRUE;
     622                 : #else
     623                 :     if( EQUAL(pszCap,OLCTransactions) )
     624                 :         return FALSE;
     625                 : #endif
     626                 :     
     627               0 :     if( EQUAL(pszCap,OLCRandomRead) )
     628               0 :         return (pszFIDColumn != NULL);
     629               0 :     else if( EQUAL(pszCap,OLCFastFeatureCount) )
     630               0 :         return TRUE;
     631                 :     else 
     632               0 :         return OGRMSSQLSpatialLayer::TestCapability( pszCap );
     633                 : }
     634                 : 
     635                 : /************************************************************************/
     636                 : /*                          GetFeatureCount()                           */
     637                 : /************************************************************************/
     638                 : 
     639               0 : int OGRMSSQLSpatialTableLayer::GetFeatureCount( int bForce )
     640                 : 
     641                 : {
     642               0 :     GetLayerDefn();
     643                 : 
     644               0 :     if( TestCapability(OLCFastFeatureCount) == FALSE )
     645               0 :         return OGRMSSQLSpatialLayer::GetFeatureCount( bForce );
     646                 : 
     647               0 :     ClearStatement();
     648                 :         
     649               0 :     CPLODBCStatement* poStatement = BuildStatement( "count(*)" );
     650                 : 
     651               0 :     if (poStatement == NULL || !poStatement->Fetch())
     652                 :     {
     653               0 :         delete poStatement;
     654               0 :         return OGRMSSQLSpatialLayer::GetFeatureCount( bForce );
     655                 :     }
     656                 : 
     657               0 :     int nRet = atoi(poStatement->GetColData( 0 ));
     658               0 :     delete poStatement;
     659               0 :     return nRet;
     660                 : }
     661                 : 
     662                 : 
     663                 : /************************************************************************/
     664                 : /*                            CreateField()                             */
     665                 : /************************************************************************/
     666                 : 
     667               0 : OGRErr OGRMSSQLSpatialTableLayer::CreateField( OGRFieldDefn *poFieldIn, 
     668                 :                                          int bApproxOK )
     669                 : 
     670                 : {
     671                 :     char                szFieldType[256];
     672               0 :     OGRFieldDefn        oField( poFieldIn );
     673                 : 
     674               0 :     GetLayerDefn();
     675                 : 
     676                 : /* -------------------------------------------------------------------- */
     677                 : /*      Do we want to "launder" the column names into MSSQL             */
     678                 : /*      friendly format?                                                */
     679                 : /* -------------------------------------------------------------------- */
     680               0 :     if( bLaunderColumnNames )
     681                 :     {
     682               0 :         char    *pszSafeName = poDS->LaunderName( oField.GetNameRef() );
     683                 : 
     684               0 :         oField.SetName( pszSafeName );
     685               0 :         CPLFree( pszSafeName );
     686                 :     }
     687                 : 
     688                 : /* -------------------------------------------------------------------- */
     689                 : /*      Identify the MSSQL type.                                        */
     690                 : /* -------------------------------------------------------------------- */
     691                 :     
     692               0 :     if( oField.GetType() == OFTInteger )
     693                 :     {
     694               0 :         if( oField.GetWidth() > 0 && bPreservePrecision )
     695               0 :             sprintf( szFieldType, "numeric(%d,0)", oField.GetWidth() );
     696                 :         else
     697               0 :             strcpy( szFieldType, "int" );
     698                 :     }
     699               0 :     else if( oField.GetType() == OFTReal )
     700                 :     {
     701               0 :         if( oField.GetWidth() > 0 && oField.GetPrecision() > 0
     702                 :             && bPreservePrecision )
     703                 :             sprintf( szFieldType, "numeric(%d,%d)",
     704               0 :                      oField.GetWidth(), oField.GetPrecision() );
     705                 :         else
     706               0 :             strcpy( szFieldType, "float" );
     707                 :     }
     708               0 :     else if( oField.GetType() == OFTString )
     709                 :     {
     710               0 :         if( oField.GetWidth() == 0 || !bPreservePrecision )
     711               0 :             strcpy( szFieldType, "varchar(MAX)" );
     712                 :         else
     713               0 :             sprintf( szFieldType, "varchar(%d)", oField.GetWidth() );
     714                 :     }
     715               0 :     else if( oField.GetType() == OFTDate )
     716                 :     {
     717               0 :         strcpy( szFieldType, "date" );
     718                 :     }
     719               0 :     else if( oField.GetType() == OFTTime )
     720                 :     {
     721               0 :         strcpy( szFieldType, "time(7)" );
     722                 :     }
     723               0 :     else if( oField.GetType() == OFTDateTime )
     724                 :     {
     725               0 :         strcpy( szFieldType, "datetime" );
     726                 :     }
     727               0 :     else if( oField.GetType() == OFTBinary )
     728                 :     {
     729               0 :         strcpy( szFieldType, "image" );
     730                 :     }
     731               0 :     else if( bApproxOK )
     732                 :     {
     733                 :         CPLError( CE_Warning, CPLE_NotSupported,
     734                 :                   "Can't create field %s with type %s on MSSQL layers.  Creating as varchar.",
     735                 :                   oField.GetNameRef(),
     736               0 :                   OGRFieldDefn::GetFieldTypeName(oField.GetType()) );
     737               0 :         strcpy( szFieldType, "varchar" );
     738                 :     }
     739                 :     else
     740                 :     {
     741                 :         CPLError( CE_Failure, CPLE_NotSupported,
     742                 :                   "Can't create field %s with type %s on MSSQL layers.",
     743                 :                   oField.GetNameRef(),
     744               0 :                   OGRFieldDefn::GetFieldTypeName(oField.GetType()) );
     745                 : 
     746               0 :         return OGRERR_FAILURE;
     747                 :     }
     748                 : 
     749                 : /* -------------------------------------------------------------------- */
     750                 : /*      Create the new field.                                           */
     751                 : /* -------------------------------------------------------------------- */
     752                 :     
     753               0 :     CPLODBCStatement oStmt( poDS->GetSession() );
     754                 :             
     755                 :     oStmt.Appendf( "ALTER TABLE [%s].[%s] ADD [%s] %s", 
     756               0 :         pszSchemaName, pszTableName, oField.GetNameRef(), szFieldType);
     757                 : 
     758               0 :     if( !oStmt.ExecuteSQL() )
     759                 :     {
     760                 :         CPLError( CE_Failure, CPLE_AppDefined,
     761                 :                     "Error creating field %s, %s", oField.GetNameRef(), 
     762               0 :                     poDS->GetSession()->GetLastError() );
     763                 : 
     764               0 :         return OGRERR_FAILURE;
     765                 :     }
     766                 : 
     767                 : /* -------------------------------------------------------------------- */
     768                 : /*      Add the field to the OGRFeatureDefn.                            */
     769                 : /* -------------------------------------------------------------------- */
     770                 : 
     771               0 :     poFeatureDefn->AddFieldDefn( &oField );
     772                 : 
     773               0 :     return OGRERR_NONE;
     774                 : }
     775                 : 
     776                 : /************************************************************************/
     777                 : /*                             SetFeature()                             */
     778                 : /*                                                                      */
     779                 : /*      SetFeature() is implemented by an UPDATE SQL command            */
     780                 : /************************************************************************/
     781                 : 
     782               0 : OGRErr OGRMSSQLSpatialTableLayer::SetFeature( OGRFeature *poFeature )
     783                 : 
     784                 : {
     785               0 :     OGRErr              eErr = OGRERR_FAILURE;
     786                 : 
     787               0 :     GetLayerDefn();
     788                 : 
     789               0 :     if( NULL == poFeature )
     790                 :     {
     791                 :         CPLError( CE_Failure, CPLE_AppDefined,
     792               0 :                   "NULL pointer to OGRFeature passed to SetFeature()." );
     793               0 :         return eErr;
     794                 :     }
     795                 : 
     796               0 :     if( poFeature->GetFID() == OGRNullFID )
     797                 :     {
     798                 :         CPLError( CE_Failure, CPLE_AppDefined,
     799               0 :                   "FID required on features given to SetFeature()." );
     800               0 :         return eErr;
     801                 :     }
     802                 : 
     803               0 :     if( !pszFIDColumn )
     804                 :     {
     805                 :         CPLError( CE_Failure, CPLE_AppDefined,
     806                 :                   "Unable to update features in tables without\n"
     807               0 :                   "a recognised FID column.");
     808               0 :         return eErr;
     809                 : 
     810                 :     }
     811                 :     
     812               0 :     ClearStatement();
     813                 : 
     814                 : /* -------------------------------------------------------------------- */
     815                 : /*      Form the UPDATE command.                                        */
     816                 : /* -------------------------------------------------------------------- */
     817               0 :     CPLODBCStatement oStmt( poDS->GetSession() );
     818                 :             
     819               0 :     oStmt.Appendf( "UPDATE [%s].[%s] SET ", pszSchemaName, pszTableName);
     820                 : 
     821               0 :     OGRMSSQLGeometryValidator oValidator(poFeature->GetGeometryRef());
     822               0 :     OGRGeometry *poGeom = oValidator.GetValidGeometryRef();
     823                 : 
     824               0 :     if (poFeature->GetGeometryRef() != poGeom)
     825                 :     {
     826                 :         CPLError( CE_Warning, CPLE_NotSupported,
     827               0 :                   "Geometry with FID = %ld has been modified.", poFeature->GetFID() );
     828                 :     }
     829                 : 
     830               0 :     int bNeedComma = FALSE;
     831               0 :     if(pszGeomColumn != NULL)
     832                 :     {
     833               0 :         char    *pszWKT = NULL;
     834                 : 
     835               0 :         if (poGeom != NULL)
     836               0 :             poGeom->exportToWkt( &pszWKT );
     837                 : 
     838               0 :         oStmt.Appendf( "[%s] = ", pszGeomColumn );
     839                 : 
     840               0 :         if( pszWKT != NULL && (nGeomColumnType == MSSQLCOLTYPE_GEOMETRY 
     841                 :             || nGeomColumnType == MSSQLCOLTYPE_GEOGRAPHY))
     842                 :         {
     843               0 :             if (nGeomColumnType == MSSQLCOLTYPE_GEOGRAPHY)
     844                 :             {
     845               0 :                 oStmt.Append( "geography::STGeomFromText(" );
     846               0 :                 OGRMSSQLAppendEscaped(&oStmt, pszWKT);
     847               0 :                 oStmt.Appendf(",%d)", nSRSId );
     848                 :             }
     849                 :             else
     850                 :             {
     851               0 :                 oStmt.Append( "geometry::STGeomFromText(" );
     852               0 :                 OGRMSSQLAppendEscaped(&oStmt, pszWKT);
     853               0 :                 oStmt.Appendf(",%d).MakeValid()", nSRSId );
     854                 :             }
     855                 :         }
     856                 :         else
     857               0 :             oStmt.Append( "null" );
     858                 : 
     859               0 :         bNeedComma = TRUE;
     860               0 :         CPLFree(pszWKT);
     861                 :     }
     862                 : 
     863               0 :     int nFieldCount = poFeatureDefn->GetFieldCount();
     864                 :     int i;
     865               0 :     for( i = 0; i < nFieldCount; i++ )
     866                 :     {
     867               0 :         if (bNeedComma)
     868               0 :             oStmt.Appendf( ", [%s] = ", poFeatureDefn->GetFieldDefn(i)->GetNameRef() );
     869                 :         else
     870                 :         {
     871               0 :             oStmt.Appendf( "[%s] = ", poFeatureDefn->GetFieldDefn(i)->GetNameRef() );
     872               0 :             bNeedComma = TRUE;
     873                 :         }
     874                 : 
     875               0 :         if( !poFeature->IsFieldSet( i ) )
     876               0 :             oStmt.Append( "null" );
     877                 :         else
     878               0 :             AppendFieldValue(&oStmt, poFeature, i);
     879                 :     }
     880                 : 
     881                 :     /* Add the WHERE clause */
     882               0 :     oStmt.Appendf( " WHERE [%s] = %ld" , pszFIDColumn, poFeature->GetFID());
     883                 : 
     884                 : /* -------------------------------------------------------------------- */
     885                 : /*      Execute the update.                                             */
     886                 : /* -------------------------------------------------------------------- */
     887                 : 
     888               0 :     if( !oStmt.ExecuteSQL() )
     889                 :     {
     890                 :         CPLError( CE_Failure, CPLE_AppDefined,
     891                 :             "Error updating feature with FID:%ld, %s", poFeature->GetFID(), 
     892               0 :                     poDS->GetSession()->GetLastError() );
     893                 : 
     894               0 :         return OGRERR_FAILURE;
     895                 :     }
     896                 :     
     897               0 :     return OGRERR_NONE;
     898                 : }
     899                 : 
     900                 : /************************************************************************/
     901                 : /*                          DeleteFeature()                             */
     902                 : /************************************************************************/
     903                 : 
     904               0 : OGRErr OGRMSSQLSpatialTableLayer::DeleteFeature( long nFID )
     905                 : 
     906                 : {
     907               0 :     GetLayerDefn();
     908                 :     
     909               0 :     if( pszFIDColumn == NULL )
     910                 :     {
     911                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     912               0 :                   "DeleteFeature() without any FID column." );
     913               0 :         return OGRERR_FAILURE;
     914                 :     }
     915                 :     
     916               0 :     if( nFID == OGRNullFID )
     917                 :     {
     918                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     919               0 :                   "DeleteFeature() with unset FID fails." );
     920               0 :         return OGRERR_FAILURE;
     921                 :     }
     922                 :     
     923               0 :     ClearStatement();
     924                 : 
     925                 : /* -------------------------------------------------------------------- */
     926                 : /*      Drop the record with this FID.                                  */
     927                 : /* -------------------------------------------------------------------- */
     928               0 :     CPLODBCStatement oStatement( poDS->GetSession() );
     929                 : 
     930                 :     oStatement.Appendf("DELETE FROM [%s] WHERE [%s] = %ld", 
     931               0 :             poFeatureDefn->GetName(), pszFIDColumn, nFID);
     932                 :     
     933               0 :     if( !oStatement.ExecuteSQL() )
     934                 :     {
     935                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     936                 :                   "Attempt to delete feature with FID %ld failed. %s", 
     937               0 :                   nFID, poDS->GetSession()->GetLastError() );
     938                 : 
     939               0 :         return OGRERR_FAILURE;
     940                 :     }
     941                 :     
     942               0 :     return OGRERR_NONE;
     943                 : }
     944                 : 
     945                 : /************************************************************************/
     946                 : /*                           CreateFeature()                            */
     947                 : /************************************************************************/
     948                 : 
     949               0 : OGRErr OGRMSSQLSpatialTableLayer::CreateFeature( OGRFeature *poFeature )
     950                 : 
     951                 : {
     952               0 :     GetLayerDefn();
     953                 : 
     954               0 :     if( NULL == poFeature )
     955                 :     {
     956                 :         CPLError( CE_Failure, CPLE_AppDefined,
     957               0 :                   "NULL pointer to OGRFeature passed to CreateFeature()." );
     958               0 :         return OGRERR_FAILURE;
     959                 :     }
     960                 :     
     961               0 :     ClearStatement();
     962                 : 
     963               0 :     CPLODBCStatement oStatement( poDS->GetSession() );
     964                 : 
     965                 :     /* the fid values are retieved from the source layer */
     966               0 :     if( poFeature->GetFID() != OGRNullFID && pszFIDColumn != NULL )
     967               0 :         oStatement.Appendf("SET IDENTITY_INSERT [%s].[%s] ON;", pszSchemaName, pszTableName );
     968                 : 
     969                 : /* -------------------------------------------------------------------- */
     970                 : /*      Form the INSERT command.                                        */
     971                 : /* -------------------------------------------------------------------- */
     972                 : 
     973               0 :     oStatement.Appendf( "INSERT INTO [%s].[%s] (", pszSchemaName, pszTableName );
     974                 : 
     975               0 :     OGRMSSQLGeometryValidator oValidator(poFeature->GetGeometryRef());
     976               0 :     OGRGeometry *poGeom = oValidator.GetValidGeometryRef();
     977                 : 
     978               0 :     if (poFeature->GetGeometryRef() != poGeom)
     979                 :     {
     980                 :         CPLError( CE_Warning, CPLE_NotSupported,
     981               0 :                   "Geometry with FID = %ld has been modified.", poFeature->GetFID() );
     982                 :     }
     983                 : 
     984               0 :     int bNeedComma = FALSE;
     985                 : 
     986               0 :     if (poGeom != NULL && pszGeomColumn != NULL)
     987                 :     {
     988               0 :         oStatement.Append( pszGeomColumn );
     989               0 :         bNeedComma = TRUE;
     990                 :     }
     991                 : 
     992               0 :     if( poFeature->GetFID() != OGRNullFID && pszFIDColumn != NULL )
     993                 :     {
     994               0 :         if (bNeedComma)
     995               0 :             oStatement.Appendf( ", [%s]", pszFIDColumn );
     996                 :         else
     997                 :         {
     998               0 :             oStatement.Appendf( "[%s]", pszFIDColumn );
     999               0 :             bNeedComma = TRUE;
    1000                 :         }
    1001                 :     }
    1002                 : 
    1003               0 :     int nFieldCount = poFeatureDefn->GetFieldCount();
    1004                 :     int i;
    1005               0 :     for( i = 0; i < nFieldCount; i++ )
    1006                 :     {
    1007               0 :         if( !poFeature->IsFieldSet( i ) )
    1008               0 :             continue;
    1009                 : 
    1010               0 :         if (bNeedComma)
    1011               0 :             oStatement.Appendf( ", [%s]", poFeatureDefn->GetFieldDefn(i)->GetNameRef() );
    1012                 :         else
    1013                 :         {
    1014               0 :             oStatement.Appendf( "[%s]", poFeatureDefn->GetFieldDefn(i)->GetNameRef() );
    1015               0 :             bNeedComma = TRUE;
    1016                 :         }
    1017                 :     }
    1018                 : 
    1019               0 :     oStatement.Appendf( ") VALUES (" );
    1020                 : 
    1021                 :     /* Set the geometry */
    1022               0 :     bNeedComma = FALSE;
    1023               0 :     if(poGeom != NULL && pszGeomColumn != NULL)
    1024                 :     {
    1025               0 :         char    *pszWKT = NULL;
    1026                 :     
    1027                 :         //poGeom->setCoordinateDimension( nCoordDimension );
    1028                 : 
    1029               0 :         poGeom->exportToWkt( &pszWKT );
    1030                 : 
    1031               0 :         if( pszWKT != NULL && (nGeomColumnType == MSSQLCOLTYPE_GEOMETRY 
    1032                 :             || nGeomColumnType == MSSQLCOLTYPE_GEOGRAPHY))
    1033                 :         {
    1034               0 :             if (nGeomColumnType == MSSQLCOLTYPE_GEOGRAPHY)
    1035                 :             {
    1036               0 :                 oStatement.Append( "geography::STGeomFromText(" );
    1037               0 :                 OGRMSSQLAppendEscaped(&oStatement, pszWKT);
    1038               0 :                 oStatement.Appendf(",%d)", nSRSId );
    1039                 :             }
    1040                 :             else
    1041                 :             {
    1042               0 :                 oStatement.Append( "geometry::STGeomFromText(" );
    1043               0 :                 OGRMSSQLAppendEscaped(&oStatement, pszWKT);
    1044               0 :                 oStatement.Appendf(",%d).MakeValid()", nSRSId );
    1045                 :             }     
    1046                 :         }
    1047                 :         else
    1048               0 :             oStatement.Append( "null" );
    1049                 : 
    1050               0 :         bNeedComma = TRUE;
    1051               0 :         CPLFree(pszWKT);
    1052                 :     }
    1053                 : 
    1054                 :     /* Set the FID */
    1055               0 :     if( poFeature->GetFID() != OGRNullFID && pszFIDColumn != NULL )
    1056                 :     {
    1057               0 :         if (bNeedComma)
    1058               0 :             oStatement.Appendf( ", %ld", poFeature->GetFID() );
    1059                 :         else
    1060                 :         {
    1061               0 :             oStatement.Appendf( "%ld", poFeature->GetFID() );
    1062               0 :             bNeedComma = TRUE;
    1063                 :         }
    1064                 :     }
    1065                 : 
    1066               0 :     for( i = 0; i < nFieldCount; i++ )
    1067                 :     {
    1068               0 :         if( !poFeature->IsFieldSet( i ) )
    1069               0 :             continue;
    1070                 : 
    1071               0 :         if (bNeedComma)
    1072               0 :             oStatement.Append( ", " );
    1073                 :         else
    1074               0 :             bNeedComma = TRUE;
    1075                 : 
    1076               0 :         AppendFieldValue(&oStatement, poFeature, i);
    1077                 :     }
    1078                 : 
    1079               0 :     oStatement.Append( ");" );
    1080                 : 
    1081               0 :     if( poFeature->GetFID() != OGRNullFID && pszFIDColumn != NULL )
    1082               0 :         oStatement.Appendf("SET IDENTITY_INSERT [%s].[%s] OFF;", pszSchemaName, pszTableName );
    1083                 : 
    1084                 : /* -------------------------------------------------------------------- */
    1085                 : /*      Execute the insert.                                             */
    1086                 : /* -------------------------------------------------------------------- */
    1087                 :     
    1088               0 :     if( !oStatement.ExecuteSQL() )
    1089                 :     {
    1090                 :         CPLError( CE_Failure, CPLE_AppDefined, 
    1091                 :                   "INSERT command for new feature failed. %s", 
    1092               0 :                    poDS->GetSession()->GetLastError() );
    1093                 : 
    1094               0 :         return OGRERR_FAILURE;
    1095                 :     }
    1096                 : 
    1097               0 :     return OGRERR_NONE;
    1098                 : }
    1099                 : 
    1100                 : /************************************************************************/
    1101                 : /*                          AppendFieldValue()                          */
    1102                 : /*                                                                      */
    1103                 : /* Used by CreateFeature() and SetFeature() to format a                 */
    1104                 : /* non-empty field value                                                */
    1105                 : /************************************************************************/
    1106                 : 
    1107               0 : void OGRMSSQLSpatialTableLayer::AppendFieldValue(CPLODBCStatement *poStatement,
    1108                 :                                        OGRFeature* poFeature, int i)
    1109                 : {
    1110               0 :     int nOGRFieldType = poFeatureDefn->GetFieldDefn(i)->GetType();
    1111                 : 
    1112                 :     // We need special formatting for integer list values.
    1113               0 :     if(  nOGRFieldType == OFTIntegerList )
    1114                 :     {
    1115                 :         //TODO
    1116               0 :         poStatement->Append( "null" );
    1117               0 :         return;
    1118                 :     }
    1119                 : 
    1120                 :     // We need special formatting for real list values.
    1121               0 :     else if( nOGRFieldType == OFTRealList )
    1122                 :     {
    1123                 :         //TODO
    1124               0 :         poStatement->Append( "null" );
    1125               0 :         return;
    1126                 :     }
    1127                 : 
    1128                 :     // We need special formatting for string list values.
    1129               0 :     else if( nOGRFieldType == OFTStringList )
    1130                 :     {
    1131                 :         //TODO
    1132               0 :         poStatement->Append( "null" );
    1133               0 :         return;
    1134                 :     }
    1135                 : 
    1136                 :     // Binary formatting
    1137               0 :     if( nOGRFieldType == OFTBinary )
    1138                 :     {
    1139               0 :         int nLen = 0;
    1140               0 :         GByte* pabyData = poFeature->GetFieldAsBinary( i, &nLen );
    1141               0 :         char* pszBytes = GByteArrayToHexString( pabyData, nLen);
    1142               0 :         poStatement->Append( pszBytes );
    1143               0 :         CPLFree(pszBytes);
    1144               0 :         return;
    1145                 :     }
    1146                 : 
    1147                 :     // Flag indicating NULL or not-a-date date value
    1148                 :     // e.g. 0000-00-00 - there is no year 0
    1149               0 :     OGRBoolean bIsDateNull = FALSE;
    1150                 : 
    1151               0 :     const char *pszStrValue = poFeature->GetFieldAsString(i);
    1152                 : 
    1153                 :     // Check if date is NULL: 0000-00-00
    1154               0 :     if( nOGRFieldType == OFTDate )
    1155                 :     {
    1156               0 :         if( EQUALN( pszStrValue, "0000", 4 ) )
    1157                 :         {
    1158               0 :             pszStrValue = "null";
    1159               0 :             bIsDateNull = TRUE;
    1160                 :         }
    1161                 :     }
    1162               0 :     else if ( nOGRFieldType == OFTReal )
    1163                 :     {
    1164               0 :         char* pszComma = strchr((char*)pszStrValue, ',');
    1165               0 :         if (pszComma)
    1166               0 :             *pszComma = '.';
    1167                 :     }
    1168                 : 
    1169               0 :     if( nOGRFieldType != OFTInteger && nOGRFieldType != OFTReal
    1170                 :         && !bIsDateNull )
    1171                 :     {
    1172               0 :         OGRMSSQLAppendEscaped(poStatement, pszStrValue);
    1173                 :     }
    1174                 :     else
    1175                 :     {
    1176               0 :         poStatement->Append( pszStrValue );
    1177                 :     }
    1178                 : }
    1179                 : 

Generated by: LCOV version 1.7