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

       1                 : /******************************************************************************
       2                 :  * $Id: ogrmssqlspatialdatasource.cpp 25690 2013-02-26 11:51:12Z tamas $
       3                 :  *
       4                 :  * Project:  MSSQL Spatial driver
       5                 :  * Purpose:  Implements OGRMSSQLSpatialDataSource class..
       6                 :  * Author:   Tamas Szekeres, szekerest at gmail.com
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2010, Tamas Szekeres
      10                 :  *
      11                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      12                 :  * copy of this software and associated documentation files (the "Software"),
      13                 :  * to deal in the Software without restriction, including without limitation
      14                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15                 :  * and/or sell copies of the Software, and to permit persons to whom the
      16                 :  * Software is furnished to do so, subject to the following conditions:
      17                 :  *
      18                 :  * The above copyright notice and this permission notice shall be included
      19                 :  * in all copies or substantial portions of the Software.
      20                 :  *
      21                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27                 :  * DEALINGS IN THE SOFTWARE.
      28                 :  ****************************************************************************/
      29                 : 
      30                 : #include "ogr_mssqlspatial.h"
      31                 : 
      32                 : CPL_CVSID("$Id: ogrmssqlspatialdatasource.cpp 25690 2013-02-26 11:51:12Z tamas $");
      33                 : 
      34                 : /************************************************************************/
      35                 : /*                          OGRMSSQLSpatialDataSource()                 */
      36                 : /************************************************************************/
      37                 : 
      38               0 : OGRMSSQLSpatialDataSource::OGRMSSQLSpatialDataSource()
      39                 : 
      40                 : {
      41               0 :     pszName = NULL;
      42               0 :     pszCatalog = NULL;
      43               0 :     papoLayers = NULL;
      44               0 :     nLayers = 0;
      45                 : 
      46               0 :     nKnownSRID = 0;
      47               0 :     panSRID = NULL;
      48               0 :     papoSRS = NULL;
      49                 : 
      50               0 :     nGeometryFormat = MSSQLGEOMETRY_NATIVE;
      51                 : 
      52               0 :     bUseGeometryColumns = CSLTestBoolean(CPLGetConfigOption("MSSQLSPATIAL_USE_GEOMETRY_COLUMNS", "YES"));
      53               0 : }
      54                 : 
      55                 : /************************************************************************/
      56                 : /*                         ~OGRMSSQLSpatialDataSource()                 */
      57                 : /************************************************************************/
      58                 : 
      59               0 : OGRMSSQLSpatialDataSource::~OGRMSSQLSpatialDataSource()
      60                 : 
      61                 : {
      62                 :     int         i;
      63                 : 
      64               0 :     CPLFree( pszName );
      65               0 :     CPLFree( pszCatalog );
      66                 : 
      67               0 :     for( i = 0; i < nLayers; i++ )
      68               0 :         delete papoLayers[i];
      69                 :     
      70               0 :     CPLFree( papoLayers );
      71                 : 
      72               0 :     for( i = 0; i < nKnownSRID; i++ )
      73                 :     {
      74               0 :         if( papoSRS[i] != NULL )
      75               0 :             papoSRS[i]->Release();
      76                 :     }
      77               0 :     CPLFree( panSRID );
      78               0 :     CPLFree( papoSRS );
      79               0 : }
      80                 : 
      81                 : /************************************************************************/
      82                 : /*                           TestCapability()                           */
      83                 : /************************************************************************/
      84                 : 
      85               0 : int OGRMSSQLSpatialDataSource::TestCapability( const char * pszCap )
      86                 : 
      87                 : {
      88               0 :     if( EQUAL(pszCap,ODsCCreateLayer) || EQUAL(pszCap,ODsCDeleteLayer) )
      89               0 :         return TRUE;
      90                 :     else
      91               0 :         return FALSE;
      92                 : }
      93                 : 
      94                 : /************************************************************************/
      95                 : /*                              GetLayer()                              */
      96                 : /************************************************************************/
      97                 : 
      98               0 : OGRLayer *OGRMSSQLSpatialDataSource::GetLayer( int iLayer )
      99                 : 
     100                 : {
     101               0 :     if( iLayer < 0 || iLayer >= nLayers )
     102               0 :         return NULL;
     103                 :     else
     104               0 :         return papoLayers[iLayer];
     105                 : }
     106                 : 
     107                 : /************************************************************************/
     108                 : /*                            DeleteLayer()                             */
     109                 : /************************************************************************/
     110                 : 
     111               0 : int OGRMSSQLSpatialDataSource::DeleteLayer( int iLayer )
     112                 : 
     113                 : {
     114               0 :     if( iLayer < 0 || iLayer >= nLayers )
     115               0 :         return OGRERR_FAILURE;
     116                 : 
     117                 : /* -------------------------------------------------------------------- */
     118                 : /*      Blow away our OGR structures related to the layer.  This is     */
     119                 : /*      pretty dangerous if anything has a reference to this layer!     */
     120                 : /* -------------------------------------------------------------------- */
     121               0 :     const char* pszLayerName = papoLayers[iLayer]->GetTableName();
     122               0 :     const char* pszSchemaName = papoLayers[iLayer]->GetSchemaName();
     123                 : 
     124               0 :     CPLODBCStatement oStmt( &oSession );
     125               0 :     if (bUseGeometryColumns)
     126                 :         oStmt.Appendf( "DELETE FROM geometry_columns WHERE f_table_schema = '%s' AND f_table_name = '%s'\n", 
     127               0 :             pszSchemaName, pszLayerName );
     128               0 :     oStmt.Appendf("DROP TABLE [%s].[%s]", pszSchemaName, pszLayerName );
     129                 : 
     130               0 :     CPLDebug( "MSSQLSpatial", "DeleteLayer(%s)", pszLayerName );
     131                 : 
     132               0 :     delete papoLayers[iLayer];
     133                 :     memmove( papoLayers + iLayer, papoLayers + iLayer + 1,
     134               0 :              sizeof(void *) * (nLayers - iLayer - 1) );
     135               0 :     nLayers--;
     136                 : 
     137               0 :     if ( strlen(pszLayerName) == 0 )
     138               0 :         return OGRERR_NONE;
     139                 : 
     140                 : /* -------------------------------------------------------------------- */
     141                 : /*      Remove from the database.                                       */
     142                 : /* -------------------------------------------------------------------- */
     143                 : 
     144               0 :     oSession.BeginTransaction();
     145                 :     
     146               0 :     if( !oStmt.ExecuteSQL() )
     147                 :     {
     148                 :         CPLError( CE_Failure, CPLE_AppDefined,
     149               0 :                     "Error deleting layer: %s", GetSession()->GetLastError() );
     150                 : 
     151               0 :         return OGRERR_FAILURE;
     152                 :     }
     153                 : 
     154               0 :     oSession.CommitTransaction();
     155                 : 
     156               0 :     return OGRERR_NONE;
     157                 : }
     158                 : 
     159                 : /************************************************************************/
     160                 : /*                            CreateLayer()                             */
     161                 : /************************************************************************/
     162                 : 
     163               0 : OGRLayer * OGRMSSQLSpatialDataSource::CreateLayer( const char * pszLayerName,
     164                 :                                           OGRSpatialReference *poSRS,
     165                 :                                           OGRwkbGeometryType eType,
     166                 :                                           char ** papszOptions )
     167                 : 
     168                 : {
     169               0 :     char                *pszTableName = NULL;
     170               0 :     char                *pszSchemaName = NULL;
     171               0 :     const char          *pszGeomType = NULL;
     172               0 :     const char          *pszGeomColumn = NULL;
     173               0 :     int                 nCoordDimension = 3;
     174                 : 
     175                 :     /* determine the dimension */
     176               0 :     if( eType == wkbFlatten(eType) )
     177               0 :         nCoordDimension = 2;
     178                 : 
     179               0 :     if( CSLFetchNameValue( papszOptions, "DIM") != NULL )
     180               0 :         nCoordDimension = atoi(CSLFetchNameValue( papszOptions, "DIM"));
     181                 :         
     182                 :     /* MSSQL Schema handling:
     183                 :        Extract schema name from input layer name or passed with -lco SCHEMA.
     184                 :        Set layer name to "schema.table" or to "table" if schema is not
     185                 :        specified
     186                 :     */
     187               0 :     const char* pszDotPos = strstr(pszLayerName,".");
     188               0 :     if ( pszDotPos != NULL )
     189                 :     {
     190               0 :       int length = pszDotPos - pszLayerName;
     191               0 :       pszSchemaName = (char*)CPLMalloc(length+1);
     192               0 :       strncpy(pszSchemaName, pszLayerName, length);
     193               0 :       pszSchemaName[length] = '\0';
     194                 :       
     195               0 :       if( CSLFetchBoolean(papszOptions,"LAUNDER", TRUE) )
     196               0 :           pszTableName = LaunderName( pszDotPos + 1 ); //skip "."
     197                 :       else
     198               0 :           pszTableName = CPLStrdup( pszDotPos + 1 ); //skip "."
     199                 :     }
     200                 :     else
     201                 :     {
     202               0 :       pszSchemaName = NULL;
     203               0 :       if( CSLFetchBoolean(papszOptions,"LAUNDER", TRUE) )
     204               0 :           pszTableName = LaunderName( pszLayerName ); //skip "."
     205                 :       else
     206               0 :           pszTableName = CPLStrdup( pszLayerName ); //skip "."
     207                 :     }
     208                 : 
     209               0 :     if( CSLFetchNameValue( papszOptions, "SCHEMA" ) != NULL )
     210                 :     {
     211               0 :         CPLFree(pszSchemaName);
     212               0 :         pszSchemaName = CPLStrdup(CSLFetchNameValue( papszOptions, "SCHEMA" ));
     213                 :     }
     214                 : 
     215               0 :     if (pszSchemaName == NULL)
     216               0 :         pszSchemaName = CPLStrdup("dbo");
     217                 : 
     218                 : /* -------------------------------------------------------------------- */
     219                 : /*      Do we already have this layer?  If so, should we blow it        */
     220                 : /*      away?                                                           */
     221                 : /* -------------------------------------------------------------------- */
     222                 :     int iLayer;
     223                 : 
     224               0 :     for( iLayer = 0; iLayer < nLayers; iLayer++ )
     225                 :     {
     226               0 :         if( EQUAL(pszLayerName,papoLayers[iLayer]->GetTableName()) )
     227                 :         {
     228               0 :             if( CSLFetchNameValue( papszOptions, "OVERWRITE" ) != NULL
     229                 :                 && !EQUAL(CSLFetchNameValue(papszOptions,"OVERWRITE"),"NO") )
     230                 :             {
     231               0 :                 if (!pszSchemaName)
     232               0 :                     pszSchemaName = CPLStrdup(papoLayers[iLayer]->GetSchemaName());
     233                 : 
     234               0 :                 DeleteLayer( iLayer );
     235                 :             }
     236                 :             else
     237                 :             {
     238                 :                 CPLError( CE_Failure, CPLE_AppDefined, 
     239                 :                           "Layer %s already exists, CreateLayer failed.\n"
     240                 :                           "Use the layer creation option OVERWRITE=YES to "
     241                 :                           "replace it.",
     242               0 :                           pszLayerName );
     243                 : 
     244               0 :                 CPLFree( pszSchemaName );
     245               0 :                 CPLFree( pszTableName );
     246               0 :                 return NULL;
     247                 :             }
     248                 :         }
     249                 :     }
     250                 : 
     251                 : /* -------------------------------------------------------------------- */
     252                 : /*      Handle the GEOM_TYPE option.                                    */
     253                 : /* -------------------------------------------------------------------- */
     254               0 :     pszGeomType = CSLFetchNameValue( papszOptions, "GEOM_TYPE" );
     255                 : 
     256               0 :     if( !pszGeomType )
     257               0 :         pszGeomType = "geometry";
     258                 :     
     259               0 :     if( !EQUAL(pszGeomType, "geometry")
     260                 :         && !EQUAL(pszGeomType, "geography"))
     261                 :     {
     262                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     263                 :                   "FORMAT=%s not recognised or supported.", 
     264               0 :                   pszGeomType );
     265                 : 
     266               0 :         CPLFree( pszSchemaName );
     267               0 :         CPLFree( pszTableName );
     268               0 :         return NULL;
     269                 :     }
     270                 : 
     271                 :     /* determine the geometry column name */
     272               0 :     pszGeomColumn =  CSLFetchNameValue( papszOptions, "GEOM_NAME");
     273               0 :     if (!pszGeomColumn)
     274               0 :         pszGeomColumn = "ogr_geometry";
     275                 : 
     276                 : /* -------------------------------------------------------------------- */
     277                 : /*      Initialize the metadata tables                                  */
     278                 : /* -------------------------------------------------------------------- */
     279                 : 
     280               0 :     if (InitializeMetadataTables() != OGRERR_NONE)
     281                 :     {
     282               0 :         CPLFree( pszSchemaName );
     283               0 :         CPLFree( pszTableName );
     284               0 :         return NULL;
     285                 :     }
     286                 : 
     287                 : /* -------------------------------------------------------------------- */
     288                 : /*      Try to get the SRS Id of this spatial reference system,         */
     289                 : /*      adding to the srs table if needed.                              */
     290                 : /* -------------------------------------------------------------------- */
     291               0 :     int nSRSId = 0;
     292                 : 
     293               0 :     if( CSLFetchNameValue( papszOptions, "SRID") != NULL )
     294               0 :         nSRSId = atoi(CSLFetchNameValue( papszOptions, "SRID"));
     295                 : 
     296               0 :     if( nSRSId == 0 && poSRS != NULL )
     297               0 :         nSRSId = FetchSRSId( poSRS );
     298                 : 
     299                 : /* -------------------------------------------------------------------- */
     300                 : /*      Create a new table and create a new entry in the geometry,      */
     301                 : /*      geometry_columns metadata table.                                */
     302                 : /* -------------------------------------------------------------------- */
     303                 : 
     304               0 :     if( eType != wkbNone )
     305                 :     {
     306               0 :         const char *pszGeometryType = OGRToOGCGeomType(eType);
     307                 : 
     308               0 :         CPLODBCStatement oStmt( &oSession );
     309                 :         
     310               0 :         if (bUseGeometryColumns)
     311                 :         {
     312                 :             oStmt.Appendf( "DELETE FROM geometry_columns WHERE f_table_schema = '%s' "
     313               0 :                 "AND f_table_name = '%s'\n", pszSchemaName, pszTableName );
     314                 :         
     315                 :             oStmt.Appendf("INSERT INTO [geometry_columns] ([f_table_catalog], [f_table_schema] ,[f_table_name], "
     316                 :                 "[f_geometry_column],[coord_dimension],[srid],[geometry_type]) VALUES ('%s', '%s', '%s', '%s', %d, %d, '%s')\n", 
     317               0 :                 pszCatalog, pszSchemaName, pszTableName, pszGeomColumn, nCoordDimension, nSRSId, pszGeometryType );
     318                 :         }
     319                 : 
     320                 :         oStmt.Appendf("CREATE TABLE [%s].[%s] ([ogr_fid] [int] IDENTITY(1,1) NOT NULL, "
     321                 :             "[%s] [%s] NULL, CONSTRAINT [PK_%s] PRIMARY KEY CLUSTERED ([ogr_fid] ASC))",
     322               0 :             pszSchemaName, pszTableName, pszGeomColumn, pszGeomType, pszTableName);
     323                 : 
     324               0 :         oSession.BeginTransaction();
     325                 :         
     326               0 :         if( !oStmt.ExecuteSQL() )
     327                 :         {
     328                 :             CPLError( CE_Failure, CPLE_AppDefined,
     329               0 :                         "Error creating layer: %s", GetSession()->GetLastError() );
     330                 : 
     331               0 :             return NULL;
     332                 :         }
     333                 : 
     334               0 :         oSession.CommitTransaction();
     335                 :     }
     336                 : 
     337                 : /* -------------------------------------------------------------------- */
     338                 : /*      Create the layer object.                                        */
     339                 : /* -------------------------------------------------------------------- */
     340                 :     OGRMSSQLSpatialTableLayer   *poLayer;
     341                 : 
     342               0 :     poLayer = new OGRMSSQLSpatialTableLayer( this );
     343                 : 
     344               0 :     poLayer->SetLaunderFlag( CSLFetchBoolean(papszOptions,"LAUNDER",TRUE) );
     345               0 :     poLayer->SetPrecisionFlag( CSLFetchBoolean(papszOptions,"PRECISION",TRUE));
     346                 :     
     347               0 :     if (poLayer->Initialize(pszSchemaName, pszTableName, pszGeomColumn, nCoordDimension, nSRSId, eType) == OGRERR_FAILURE)
     348                 :     {
     349               0 :         CPLFree( pszSchemaName );
     350               0 :         CPLFree( pszTableName );
     351               0 :         return NULL;
     352                 :     }
     353                 : 
     354               0 :     CPLFree( pszSchemaName );
     355               0 :     CPLFree( pszTableName );
     356                 : 
     357                 : /* -------------------------------------------------------------------- */
     358                 : /*      Add layer to data source layer list.                            */
     359                 : /* -------------------------------------------------------------------- */
     360                 :     papoLayers = (OGRMSSQLSpatialTableLayer **)
     361               0 :         CPLRealloc( papoLayers,  sizeof(OGRMSSQLSpatialTableLayer *) * (nLayers+1) );
     362                 : 
     363               0 :     papoLayers[nLayers++] = poLayer;
     364                 : 
     365                 : 
     366               0 :     return poLayer;
     367                 : }
     368                 : 
     369                 : /************************************************************************/
     370                 : /*                             OpenTable()                              */
     371                 : /************************************************************************/
     372                 : 
     373               0 : int OGRMSSQLSpatialDataSource::OpenTable( const char *pszSchemaName, const char *pszTableName, 
     374                 :                     const char *pszGeomCol, int nCoordDimension,
     375                 :                     int nSRID, OGRwkbGeometryType eType, int bUpdate )
     376                 : 
     377                 : {
     378                 : /* -------------------------------------------------------------------- */
     379                 : /*      Create the layer object.                                        */
     380                 : /* -------------------------------------------------------------------- */
     381               0 :     OGRMSSQLSpatialTableLayer  *poLayer = new OGRMSSQLSpatialTableLayer( this );
     382                 : 
     383               0 :     if( poLayer->Initialize( pszSchemaName, pszTableName, pszGeomCol, nCoordDimension, nSRID, eType ) )
     384                 :     {
     385               0 :         delete poLayer;
     386               0 :         return FALSE;
     387                 :     }
     388                 : 
     389                 : /* -------------------------------------------------------------------- */
     390                 : /*      Add layer to data source layer list.                            */
     391                 : /* -------------------------------------------------------------------- */
     392                 :     papoLayers = (OGRMSSQLSpatialTableLayer **)
     393               0 :         CPLRealloc( papoLayers,  sizeof(OGRMSSQLSpatialTableLayer *) * (nLayers+1) );
     394               0 :     papoLayers[nLayers++] = poLayer;
     395                 :     
     396               0 :     return TRUE;
     397                 : }
     398                 : 
     399                 : 
     400                 : /************************************************************************/
     401                 : /*                       GetLayerCount()                                */
     402                 : /************************************************************************/
     403                 : 
     404               0 : int OGRMSSQLSpatialDataSource::GetLayerCount() 
     405                 : { 
     406               0 :     return nLayers; 
     407                 : }
     408                 : 
     409                 : /************************************************************************/
     410                 : /*                       ParseValue()                                   */
     411                 : /************************************************************************/
     412                 : 
     413               0 : int OGRMSSQLSpatialDataSource::ParseValue(char** pszValue, char* pszSource, const char* pszKey, int nStart, int nNext, int nTerm, int bRemove)
     414                 : {
     415               0 :     int nLen = strlen(pszKey);
     416               0 :     if ((*pszValue) == NULL && nStart + nLen < nNext && 
     417                 :             EQUALN(pszSource + nStart, pszKey, nLen))
     418                 :     {
     419               0 :         *pszValue = (char*)CPLMalloc( sizeof(char) * (nNext - nStart - nLen + 1) );
     420               0 :         if (*pszValue)
     421               0 :             strncpy(*pszValue, pszSource + nStart + nLen, nNext - nStart - nLen);
     422               0 :         (*pszValue)[nNext - nStart - nLen] = 0;
     423                 : 
     424               0 :         if (bRemove)
     425                 :         {
     426                 :             // remove the value from the source string
     427               0 :             if (pszSource[nNext] == ';')
     428               0 :                 memmove( pszSource + nStart, pszSource + nNext + 1, nTerm - nNext);
     429                 :             else
     430               0 :                 memmove( pszSource + nStart, pszSource + nNext, nTerm - nNext + 1);
     431                 :         }
     432               0 :         return TRUE;
     433                 :     }
     434               0 :     return FALSE;
     435                 : }
     436                 : 
     437                 : 
     438                 : /************************************************************************/
     439                 : /*                                Open()                                */
     440                 : /************************************************************************/
     441                 : 
     442               0 : int OGRMSSQLSpatialDataSource::Open( const char * pszNewName, int bUpdate,
     443                 :                              int bTestOpen )
     444                 : 
     445                 : {
     446               0 :     CPLAssert( nLayers == 0 );
     447                 : 
     448               0 :     if( !EQUALN(pszNewName,"MSSQL:",6) )
     449                 :     {
     450               0 :         if( !bTestOpen )
     451                 :             CPLError( CE_Failure, CPLE_AppDefined,
     452                 :                       "%s does not conform to MSSSQLSpatial naming convention,"
     453               0 :                       " MSSQL:*\n", pszNewName );
     454               0 :         return FALSE;
     455                 :     }
     456                 : 
     457                 :     /* Determine if the connection string contains specific values */
     458               0 :     char* pszTableSpec = NULL;
     459               0 :     char* pszGeometryFormat = NULL;
     460               0 :     char* pszConnectionName = CPLStrdup(pszNewName + 6);
     461               0 :     char* pszDriver = NULL;
     462                 :     int nCurrent, nNext, nTerm;
     463               0 :     nCurrent = nNext = nTerm = strlen(pszConnectionName);
     464                 : 
     465               0 :     while (nCurrent > 0)
     466                 :     {
     467               0 :         --nCurrent;
     468               0 :         if (pszConnectionName[nCurrent] == ';')
     469                 :         {
     470               0 :             nNext = nCurrent;
     471               0 :             continue;
     472                 :         }
     473                 : 
     474               0 :         if (ParseValue(&pszCatalog, pszConnectionName, "database=", 
     475                 :             nCurrent, nNext, nTerm, FALSE))
     476               0 :             continue;
     477                 : 
     478               0 :         if (ParseValue(&pszTableSpec, pszConnectionName, "tables=", 
     479                 :             nCurrent, nNext, nTerm, TRUE))
     480               0 :             continue;
     481                 : 
     482               0 :         if (ParseValue(&pszDriver, pszConnectionName, "driver=", 
     483                 :             nCurrent, nNext, nTerm, FALSE))
     484               0 :             continue;
     485                 : 
     486               0 :         if (ParseValue(&pszGeometryFormat, pszConnectionName, 
     487                 :             "geometryformat=", nCurrent, nNext, nTerm, TRUE))
     488                 :         {
     489               0 :             if (EQUALN(pszGeometryFormat,"wkbzm",5))
     490               0 :                 nGeometryFormat = MSSQLGEOMETRY_WKBZM;
     491               0 :             else if (EQUALN(pszGeometryFormat, "wkb",3))
     492               0 :                 nGeometryFormat = MSSQLGEOMETRY_WKB;
     493               0 :             else if (EQUALN(pszGeometryFormat,"wkt",3))
     494               0 :                 nGeometryFormat = MSSQLGEOMETRY_WKT;
     495               0 :             else if (EQUALN(pszGeometryFormat,"native",6))
     496               0 :                 nGeometryFormat = MSSQLGEOMETRY_NATIVE;
     497                 :             else
     498                 :             {
     499                 :                 CPLError( CE_Failure, CPLE_AppDefined,
     500                 :                     "Invalid geometry type specified: %s,"
     501               0 :                       " MSSQL:*\n", pszGeometryFormat );
     502                 :                 
     503               0 :                 CPLFree(pszTableSpec);
     504               0 :                 CPLFree(pszGeometryFormat);
     505               0 :                 CPLFree(pszConnectionName);
     506               0 :                 CPLFree(pszDriver);
     507               0 :                 return FALSE;
     508                 :             }
     509                 : 
     510               0 :             CPLFree(pszGeometryFormat);
     511               0 :             pszGeometryFormat = NULL;
     512               0 :             continue;
     513                 :         }
     514                 :     }
     515                 : 
     516                 :     /* Determine if the connection string contains the catalog portion */
     517               0 :     if( pszCatalog == NULL )
     518                 :     {
     519                 :         CPLError( CE_Failure, CPLE_AppDefined,
     520               0 :                       "'%s' does not contain the 'database' portion\n", pszNewName );
     521                 :         
     522               0 :         CPLFree(pszTableSpec);
     523               0 :         CPLFree(pszGeometryFormat);
     524               0 :         CPLFree(pszConnectionName);
     525               0 :         CPLFree(pszDriver);
     526               0 :         return FALSE;
     527                 :     }
     528                 :     
     529               0 :     pszName = CPLStrdup(pszNewName);
     530                 : 
     531               0 :     char  **papszTableNames=NULL;
     532               0 :     char  **papszSchemaNames=NULL;
     533               0 :     char  **papszGeomColumnNames=NULL;
     534               0 :     char  **papszCoordDimensions=NULL;
     535               0 :     char  **papszSRIds=NULL;
     536                 : 
     537                 :     /* Determine if the connection string contains the TABLES portion */
     538               0 :     if( pszTableSpec != NULL )
     539                 :     {
     540                 :         char          **papszTableList;
     541                 :         int             i;
     542                 : 
     543               0 :         papszTableList = CSLTokenizeString2( pszTableSpec, ",", 0 );
     544                 : 
     545               0 :         for( i = 0; i < CSLCount(papszTableList); i++ )
     546                 :         {
     547                 :             char      **papszQualifiedParts;
     548                 : 
     549                 :             // Get schema and table name
     550               0 :             papszQualifiedParts = CSLTokenizeString2( papszTableList[i],
     551               0 :                                                       ".", 0 );
     552                 : 
     553                 :             /* Find the geometry column name if specified */
     554               0 :             if( CSLCount( papszQualifiedParts ) >= 1 )
     555                 :             {
     556               0 :                 char* pszGeomColumnName = NULL;
     557               0 :                 char* pos = strchr(papszQualifiedParts[CSLCount( papszQualifiedParts ) - 1], '(');
     558               0 :                 if (pos != NULL)
     559                 :                 {
     560               0 :                     *pos = '\0';
     561               0 :                     pszGeomColumnName = pos+1;
     562               0 :                     int len = strlen(pszGeomColumnName);
     563               0 :                     if (len > 0)
     564               0 :                         pszGeomColumnName[len - 1] = '\0';
     565                 :                 }
     566                 :                 papszGeomColumnNames = CSLAddString( papszGeomColumnNames,
     567               0 :                         pszGeomColumnName ? pszGeomColumnName : "");
     568                 :             }
     569                 : 
     570               0 :             if( CSLCount( papszQualifiedParts ) == 2 )
     571                 :             {
     572                 :                 papszSchemaNames = CSLAddString( papszSchemaNames, 
     573               0 :                                                 papszQualifiedParts[0] );
     574                 :                 papszTableNames = CSLAddString( papszTableNames,
     575               0 :                                                 papszQualifiedParts[1] );
     576                 :             }
     577               0 :             else if( CSLCount( papszQualifiedParts ) == 1 )
     578                 :             {
     579               0 :                 papszSchemaNames = CSLAddString( papszSchemaNames, "dbo");
     580                 :                 papszTableNames = CSLAddString( papszTableNames,
     581               0 :                                                 papszQualifiedParts[0] );
     582                 :             }
     583                 : 
     584               0 :             CSLDestroy(papszQualifiedParts);
     585                 :         }
     586                 : 
     587               0 :         CSLDestroy(papszTableList);
     588                 :     }
     589                 : 
     590               0 :     CPLFree(pszTableSpec);
     591                 : 
     592                 :     /* Initialize the SQL Server connection. */
     593                 :     int nResult;
     594               0 :     if ( pszDriver != NULL )
     595                 :     {
     596                 :         /* driver has been specified */
     597               0 :         CPLDebug( "OGR_MSSQLSpatial", "EstablishSession(Connection:\"%s\")", pszConnectionName);
     598               0 :         nResult = oSession.EstablishSession( pszConnectionName, "", "" );
     599                 :     }
     600                 :     else
     601                 :     {
     602                 :         /* no driver has been specified, defautls to SQL Server */
     603               0 :         CPLDebug( "OGR_MSSQLSpatial", "EstablishSession(Connection:\"%s\")", pszConnectionName);
     604               0 :         nResult = oSession.EstablishSession( CPLSPrintf("DRIVER=SQL Server;%s", pszConnectionName), "", "" );
     605                 :     }
     606                 : 
     607               0 :     CPLFree(pszDriver);
     608                 : 
     609               0 :     if( !nResult )
     610                 :     {
     611                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     612                 :                   "Unable to initialize connection to the server for %s,\n"
     613               0 :                   "%s", pszNewName, oSession.GetLastError() );
     614                 :         
     615               0 :         CSLDestroy( papszTableNames );
     616               0 :         CSLDestroy( papszSchemaNames );
     617               0 :         CSLDestroy( papszGeomColumnNames );
     618               0 :         CSLDestroy( papszCoordDimensions );
     619               0 :         CSLDestroy( papszSRIds );
     620               0 :         CPLFree(pszGeometryFormat);
     621               0 :         CPLFree(pszConnectionName);
     622               0 :         return FALSE;
     623                 :     }
     624                 : 
     625               0 :     char** papszTypes = NULL;
     626                 : 
     627                 :     /* Determine the available tables if not specified. */
     628               0 :     if (papszTableNames == NULL && bUseGeometryColumns)
     629                 :     {
     630               0 :         CPLODBCStatement oStmt( &oSession );
     631                 :             
     632               0 :         oStmt.Append( "SELECT f_table_schema, f_table_name, f_geometry_column, coord_dimension, srid, geometry_type FROM dbo.geometry_columns");
     633                 : 
     634               0 :         if( oStmt.ExecuteSQL() )
     635                 :         {
     636               0 :             while( oStmt.Fetch() )
     637                 :             {
     638                 :                 papszSchemaNames = 
     639               0 :                         CSLAddString( papszSchemaNames, oStmt.GetColData(0) );
     640                 :                 papszTableNames = 
     641               0 :                         CSLAddString( papszTableNames, oStmt.GetColData(1) );
     642                 :                 papszGeomColumnNames = 
     643               0 :                         CSLAddString( papszGeomColumnNames, oStmt.GetColData(2) );
     644                 :                 papszCoordDimensions = 
     645               0 :                         CSLAddString( papszCoordDimensions, oStmt.GetColData(3) );
     646                 :                 papszSRIds = 
     647               0 :                         CSLAddString( papszSRIds, oStmt.GetColData(4) );
     648                 :                 papszTypes = 
     649               0 :                         CSLAddString( papszTypes, oStmt.GetColData(5) );
     650                 :             }
     651                 :         }
     652                 :         else
     653               0 :             bUseGeometryColumns = FALSE;
     654                 :     }
     655                 : 
     656                 :     /* Query catalog for tables having geometry columns */
     657               0 :     if (papszTableNames == NULL)
     658                 :     {
     659               0 :         CPLODBCStatement oStmt( &oSession );
     660                 :             
     661               0 :         oStmt.Append( "SELECT sys.schemas.name, sys.schemas.name + '.' + sys.objects.name, sys.columns.name from sys.columns join sys.types on sys.columns.system_type_id = sys.types.system_type_id and sys.columns.user_type_id = sys.types.user_type_id join sys.objects on sys.objects.object_id = sys.columns.object_id join sys.schemas on sys.objects.schema_id = sys.schemas.schema_id where (sys.types.name = 'geometry' or sys.types.name = 'geography') and (sys.objects.type = 'U' or sys.objects.type = 'V')");
     662                 : 
     663               0 :         if( oStmt.ExecuteSQL() )
     664                 :         {
     665               0 :             while( oStmt.Fetch() )
     666                 :             {
     667                 :                 papszSchemaNames = 
     668               0 :                         CSLAddString( papszSchemaNames, oStmt.GetColData(0) );
     669                 :                 papszTableNames = 
     670               0 :                         CSLAddString( papszTableNames, oStmt.GetColData(1) );
     671                 :                 papszGeomColumnNames = 
     672               0 :                         CSLAddString( papszGeomColumnNames, oStmt.GetColData(2) );
     673                 :             }
     674               0 :         }
     675                 :     }
     676                 : 
     677                 :     int nSRId, nCoordDimension;
     678                 :     OGRwkbGeometryType eType;
     679                 :         
     680               0 :     for( int iTable = 0; 
     681               0 :          papszTableNames != NULL && papszTableNames[iTable] != NULL; 
     682                 :          iTable++ )
     683                 :     {
     684               0 :         if (papszSRIds != NULL)
     685               0 :             nSRId = atoi(papszSRIds[iTable]);
     686                 :         else
     687               0 :             nSRId = -1;
     688                 : 
     689               0 :         if (papszCoordDimensions != NULL)
     690               0 :             nCoordDimension = atoi(papszCoordDimensions[iTable]);
     691                 :         else
     692               0 :             nCoordDimension = 2;
     693                 : 
     694               0 :         if (papszTypes != NULL)
     695               0 :             eType = OGRFromOGCGeomType(papszTypes[iTable]);
     696                 :         else
     697               0 :             eType = wkbUnknown;
     698                 : 
     699               0 :         if( strlen(papszGeomColumnNames[iTable]) > 0 )
     700               0 :             OpenTable( papszSchemaNames[iTable], papszTableNames[iTable], papszGeomColumnNames[iTable], 
     701               0 :                     nCoordDimension, nSRId, eType, bUpdate );
     702                 :         else
     703               0 :             OpenTable( papszSchemaNames[iTable], papszTableNames[iTable], NULL, 
     704               0 :                     nCoordDimension, nSRId, eType, bUpdate );
     705                 :     }
     706                 : 
     707               0 :     CSLDestroy( papszTableNames );
     708               0 :     CSLDestroy( papszSchemaNames );
     709               0 :     CSLDestroy( papszGeomColumnNames );
     710               0 :     CSLDestroy( papszCoordDimensions );
     711               0 :     CSLDestroy( papszSRIds );
     712               0 :     CSLDestroy( papszTypes );
     713                 : 
     714               0 :     CPLFree(pszGeometryFormat);
     715               0 :     CPLFree(pszConnectionName);
     716                 :     
     717               0 :     bDSUpdate = bUpdate;
     718                 : 
     719               0 :     return TRUE;
     720                 : }
     721                 : 
     722                 : /************************************************************************/
     723                 : /*                             ExecuteSQL()                             */
     724                 : /************************************************************************/
     725                 : 
     726               0 : OGRLayer * OGRMSSQLSpatialDataSource::ExecuteSQL( const char *pszSQLCommand,
     727                 :                                           OGRGeometry *poSpatialFilter,
     728                 :                                           const char *pszDialect )
     729                 : 
     730                 : {
     731                 : /* -------------------------------------------------------------------- */
     732                 : /*      Use generic imlplementation for OGRSQL dialect.                 */
     733                 : /* -------------------------------------------------------------------- */
     734               0 :     if( pszDialect != NULL && EQUAL(pszDialect,"OGRSQL") )
     735                 :         return OGRDataSource::ExecuteSQL( pszSQLCommand, 
     736                 :                                           poSpatialFilter, 
     737               0 :                                           pszDialect );
     738                 : 
     739                 : /* -------------------------------------------------------------------- */
     740                 : /*      Special case DELLAYER: command.                                 */
     741                 : /* -------------------------------------------------------------------- */
     742               0 :     if( EQUALN(pszSQLCommand,"DELLAYER:",9) )
     743                 :     {
     744               0 :         const char *pszLayerName = pszSQLCommand + 9;
     745                 : 
     746               0 :         while( *pszLayerName == ' ' )
     747               0 :             pszLayerName++;
     748                 :         
     749               0 :         for( int iLayer = 0; iLayer < nLayers; iLayer++ )
     750                 :         {
     751               0 :             if( EQUAL(papoLayers[iLayer]->GetName(), 
     752                 :                       pszLayerName ))
     753                 :             {
     754               0 :                 DeleteLayer( iLayer );
     755               0 :                 break;
     756                 :             }
     757                 :         }
     758               0 :         return NULL;
     759                 :     }
     760                 : 
     761               0 :     CPLDebug( "MSSQLSpatial", "ExecuteSQL(%s) called.", pszSQLCommand );
     762                 : 
     763               0 :     if( EQUALN(pszSQLCommand, "DROP SPATIAL INDEX ON ", 22) )
     764                 :     {
     765                 :         /* Handle command to drop a spatial index. */
     766               0 :         OGRMSSQLSpatialTableLayer  *poLayer = new OGRMSSQLSpatialTableLayer( this );
     767                 : 
     768               0 :         if (poLayer)
     769                 :         {
     770               0 :             if( poLayer->Initialize( "dbo", pszSQLCommand + 22, NULL, 0, 0, wkbUnknown ) != CE_None )
     771                 :             {
     772                 :                 CPLError( CE_Failure, CPLE_AppDefined, 
     773               0 :                       "Failed to initialize layer '%s'", pszSQLCommand + 22 );   
     774                 :             }
     775               0 :             poLayer->DropSpatialIndex();
     776               0 :             delete poLayer;
     777                 :         }
     778               0 :         return NULL;
     779                 :     }
     780               0 :     else if( EQUALN(pszSQLCommand, "CREATE SPATIAL INDEX ON ", 24) )
     781                 :     {
     782                 :         /* Handle command to create a spatial index. */
     783               0 :         OGRMSSQLSpatialTableLayer  *poLayer = new OGRMSSQLSpatialTableLayer( this );
     784                 : 
     785               0 :         if (poLayer)
     786                 :         {
     787               0 :             if( poLayer->Initialize( "dbo", pszSQLCommand + 24, NULL, 0, 0, wkbUnknown ) != CE_None )
     788                 :             {
     789                 :                 CPLError( CE_Failure, CPLE_AppDefined, 
     790               0 :                       "Failed to initialize layer '%s'", pszSQLCommand + 24 );    
     791                 :             }
     792               0 :             poLayer->CreateSpatialIndex();
     793               0 :             delete poLayer;
     794                 :         }
     795               0 :         return NULL;
     796                 :     }
     797                 :     
     798                 :     /* Execute the command natively */
     799               0 :     CPLODBCStatement *poStmt = new CPLODBCStatement( &oSession );
     800               0 :     poStmt->Append( pszSQLCommand );
     801                 : 
     802               0 :     if( !poStmt->ExecuteSQL() )
     803                 :     {
     804                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     805               0 :                   "%s", oSession.GetLastError() );
     806               0 :         delete poStmt;
     807               0 :         return NULL;
     808                 :     }
     809                 : 
     810                 : /* -------------------------------------------------------------------- */
     811                 : /*      Are there result columns for this statement?                    */
     812                 : /* -------------------------------------------------------------------- */
     813               0 :     if( poStmt->GetColCount() == 0 )
     814                 :     {
     815               0 :         delete poStmt;
     816               0 :         CPLErrorReset();
     817               0 :         return NULL;
     818                 :     }
     819                 : 
     820                 : /* -------------------------------------------------------------------- */
     821                 : /*      Create a results layer.  It will take ownership of the          */
     822                 : /*      statement.                                                      */
     823                 : /* -------------------------------------------------------------------- */
     824                 :     
     825               0 :     OGRMSSQLSpatialSelectLayer *poLayer = NULL;
     826                 :         
     827               0 :     poLayer = new OGRMSSQLSpatialSelectLayer( this, poStmt );
     828                 : 
     829               0 :     if( poSpatialFilter != NULL )
     830               0 :         poLayer->SetSpatialFilter( poSpatialFilter );
     831                 : 
     832               0 :     return poLayer;
     833                 : }
     834                 : 
     835                 : /************************************************************************/
     836                 : /*                          ReleaseResultSet()                          */
     837                 : /************************************************************************/
     838                 : 
     839               0 : void OGRMSSQLSpatialDataSource::ReleaseResultSet( OGRLayer * poLayer )
     840                 : 
     841                 : {
     842               0 :     delete poLayer;
     843               0 : }
     844                 : 
     845                 : /************************************************************************/
     846                 : /*                            LaunderName()                             */
     847                 : /************************************************************************/
     848                 : 
     849               0 : char *OGRMSSQLSpatialDataSource::LaunderName( const char *pszSrcName )
     850                 : 
     851                 : {
     852               0 :     char    *pszSafeName = CPLStrdup( pszSrcName );
     853                 :     int     i;
     854                 : 
     855               0 :     for( i = 0; pszSafeName[i] != '\0'; i++ )
     856                 :     {
     857               0 :         pszSafeName[i] = (char) tolower( pszSafeName[i] );
     858               0 :         if( pszSafeName[i] == '-' || pszSafeName[i] == '#' )
     859               0 :             pszSafeName[i] = '_';
     860                 :     }
     861                 : 
     862               0 :     return pszSafeName;
     863                 : }
     864                 : 
     865                 : /************************************************************************/
     866                 : /*                      InitializeMetadataTables()                      */
     867                 : /*                                                                      */
     868                 : /*      Create the metadata tables (SPATIAL_REF_SYS and                 */
     869                 : /*      GEOMETRY_COLUMNS).                                              */
     870                 : /************************************************************************/
     871                 : 
     872               0 : OGRErr OGRMSSQLSpatialDataSource::InitializeMetadataTables()
     873                 : 
     874                 : {
     875               0 :     if (bUseGeometryColumns)
     876                 :     {
     877               0 :         CPLODBCStatement oStmt( &oSession );
     878                 : 
     879                 :         oStmt.Append( "IF NOT EXISTS (SELECT * FROM sys.objects WHERE "
     880                 :             "object_id = OBJECT_ID(N'[dbo].[geometry_columns]') AND type in (N'U')) "
     881                 :             "CREATE TABLE geometry_columns (f_table_catalog varchar(128) not null, "
     882                 :             "f_table_schema varchar(128) not null, f_table_name varchar(256) not null, "
     883                 :             "f_geometry_column varchar(256) not null, coord_dimension integer not null, "
     884                 :             "srid integer not null, geometry_type varchar(30) not null, "
     885                 :             "CONSTRAINT geometry_columns_pk PRIMARY KEY (f_table_catalog, "
     886               0 :             "f_table_schema, f_table_name, f_geometry_column));\n" );
     887                 : 
     888                 :         oStmt.Append( "IF NOT EXISTS (SELECT * FROM sys.objects "
     889                 :             "WHERE object_id = OBJECT_ID(N'[dbo].[spatial_ref_sys]') AND type in (N'U')) "
     890                 :             "CREATE TABLE spatial_ref_sys (srid integer not null "
     891               0 :             "PRIMARY KEY, auth_name varchar(256), auth_srid integer, srtext varchar(2048), proj4text varchar(2048))" );
     892                 : 
     893               0 :         oSession.BeginTransaction();
     894                 :     
     895               0 :         if( !oStmt.ExecuteSQL() )
     896                 :         {
     897                 :             CPLError( CE_Failure, CPLE_AppDefined,
     898               0 :                         "Error initializing the metadata tables : %s", GetSession()->GetLastError() );
     899               0 :             return OGRERR_FAILURE;
     900                 :         }
     901                 : 
     902               0 :         oSession.CommitTransaction();
     903                 :     }
     904                 : 
     905               0 :     return OGRERR_NONE;
     906                 : }
     907                 : 
     908                 : 
     909                 : /************************************************************************/
     910                 : /*                              FetchSRS()                              */
     911                 : /*                                                                      */
     912                 : /*      Return a SRS corresponding to a particular id.  Note that       */
     913                 : /*      reference counting should be honoured on the returned           */
     914                 : /*      OGRSpatialReference, as handles may be cached.                  */
     915                 : /************************************************************************/
     916                 : 
     917               0 : OGRSpatialReference *OGRMSSQLSpatialDataSource::FetchSRS( int nId )
     918                 : 
     919                 : {
     920               0 :     if( nId <= 0 )
     921               0 :         return NULL;
     922                 : 
     923                 : /* -------------------------------------------------------------------- */
     924                 : /*      First, we look through our SRID cache, is it there?             */
     925                 : /* -------------------------------------------------------------------- */
     926                 :     int  i;
     927                 : 
     928               0 :     for( i = 0; i < nKnownSRID; i++ )
     929                 :     {
     930               0 :         if( panSRID[i] == nId )
     931               0 :             return papoSRS[i];
     932                 :     }
     933                 : 
     934               0 :     OGRSpatialReference *poSRS = NULL;
     935                 : 
     936                 : /* -------------------------------------------------------------------- */
     937                 : /*      Try looking up in spatial_ref_sys table                         */
     938                 : /* -------------------------------------------------------------------- */
     939               0 :     if (bUseGeometryColumns)
     940                 :     {
     941               0 :         CPLODBCStatement oStmt( GetSession() );
     942               0 :         oStmt.Appendf( "SELECT srtext FROM spatial_ref_sys WHERE srid = %d", nId );
     943                 : 
     944               0 :         if( oStmt.ExecuteSQL() && oStmt.Fetch() )
     945                 :         {
     946               0 :             if ( oStmt.GetColData( 0 ) )
     947                 :             {
     948               0 :                 poSRS = new OGRSpatialReference();
     949               0 :                 char* pszWKT = (char*)oStmt.GetColData( 0 );
     950               0 :                 if( poSRS->importFromWkt( &pszWKT ) != OGRERR_NONE )
     951                 :                 {
     952               0 :                     delete poSRS;
     953               0 :                     poSRS = NULL;
     954                 :                 }    
     955                 :             }
     956               0 :         }
     957                 :     }
     958                 : 
     959                 : /* -------------------------------------------------------------------- */
     960                 : /*      Try looking up the EPSG list                                    */
     961                 : /* -------------------------------------------------------------------- */
     962               0 :     if (!poSRS)
     963                 :     {
     964               0 :         poSRS = new OGRSpatialReference();
     965               0 :         if( poSRS->importFromEPSG( nId ) != OGRERR_NONE )
     966                 :         {
     967               0 :             delete poSRS;
     968               0 :             poSRS = NULL;
     969                 :         } 
     970                 :     }
     971                 : 
     972                 : /* -------------------------------------------------------------------- */
     973                 : /*      Add to the cache.                                               */
     974                 : /* -------------------------------------------------------------------- */
     975               0 :     if (poSRS)
     976                 :     {
     977               0 :         panSRID = (int *) CPLRealloc(panSRID,sizeof(int) * (nKnownSRID+1) );
     978                 :         papoSRS = (OGRSpatialReference **)
     979               0 :             CPLRealloc(papoSRS, sizeof(void*) * (nKnownSRID + 1) );
     980               0 :         panSRID[nKnownSRID] = nId;
     981               0 :         papoSRS[nKnownSRID] = poSRS;
     982               0 :         nKnownSRID++;
     983                 :     }
     984                 : 
     985               0 :     return poSRS;
     986                 : }
     987                 : 
     988                 : /************************************************************************/
     989                 : /*                             FetchSRSId()                             */
     990                 : /*                                                                      */
     991                 : /*      Fetch the id corresponding to an SRS, and if not found, add     */
     992                 : /*      it to the table.                                                */
     993                 : /************************************************************************/
     994                 : 
     995               0 : int OGRMSSQLSpatialDataSource::FetchSRSId( OGRSpatialReference * poSRS)
     996                 : 
     997                 : {
     998               0 :     char                *pszWKT = NULL;
     999               0 :     int                 nSRSId = 0;
    1000                 :     const char*         pszAuthorityName;
    1001                 : 
    1002               0 :     if( poSRS == NULL )
    1003               0 :         return 0;
    1004                 : 
    1005               0 :     OGRSpatialReference oSRS(*poSRS);
    1006               0 :     poSRS = NULL;
    1007                 : 
    1008               0 :     pszAuthorityName = oSRS.GetAuthorityName(NULL);
    1009                 : 
    1010               0 :     if( pszAuthorityName == NULL || strlen(pszAuthorityName) == 0 )
    1011                 :     {
    1012                 : /* -------------------------------------------------------------------- */
    1013                 : /*      Try to identify an EPSG code                                    */
    1014                 : /* -------------------------------------------------------------------- */
    1015               0 :         oSRS.AutoIdentifyEPSG();
    1016                 : 
    1017               0 :         pszAuthorityName = oSRS.GetAuthorityName(NULL);
    1018               0 :         if (pszAuthorityName != NULL && EQUAL(pszAuthorityName, "EPSG"))
    1019                 :         {
    1020               0 :             const char* pszAuthorityCode = oSRS.GetAuthorityCode(NULL);
    1021               0 :             if ( pszAuthorityCode != NULL && strlen(pszAuthorityCode) > 0 )
    1022                 :             {
    1023                 :                 /* Import 'clean' SRS */
    1024               0 :                 oSRS.importFromEPSG( atoi(pszAuthorityCode) );
    1025                 : 
    1026               0 :                 pszAuthorityName = oSRS.GetAuthorityName(NULL);
    1027                 :             }
    1028                 :         }
    1029                 :     }
    1030                 : /* -------------------------------------------------------------------- */
    1031                 : /*      Check whether the EPSG authority code is already mapped to a    */
    1032                 : /*      SRS ID.                                                         */
    1033                 : /* -------------------------------------------------------------------- */
    1034               0 :     int  nAuthorityCode = 0;
    1035               0 :     if( pszAuthorityName != NULL && EQUAL( pszAuthorityName, "EPSG" ) )
    1036                 :     {
    1037                 :         /* For the root authority name 'EPSG', the authority code
    1038                 :          * should always be integral
    1039                 :          */
    1040               0 :         nAuthorityCode = atoi( oSRS.GetAuthorityCode(NULL) );
    1041                 : 
    1042               0 :         CPLODBCStatement oStmt( &oSession );
    1043                 :         oStmt.Appendf("SELECT srid FROM spatial_ref_sys WHERE "
    1044                 :                          "auth_name = '%s' AND auth_srid = %d",
    1045                 :                          pszAuthorityName,
    1046               0 :                          nAuthorityCode );
    1047                 : 
    1048               0 :         if( oStmt.ExecuteSQL() && oStmt.Fetch() && oStmt.GetColData( 0 ) )
    1049                 :         {
    1050               0 :             nSRSId = atoi(oStmt.GetColData( 0 ));
    1051               0 :             return nSRSId;
    1052               0 :         }
    1053                 :     }
    1054                 : 
    1055                 : /* -------------------------------------------------------------------- */
    1056                 : /*      Translate SRS to WKT.                                           */
    1057                 : /* -------------------------------------------------------------------- */
    1058               0 :     if( oSRS.exportToWkt( &pszWKT ) != OGRERR_NONE )
    1059                 :     {
    1060               0 :         CPLFree(pszWKT);
    1061               0 :         return 0;
    1062                 :     }
    1063                 : 
    1064                 : /* -------------------------------------------------------------------- */
    1065                 : /*      Try to find in the existing table.                              */
    1066                 : /* -------------------------------------------------------------------- */
    1067               0 :     CPLODBCStatement oStmt( &oSession );
    1068                 : 
    1069               0 :     oStmt.Append( "SELECT srid FROM spatial_ref_sys WHERE srtext = ");
    1070               0 :     OGRMSSQLAppendEscaped(&oStmt, pszWKT);
    1071                 : 
    1072                 : /* -------------------------------------------------------------------- */
    1073                 : /*      We got it!  Return it.                                          */
    1074                 : /* -------------------------------------------------------------------- */
    1075               0 :     if( oStmt.ExecuteSQL() )
    1076                 :     {
    1077               0 :         if ( oStmt.Fetch() && oStmt.GetColData( 0 ) )
    1078                 :         {
    1079               0 :             nSRSId = atoi(oStmt.GetColData( 0 ));
    1080               0 :             CPLFree(pszWKT);
    1081               0 :             return nSRSId;
    1082                 :         }
    1083                 :     }
    1084                 :     else
    1085                 :     {
    1086                 :         /* probably the table is missing at all */
    1087               0 :         if( InitializeMetadataTables() != OGRERR_NONE )
    1088                 :         {
    1089               0 :             CPLFree(pszWKT);
    1090               0 :             return 0;
    1091                 :         }
    1092                 :     }
    1093                 : 
    1094                 : /* -------------------------------------------------------------------- */
    1095                 : /*      Try adding the SRS to the SRS table.                            */
    1096                 : /* -------------------------------------------------------------------- */
    1097               0 :     char    *pszProj4 = NULL;
    1098               0 :     if( oSRS.exportToProj4( &pszProj4 ) != OGRERR_NONE )
    1099                 :     {
    1100               0 :         CPLFree( pszProj4 );
    1101               0 :         CPLFree(pszWKT);
    1102               0 :         return 0;
    1103                 :     }
    1104                 : 
    1105                 : /* -------------------------------------------------------------------- */
    1106                 : /*      Check whether the auth_code can be used as srid.                */
    1107                 : /* -------------------------------------------------------------------- */
    1108               0 :     nSRSId = nAuthorityCode;
    1109                 : 
    1110               0 :     oStmt.Clear();
    1111               0 :     oSession.BeginTransaction();
    1112               0 :     if (nAuthorityCode > 0)
    1113                 :     {
    1114               0 :         oStmt.Appendf("SELECT srid FROM spatial_ref_sys where srid = %d", nAuthorityCode);
    1115               0 :         if ( oStmt.ExecuteSQL() && oStmt.Fetch())
    1116                 :         {
    1117               0 :             nSRSId = 0;
    1118                 :         }
    1119                 :     }
    1120                 : 
    1121                 : /* -------------------------------------------------------------------- */
    1122                 : /*      Get the current maximum srid in the srs table.                  */
    1123                 : /* -------------------------------------------------------------------- */
    1124                 :     
    1125               0 :     if (nSRSId == 0)
    1126                 :     {
    1127               0 :         oStmt.Clear();
    1128               0 :         oStmt.Append("SELECT COALESCE(MAX(srid) + 1, 32768) FROM spatial_ref_sys where srid between 32768 and 65536");
    1129                 : 
    1130               0 :         if ( oStmt.ExecuteSQL() && oStmt.Fetch() && oStmt.GetColData( 0 ) )
    1131                 :         {
    1132               0 :             nSRSId = atoi(oStmt.GetColData( 0 ));
    1133                 :         }
    1134                 :     }
    1135                 : 
    1136               0 :     if (nSRSId == 0)
    1137                 :     {
    1138                 :         /* unable to allocate srid */
    1139               0 :         oSession.RollbackTransaction();
    1140               0 :         CPLFree( pszProj4 );
    1141               0 :         CPLFree(pszWKT);
    1142               0 :         return 0;
    1143                 :     }
    1144                 :     
    1145               0 :     oStmt.Clear();
    1146               0 :     if( nAuthorityCode > 0 )
    1147                 :     {
    1148                 :         oStmt.Appendf(
    1149                 :                  "INSERT INTO spatial_ref_sys (srid, auth_srid, auth_name, srtext, proj4text) "
    1150               0 :                  "VALUES (%d, %d, ", nSRSId, nAuthorityCode );
    1151               0 :         OGRMSSQLAppendEscaped(&oStmt, pszAuthorityName);
    1152               0 :         oStmt.Append(", ");
    1153               0 :         OGRMSSQLAppendEscaped(&oStmt, pszWKT);
    1154               0 :         oStmt.Append(", ");
    1155               0 :         OGRMSSQLAppendEscaped(&oStmt, pszProj4);
    1156               0 :         oStmt.Append(")");
    1157                 :     }
    1158                 :     else
    1159                 :     {
    1160                 :         oStmt.Appendf(
    1161               0 :                  "INSERT INTO spatial_ref_sys (srid,srtext,proj4text) VALUES (%d, ", nSRSId);
    1162               0 :         OGRMSSQLAppendEscaped(&oStmt, pszWKT);
    1163               0 :         oStmt.Append(", ");
    1164               0 :         OGRMSSQLAppendEscaped(&oStmt, pszProj4);
    1165               0 :         oStmt.Append(")");
    1166                 :     }
    1167                 : 
    1168                 :     /* Free everything that was allocated. */
    1169               0 :     CPLFree( pszProj4 );
    1170               0 :     CPLFree( pszWKT);
    1171                 : 
    1172               0 :     if ( oStmt.ExecuteSQL() )
    1173               0 :         oSession.CommitTransaction();
    1174                 :     else
    1175               0 :         oSession.RollbackTransaction();
    1176                 : 
    1177               0 :     return nSRSId;
    1178                 : }
    1179                 : 

Generated by: LCOV version 1.7