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

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

Generated by: LCOV version 1.7