~ubuntu-branches/debian/sid/gdal/sid

« back to all changes in this revision

Viewing changes to ogr/ogrsf_frmts/mssqlspatial/ogrmssqlspatialdatasource.cpp

  • Committer: Package Import Robot
  • Author(s): Francesco Paolo Lovergine
  • Date: 2012-05-07 15:04:42 UTC
  • mfrom: (5.5.16 experimental)
  • Revision ID: package-import@ubuntu.com-20120507150442-2eks97loeh6rq005
Tags: 1.9.0-1
* Ready for sid, starting transition.
* All symfiles updated to latest builds.
* Added dh_numpy call in debian/rules to depend on numpy ABI.
* Policy bumped to 3.9.3, no changes required.

Show diffs side-by-side

added added

removed removed

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