LTP GCOV extension - code coverage report
Current view: directory - ogr/ogrsf_frmts/mysql - ogrmysqltablelayer.cpp
Test: gdal_filtered.info
Date: 2010-07-12 Instrumented lines: 465
Code covered: 74.0 % Executed lines: 344

       1                 : /******************************************************************************
       2                 :  * $Id: ogrmysqltablelayer.cpp 14430 2008-05-10 18:42:32Z warmerdam $
       3                 :  *
       4                 :  * Project:  OpenGIS Simple Features Reference Implementation
       5                 :  * Purpose:  Implements OGRMySQLTableLayer class.
       6                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7                 :  * Author:   Howard Butler, hobu@hobu.net
       8                 :  *
       9                 :  ******************************************************************************
      10                 :  * Copyright (c) 2004, Frank Warmerdam <warmerdam@pobox.com>
      11                 :  *
      12                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      13                 :  * copy of this software and associated documentation files (the "Software"),
      14                 :  * to deal in the Software without restriction, including without limitation
      15                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      16                 :  * and/or sell copies of the Software, and to permit persons to whom the
      17                 :  * Software is furnished to do so, subject to the following conditions:
      18                 :  *
      19                 :  * The above copyright notice and this permission notice shall be included
      20                 :  * in all copies or substantial portions of the Software.
      21                 :  *
      22                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      23                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      24                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      25                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      26                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      27                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      28                 :  * DEALINGS IN THE SOFTWARE.
      29                 :  ****************************************************************************/
      30                 : 
      31                 : #include "cpl_conv.h"
      32                 : #include "cpl_string.h"
      33                 : #include "ogr_mysql.h"
      34                 : 
      35                 : CPL_CVSID("$Id: ogrmysqltablelayer.cpp 14430 2008-05-10 18:42:32Z warmerdam $");
      36                 : 
      37                 : /************************************************************************/
      38                 : /*                         OGRMySQLTableLayer()                         */
      39                 : /************************************************************************/
      40                 : 
      41                 : OGRMySQLTableLayer::OGRMySQLTableLayer( OGRMySQLDataSource *poDSIn, 
      42                 :                                   const char * pszTableName,
      43               4 :                                   int bUpdate, int nSRSIdIn )
      44                 : 
      45                 : {
      46               4 :     poDS = poDSIn;
      47                 : 
      48               4 :     pszQuery = NULL;
      49               4 :     pszWHERE = CPLStrdup( "" );
      50               4 :     pszQueryStatement = NULL;
      51                 :     
      52               4 :     bUpdateAccess = bUpdate;
      53                 : 
      54               4 :     iNextShapeId = 0;
      55                 : 
      56               4 :     nSRSId = nSRSIdIn;
      57                 : 
      58               4 :     poFeatureDefn = NULL;
      59               4 :     bLaunderColumnNames = TRUE;
      60               4 : }
      61                 : 
      62                 : /************************************************************************/
      63                 : /*                        ~OGRMySQLTableLayer()                         */
      64                 : /************************************************************************/
      65                 : 
      66               4 : OGRMySQLTableLayer::~OGRMySQLTableLayer()
      67                 : 
      68                 : {
      69               4 :     CPLFree( pszQuery );
      70               4 :     CPLFree( pszWHERE );
      71               4 : }
      72                 : 
      73                 : 
      74                 : /************************************************************************/
      75                 : /*                        Initialize()                                  */
      76                 : /*                                                                      */
      77                 : /*      Make sure we only do a ResetReading once we really have a       */
      78                 : /*      FieldDefn.  Otherwise, we'll segfault.  After you construct     */
      79                 : /*      the MySQLTableLayer, make sure to do pLayer->Initialize()       */
      80                 : /************************************************************************/
      81                 : 
      82               4 : OGRErr  OGRMySQLTableLayer::Initialize(const char * pszTableName)
      83                 : {
      84               4 :     poFeatureDefn = ReadTableDefinition( pszTableName );   
      85               4 :     if (poFeatureDefn)
      86                 :     {
      87               4 :         ResetReading();
      88               4 :         return OGRERR_NONE;
      89                 :     }
      90                 :     else
      91                 :     {
      92               0 :         return OGRERR_FAILURE;
      93                 :     }
      94                 : }
      95                 : 
      96                 : /************************************************************************/
      97                 : /*                        ReadTableDefinition()                         */
      98                 : /*                                                                      */
      99                 : /*      Build a schema from the named table.  Done by querying the      */
     100                 : /*      catalog.                                                        */
     101                 : /************************************************************************/
     102                 : 
     103               4 : OGRFeatureDefn *OGRMySQLTableLayer::ReadTableDefinition( const char *pszTable )
     104                 : 
     105                 : {
     106                 :     MYSQL_RES    *hResult;
     107                 :     char         szCommand[1024];
     108                 :     
     109                 : /* -------------------------------------------------------------------- */
     110                 : /*      Fire off commands to get back the schema of the table.          */
     111                 : /* -------------------------------------------------------------------- */
     112               4 :     sprintf( szCommand, "DESCRIBE `%s`", pszTable );
     113               4 :     pszGeomColumnTable = CPLStrdup(pszTable);
     114               4 :     if( mysql_query( poDS->GetConn(), szCommand ) )
     115                 :     {
     116               0 :         poDS->ReportError( "DESCRIBE Failed" );
     117               0 :         return FALSE;
     118                 :     }
     119                 : 
     120               4 :     hResult = mysql_store_result( poDS->GetConn() );
     121               4 :     if( hResult == NULL )
     122                 :     {
     123               0 :         poDS->ReportError( "mysql_store_result() failed on DESCRIBE result." );
     124               0 :         return FALSE;
     125                 :     }
     126                 : 
     127                 : /* -------------------------------------------------------------------- */
     128                 : /*      Parse the returned table information.                           */
     129                 : /* -------------------------------------------------------------------- */
     130               4 :     OGRFeatureDefn *poDefn = new OGRFeatureDefn( pszTable );
     131                 :     char           **papszRow;
     132                 : 
     133               4 :     poDefn->Reference();
     134                 : 
     135              16 :     while( (papszRow = mysql_fetch_row( hResult )) != NULL )
     136                 :     {
     137                 :         const char      *pszType;
     138               8 :         OGRFieldDefn    oField( papszRow[0], OFTString);
     139                 : 
     140               8 :         pszType = papszRow[1];
     141                 : 
     142               8 :         if( pszType == NULL )
     143               8 :             continue;
     144                 : 
     145               8 :         if( EQUAL(pszType,"varbinary")
     146                 :             || (strlen(pszType)>3 && EQUAL(pszType+strlen(pszType)-4,"blob")))
     147                 :         {
     148               0 :             oField.SetType( OFTBinary );
     149                 :         }
     150               8 :         else if( EQUAL(pszType,"varchar") 
     151                 :                  || EQUAL(pszType+strlen(pszType)-4,"enum") 
     152                 :                  || EQUAL(pszType+strlen(pszType)-4,"set") )
     153                 :         {
     154               0 :             oField.SetType( OFTString );
     155                 : 
     156                 :         }
     157               8 :         else if( EQUALN(pszType,"char",4)  )
     158                 :         {
     159               0 :             oField.SetType( OFTString );
     160                 :             char ** papszTokens;
     161                 : 
     162               0 :             papszTokens = CSLTokenizeString2(pszType,"(),",0);
     163                 :             
     164                 :             /* width is the second */
     165               0 :             oField.SetWidth(atoi(papszTokens[1]));
     166                 : 
     167               0 :             CSLDestroy( papszTokens );
     168               0 :             oField.SetType( OFTString );
     169                 : 
     170                 :         }
     171                 :         
     172               8 :         if(strlen(pszType)>3 && EQUAL(pszType+strlen(pszType)-4,"text"))
     173                 :         {
     174               0 :             oField.SetType( OFTString );            
     175                 :         }
     176               8 :         else if( EQUALN(pszType,"varchar",6)  )
     177                 :         {
     178                 :             /* 
     179                 :                pszType is usually in the form "varchar(15)" 
     180                 :                so we'll split it up and get the width and precision
     181                 :             */
     182                 :             
     183               0 :             oField.SetType( OFTString );
     184                 :             char ** papszTokens;
     185                 : 
     186               0 :             papszTokens = CSLTokenizeString2(pszType,"(),",0);
     187                 :             
     188                 :             /* width is the second */
     189               0 :             oField.SetWidth(atoi(papszTokens[1]));
     190                 : 
     191               0 :             CSLDestroy( papszTokens );
     192               0 :             oField.SetType( OFTString );
     193                 :         }
     194               8 :         else if( EQUALN(pszType,"int", 3) )
     195                 :         {
     196               4 :             oField.SetType( OFTInteger );
     197                 :         }
     198               4 :         else if( EQUALN(pszType,"tinyint", 7) )
     199                 :         {
     200               0 :             oField.SetType( OFTInteger );
     201                 :         }
     202               4 :         else if( EQUALN(pszType,"smallint", 8) )
     203                 :         {
     204               0 :             oField.SetType( OFTInteger );
     205                 :         }
     206               4 :         else if( EQUALN(pszType,"mediumint",9) )
     207                 :         {
     208               0 :             oField.SetType( OFTInteger );
     209                 :         }
     210               4 :         else if( EQUALN(pszType,"bigint",6) )
     211                 :         {
     212               0 :             oField.SetType( OFTInteger );
     213                 :         }
     214               4 :         else if( EQUALN(pszType,"decimal",7) )
     215                 :         {
     216                 :             /* 
     217                 :                pszType is usually in the form "decimal(15,2)" 
     218                 :                so we'll split it up and get the width and precision
     219                 :             */
     220               0 :             oField.SetType( OFTReal );
     221                 :             char ** papszTokens;
     222                 : 
     223               0 :             papszTokens = CSLTokenizeString2(pszType,"(),",0);
     224                 :             
     225                 :             /* width is the second and precision is the third */
     226               0 :             oField.SetWidth(atoi(papszTokens[1]));
     227               0 :             oField.SetPrecision(atoi(papszTokens[2]));
     228               0 :             CSLDestroy( papszTokens );
     229                 : 
     230                 : 
     231                 :         }
     232               4 :         else if( EQUALN(pszType,"float", 5) )
     233                 :         {
     234               0 :             oField.SetType( OFTReal );
     235                 :         }
     236               4 :         else if( EQUAL(pszType,"double") )
     237                 :         {
     238               0 :             oField.SetType( OFTReal );
     239                 :         }
     240               4 :         else if( EQUALN(pszType,"double",6) )
     241                 :         {
     242                 :             // double can also be double(15,2)
     243                 :             // so we'll handle this case here after 
     244                 :             // we check for just a regular double 
     245                 :             // without a width and precision specified
     246                 :             
     247               0 :             char ** papszTokens=NULL;
     248               0 :             papszTokens = CSLTokenizeString2(pszType,"(),",0);
     249                 :             /* width is the second and precision is the third */
     250               0 :             oField.SetWidth(atoi(papszTokens[1]));
     251               0 :             oField.SetPrecision(atoi(papszTokens[2]));
     252               0 :             CSLDestroy( papszTokens );  
     253                 : 
     254               0 :             oField.SetType( OFTReal );
     255                 :         }
     256               4 :         else if( EQUAL(pszType,"decimal") )
     257                 :         {
     258               0 :             oField.SetType( OFTReal );
     259                 :         }
     260               4 :         else if( EQUAL(pszType, "date") )
     261                 :         {
     262               0 :             oField.SetType( OFTDate );
     263                 :         }
     264               4 :         else if( EQUAL(pszType, "time") )
     265                 :         {
     266               0 :             oField.SetType( OFTTime );
     267                 :         }
     268               4 :         else if( EQUAL(pszType, "datetime") 
     269                 :                  || EQUAL(pszType, "timestamp") )
     270                 :         {
     271               0 :             oField.SetType( OFTDateTime );
     272                 :         }
     273               4 :         else if( EQUAL(pszType, "year") )  
     274                 :         {
     275               0 :             oField.SetType( OFTString );
     276               0 :             oField.SetWidth( 10 );
     277                 :         }
     278               4 :         else if( EQUAL(pszType, "geometry") ) 
     279                 :         {
     280               4 :             pszGeomColumn = CPLStrdup(papszRow[0]);
     281                 :             continue;
     282                 :         }
     283                 :         // Is this an integer primary key field?
     284               4 :         if( !bHasFid && papszRow[3] != NULL && EQUAL(papszRow[3],"PRI") 
     285                 :             && oField.GetType() == OFTInteger )
     286                 :         {
     287               4 :             bHasFid = TRUE;
     288               4 :             pszFIDColumn = CPLStrdup(oField.GetNameRef());
     289                 :             continue;
     290                 :         }
     291                 : 
     292               0 :         poDefn->AddFieldDefn( &oField );
     293                 :     }
     294                 : 
     295                 :     // set to none for now... if we have a geometry column it will be set layer.
     296               4 :     poDefn->SetGeomType( wkbNone );
     297                 : 
     298               4 :     if( hResult != NULL )
     299                 :     {
     300               4 :         mysql_free_result( hResult );
     301               4 :         hResultSet = NULL;
     302                 :     }
     303                 : 
     304               4 :     if( bHasFid )
     305                 :         CPLDebug( "MySQL", "table %s has FID column %s.",
     306               4 :                   pszTable, pszFIDColumn );
     307                 :     else
     308                 :         CPLDebug( "MySQL", 
     309                 :                   "table %s has no FID column, FIDs will not be reliable!",
     310               0 :                   pszTable );
     311                 : 
     312               4 :     if (pszGeomColumn) 
     313                 :     {
     314               4 :         char*        pszType=NULL;
     315                 :         
     316                 :         // set to unknown first
     317               4 :         poDefn->SetGeomType( wkbUnknown );
     318                 :         
     319                 :         sprintf(szCommand, "SELECT type, coord_dimension FROM geometry_columns WHERE f_table_name='%s'",
     320               4 :                 pszTable );
     321                 :         
     322               4 :         hResult = NULL;
     323               4 :         if( !mysql_query( poDS->GetConn(), szCommand ) )
     324               4 :             hResult = mysql_store_result( poDS->GetConn() );
     325                 : 
     326               4 :         papszRow = NULL;
     327               4 :         if( hResult != NULL )
     328               4 :             papszRow = mysql_fetch_row( hResult );
     329                 : 
     330               4 :         if( papszRow != NULL && papszRow[0] != NULL )
     331                 :         {
     332                 : 
     333               4 :             pszType = papszRow[0];
     334                 : 
     335               4 :             OGRwkbGeometryType nGeomType = wkbUnknown;
     336                 : 
     337                 :             // check only standard OGC geometry types
     338               4 :             if ( EQUAL(pszType, "POINT") )
     339               2 :                 nGeomType = wkbPoint;
     340               2 :             else if ( EQUAL(pszType,"LINESTRING"))
     341               0 :                 nGeomType = wkbLineString;
     342               2 :             else if ( EQUAL(pszType,"POLYGON"))
     343               0 :                 nGeomType = wkbPolygon;
     344               2 :             else if ( EQUAL(pszType,"MULTIPOINT"))
     345               0 :                 nGeomType = wkbMultiPoint;
     346               2 :             else if ( EQUAL(pszType,"MULTILINESTRING"))
     347               0 :                 nGeomType = wkbMultiLineString;
     348               2 :             else if ( EQUAL(pszType,"MULTIPOLYGON"))
     349               0 :                 nGeomType = wkbMultiPolygon;
     350               2 :             else if ( EQUAL(pszType,"GEOMETRYCOLLECTION"))
     351               0 :                 nGeomType = wkbGeometryCollection;
     352                 : 
     353               4 :             if( papszRow[1] != NULL && atoi(papszRow[1]) == 3 )
     354               0 :                 nGeomType = (OGRwkbGeometryType) (nGeomType | wkb25DBit);
     355                 : 
     356               4 :             poDefn->SetGeomType( nGeomType );
     357                 : 
     358                 :         } 
     359                 : 
     360               4 :         if( hResult != NULL )
     361               4 :             mysql_free_result( hResult );   //Free our query results for finding type.
     362               4 :       hResult = NULL;
     363                 :     } 
     364                 :  
     365                 :     // Fetch the SRID for this table now
     366               4 :     nSRSId = FetchSRSId(); 
     367               4 :     return poDefn;
     368                 : }
     369                 : 
     370                 : /************************************************************************/
     371                 : /*                          SetSpatialFilter()                          */
     372                 : /************************************************************************/
     373                 : 
     374               2 : void OGRMySQLTableLayer::SetSpatialFilter( OGRGeometry * poGeomIn )
     375                 : 
     376                 : {
     377               2 :     if( !InstallFilter( poGeomIn ) )
     378               0 :         return;
     379                 : 
     380               2 :     BuildWhere();
     381                 : 
     382               2 :     ResetReading();
     383                 : }
     384                 : 
     385                 : 
     386                 : 
     387                 : /************************************************************************/
     388                 : /*                             BuildWhere()                             */
     389                 : /*                                                                      */
     390                 : /*      Build the WHERE statement appropriate to the current set of     */
     391                 : /*      criteria (spatial and attribute queries).                       */
     392                 : /************************************************************************/
     393                 : 
     394              22 : void OGRMySQLTableLayer::BuildWhere()
     395                 : 
     396                 : {
     397              22 :     CPLFree( pszWHERE );
     398              22 :     pszWHERE = (char*)CPLMalloc(500 + ((pszQuery) ? strlen(pszQuery) : 0));
     399              22 :     pszWHERE[0] = '\0';
     400                 : 
     401              22 :     if( m_poFilterGeom != NULL && pszGeomColumn )
     402                 :     {
     403                 :         char szEnvelope[4096];
     404               3 :         OGREnvelope  sEnvelope;
     405               3 :         szEnvelope[0] = '\0';
     406                 :         
     407                 :         //POLYGON((MINX MINY, MAXX MINY, MAXX MAXY, MINX MAXY, MINX MINY))
     408               3 :         m_poFilterGeom->getEnvelope( &sEnvelope );
     409                 :         
     410                 :         sprintf(szEnvelope,
     411                 :                 "POLYGON((%.12f %.12f, %.12f %.12f, %.12f %.12f, %.12f %.12f, %.12f %.12f))",
     412                 :                 sEnvelope.MinX, sEnvelope.MinY,
     413                 :                 sEnvelope.MaxX, sEnvelope.MinY,
     414                 :                 sEnvelope.MaxX, sEnvelope.MaxY,
     415                 :                 sEnvelope.MinX, sEnvelope.MaxY,
     416               3 :                 sEnvelope.MinX, sEnvelope.MinY);
     417                 : 
     418                 :         sprintf( pszWHERE,
     419                 :                  "WHERE MBRIntersects(GeomFromText('%s'), `%s`)",
     420                 :                  szEnvelope,
     421               3 :                  pszGeomColumn);
     422                 : 
     423                 :     }
     424                 : 
     425              22 :     if( pszQuery != NULL )
     426                 :     {
     427              13 :         if( strlen(pszWHERE) == 0 )
     428              12 :             sprintf( pszWHERE, "WHERE %s ", pszQuery  );
     429                 :         else
     430               1 :             sprintf( pszWHERE+strlen(pszWHERE), "&& %s ", pszQuery );
     431                 :     }
     432              22 : }
     433                 : 
     434                 : /************************************************************************/
     435                 : /*                      BuildFullQueryStatement()                       */
     436                 : /************************************************************************/
     437                 : 
     438              56 : void OGRMySQLTableLayer::BuildFullQueryStatement()
     439                 : 
     440                 : {
     441              56 :     if( pszQueryStatement != NULL )
     442                 :     {
     443              52 :         CPLFree( pszQueryStatement );
     444              52 :         pszQueryStatement = NULL;
     445                 :     }
     446                 : 
     447              56 :     char *pszFields = BuildFields();
     448                 : 
     449                 :     pszQueryStatement = (char *) 
     450                 :         CPLMalloc(strlen(pszFields)+strlen(pszWHERE)
     451              56 :                   +strlen(poFeatureDefn->GetName()) + 40);
     452                 :     sprintf( pszQueryStatement,
     453                 :              "SELECT %s FROM `%s` %s", 
     454              56 :              pszFields, poFeatureDefn->GetName(), pszWHERE );
     455                 :     
     456              56 :     CPLFree( pszFields );
     457              56 : }
     458                 : 
     459                 : /************************************************************************/
     460                 : /*                            ResetReading()                            */
     461                 : /************************************************************************/
     462                 : 
     463              56 : void OGRMySQLTableLayer::ResetReading()
     464                 : 
     465                 : {
     466              56 :     BuildFullQueryStatement();
     467                 : 
     468              56 :     OGRMySQLLayer::ResetReading();
     469              56 : }
     470                 : 
     471                 : /************************************************************************/
     472                 : /*                            BuildFields()                             */
     473                 : /*                                                                      */
     474                 : /*      Build list of fields to fetch, performing any required          */
     475                 : /*      transformations (such as on geometry).                          */
     476                 : /************************************************************************/
     477                 : 
     478              57 : char *OGRMySQLTableLayer::BuildFields()
     479                 : 
     480                 : {
     481                 :     int         i, nSize;
     482                 :     char        *pszFieldList;
     483                 : 
     484              57 :     nSize = 25;
     485              57 :     if( pszGeomColumn )
     486              57 :         nSize += strlen(pszGeomColumn);
     487                 : 
     488              57 :     if( bHasFid )
     489              57 :         nSize += strlen(pszFIDColumn);
     490                 :         
     491                 : 
     492             245 :     for( i = 0; i < poFeatureDefn->GetFieldCount(); i++ )
     493             188 :         nSize += strlen(poFeatureDefn->GetFieldDefn(i)->GetNameRef()) + 6;
     494                 : 
     495              57 :     pszFieldList = (char *) CPLMalloc(nSize);
     496              57 :     pszFieldList[0] = '\0';
     497                 : 
     498              57 :     if( bHasFid && poFeatureDefn->GetFieldIndex( pszFIDColumn ) == -1 )
     499              57 :         sprintf( pszFieldList, "`%s`", pszFIDColumn );
     500                 : 
     501              57 :     if( pszGeomColumn )
     502                 :     {
     503              57 :         if( strlen(pszFieldList) > 0 )
     504              57 :             strcat( pszFieldList, ", " );
     505                 : 
     506                 :     /* ------------------------------------------------------------ */
     507                 :     /*      Geometry returned from MySQL is as WKB, with the        */
     508                 :         /*      first 4 bytes being an int that defines the SRID        */
     509                 :         /*      and the rest being the WKB.                             */
     510                 :     /* ------------------------------------------------------------ */            
     511                 :         sprintf( pszFieldList+strlen(pszFieldList), 
     512              57 :                  "`%s` `%s`", pszGeomColumn, pszGeomColumn );
     513                 :     }
     514                 : 
     515             245 :     for( i = 0; i < poFeatureDefn->GetFieldCount(); i++ )
     516                 :     {
     517             188 :         const char *pszName = poFeatureDefn->GetFieldDefn(i)->GetNameRef();
     518                 : 
     519             188 :         if( strlen(pszFieldList) > 0 )
     520             188 :             strcat( pszFieldList, ", " );
     521                 : 
     522             188 :         strcat( pszFieldList, "`");
     523             188 :         strcat( pszFieldList, pszName );
     524             188 :         strcat( pszFieldList, "`");
     525                 :     }
     526                 : 
     527              57 :     CPLAssert( (int) strlen(pszFieldList) < nSize );
     528                 : 
     529              57 :     return pszFieldList;
     530                 : }
     531                 : 
     532                 : /************************************************************************/
     533                 : /*                         SetAttributeFilter()                         */
     534                 : /************************************************************************/
     535                 : 
     536              20 : OGRErr OGRMySQLTableLayer::SetAttributeFilter( const char *pszQuery )
     537                 : 
     538                 : {
     539              20 :     CPLFree( this->pszQuery );
     540                 : 
     541              27 :     if( pszQuery == NULL || strlen(pszQuery) == 0 )
     542               7 :         this->pszQuery = NULL;
     543                 :     else
     544              13 :         this->pszQuery = CPLStrdup( pszQuery );
     545                 : 
     546              20 :     BuildWhere();
     547                 : 
     548              20 :     ResetReading();
     549                 : 
     550              20 :     return OGRERR_NONE;
     551                 : }
     552                 : 
     553                 : /************************************************************************/
     554                 : /*                           TestCapability()                           */
     555                 : /************************************************************************/
     556                 : 
     557               0 : int OGRMySQLTableLayer::TestCapability( const char * pszCap )
     558                 : 
     559                 : {
     560               0 :     if( EQUAL(pszCap,OLCRandomRead) )
     561               0 :         return bHasFid;
     562                 : 
     563               0 :     else if( EQUAL(pszCap,OLCFastFeatureCount) )
     564               0 :         return TRUE;
     565                 : 
     566               0 :     else if( EQUAL(pszCap,OLCFastSpatialFilter) )
     567               0 :         return TRUE;
     568                 : 
     569               0 :     else if( EQUAL(pszCap,OLCFastGetExtent) )
     570               0 :         return TRUE;
     571                 : 
     572               0 :     else if( EQUAL(pszCap,OLCCreateField) )
     573               0 :         return bUpdateAccess;
     574                 : 
     575               0 :     else if( EQUAL(pszCap,OLCDeleteFeature) )
     576               0 :         return bUpdateAccess;
     577                 : 
     578               0 :     else if( EQUAL(pszCap,OLCRandomWrite) )
     579               0 :         return bUpdateAccess;
     580                 : 
     581               0 :     else if( EQUAL(pszCap,OLCSequentialWrite) )
     582               0 :         return bUpdateAccess;
     583                 : 
     584                 :     else
     585               0 :         return FALSE;
     586                 : }
     587                 : 
     588                 : /************************************************************************/
     589                 : /*                             SetFeature()                             */
     590                 : /*                                                                      */
     591                 : /*      SetFeature() is implemented by dropping the old copy of the     */
     592                 : /*      feature in question (if there is one) and then creating a       */
     593                 : /*      new one with the provided feature id.                           */
     594                 : /************************************************************************/
     595                 : 
     596               1 : OGRErr OGRMySQLTableLayer::SetFeature( OGRFeature *poFeature )
     597                 : 
     598                 : {
     599                 :     OGRErr eErr;
     600                 : 
     601               1 :     if( poFeature->GetFID() == OGRNullFID )
     602                 :     {
     603                 :         CPLError( CE_Failure, CPLE_AppDefined,
     604               0 :                   "FID required on features given to SetFeature()." );
     605               0 :         return OGRERR_FAILURE;
     606                 :     }
     607                 : 
     608               1 :     eErr = DeleteFeature( poFeature->GetFID() );
     609               1 :     if( eErr != OGRERR_NONE )
     610               0 :         return eErr;
     611                 : 
     612               1 :     return CreateFeature( poFeature );
     613                 : }
     614                 : 
     615                 : /************************************************************************/
     616                 : /*                           DeleteFeature()                            */
     617                 : /************************************************************************/
     618                 : 
     619               2 : OGRErr OGRMySQLTableLayer::DeleteFeature( long nFID )
     620                 : 
     621                 : {
     622               2 :     MYSQL_RES           *hResult=NULL;
     623               2 :     CPLString           osCommand;
     624                 : 
     625                 : 
     626                 : /* -------------------------------------------------------------------- */
     627                 : /*      We can only delete features if we have a well defined FID       */
     628                 : /*      column to target.                                               */
     629                 : /* -------------------------------------------------------------------- */
     630               2 :     if( !bHasFid )
     631                 :     {
     632                 :         CPLError( CE_Failure, CPLE_AppDefined,
     633                 :                   "DeleteFeature(%ld) failed.  Unable to delete features "
     634                 :                   "in tables without\n a recognised FID column.",
     635               0 :                   nFID );
     636               0 :         return OGRERR_FAILURE;
     637                 : 
     638                 :     }
     639                 : 
     640                 : /* -------------------------------------------------------------------- */
     641                 : /*      Form the statement to drop the record.                          */
     642                 : /* -------------------------------------------------------------------- */
     643                 :     osCommand.Printf( "DELETE FROM `%s` WHERE `%s` = %ld",
     644               2 :                       poFeatureDefn->GetName(), pszFIDColumn, nFID );
     645                 :                       
     646                 : /* -------------------------------------------------------------------- */
     647                 : /*      Execute the delete.                                             */
     648                 : /* -------------------------------------------------------------------- */
     649               2 :     poDS->InterruptLongResult();
     650               2 :     if( mysql_query(poDS->GetConn(), osCommand.c_str() ) ){   
     651               0 :         poDS->ReportError(  osCommand.c_str() );
     652               0 :         return OGRERR_FAILURE;   
     653                 :     }
     654                 : 
     655                 :     // make sure to attempt to free results of successful queries
     656               2 :     hResult = mysql_store_result( poDS->GetConn() );
     657               2 :     if( hResult != NULL )
     658               0 :         mysql_free_result( hResult );
     659               2 :     hResult = NULL;
     660                 :     
     661               2 :     return OGRERR_NONE;
     662                 : }
     663                 : 
     664                 : 
     665                 : /************************************************************************/
     666                 : /*                       CreateFeature()                                */
     667                 : /************************************************************************/
     668                 : 
     669              21 : OGRErr OGRMySQLTableLayer::CreateFeature( OGRFeature *poFeature )
     670                 : 
     671                 : {
     672              21 :     MYSQL_RES           *hResult=NULL;
     673              21 :     CPLString           osCommand;
     674              21 :     int                 i, bNeedComma = FALSE;
     675                 : 
     676                 : /* -------------------------------------------------------------------- */
     677                 : /*      Form the INSERT command.                                        */
     678                 : /* -------------------------------------------------------------------- */
     679              21 :     osCommand.Printf( "INSERT INTO `%s` (", poFeatureDefn->GetName() );
     680                 : 
     681              21 :     if( poFeature->GetGeometryRef() != NULL )
     682                 :     {
     683              19 :         osCommand = osCommand + "`" + pszGeomColumn + "` ";
     684              19 :         bNeedComma = TRUE;
     685                 :     }
     686                 : 
     687              21 :     if( poFeature->GetFID() != OGRNullFID && pszFIDColumn != NULL )
     688                 :     {
     689               1 :         if( bNeedComma )
     690               1 :             osCommand += ", ";
     691                 :         
     692               1 :         osCommand = osCommand + "`" + pszFIDColumn + "` ";
     693               1 :         bNeedComma = TRUE;
     694                 :     }
     695                 : 
     696              97 :     for( i = 0; i < poFeatureDefn->GetFieldCount(); i++ )
     697                 :     {
     698              76 :         if( !poFeature->IsFieldSet( i ) )
     699              32 :             continue;
     700                 : 
     701              44 :         if( !bNeedComma )
     702               2 :             bNeedComma = TRUE;
     703                 :         else
     704              42 :             osCommand += ", ";
     705                 : 
     706                 :         osCommand = osCommand + "`"
     707              44 :              + poFeatureDefn->GetFieldDefn(i)->GetNameRef() + "`";
     708                 :     }
     709                 : 
     710              21 :     osCommand += ") VALUES (";
     711                 : 
     712                 :     // Set the geometry 
     713              21 :     bNeedComma = poFeature->GetGeometryRef() != NULL;
     714              21 :     if( poFeature->GetGeometryRef() != NULL)
     715                 :     {
     716              19 :         char    *pszWKT = NULL;
     717                 : 
     718              19 :         if( poFeature->GetGeometryRef() != NULL )
     719                 :         {
     720              19 :             OGRGeometry *poGeom = (OGRGeometry *) poFeature->GetGeometryRef();
     721                 :             
     722              19 :             poGeom->closeRings();
     723              19 :             poGeom->flattenTo2D();
     724              19 :             poGeom->exportToWkt( &pszWKT );
     725                 :         }
     726                 : 
     727              19 :         if( pszWKT != NULL )
     728                 :         {
     729                 : 
     730                 :             osCommand += 
     731                 :                 CPLString().Printf(
     732              19 :                     "GeometryFromText('%s',%d) ", pszWKT, nSRSId );
     733                 : 
     734              19 :             OGRFree( pszWKT );
     735                 :         }
     736                 :         else
     737               0 :             osCommand += "''";
     738                 :     }
     739                 : 
     740                 : 
     741                 :     // Set the FID 
     742              21 :     if( poFeature->GetFID() != OGRNullFID && pszFIDColumn != NULL )
     743                 :     {
     744               1 :         if( bNeedComma )
     745               1 :             osCommand += ", ";
     746               1 :         osCommand += CPLString().Printf( "%ld ", poFeature->GetFID() );
     747               1 :         bNeedComma = TRUE;
     748                 :     }
     749                 : 
     750              97 :     for( i = 0; i < poFeatureDefn->GetFieldCount(); i++ )
     751                 :     {
     752              76 :         if( !poFeature->IsFieldSet( i ) )
     753              32 :             continue;
     754                 : 
     755              44 :         if( bNeedComma )
     756              42 :             osCommand += ", ";
     757                 :         else
     758               2 :             bNeedComma = TRUE;
     759                 : 
     760              44 :         const char *pszStrValue = poFeature->GetFieldAsString(i);
     761                 : 
     762              44 :         if( poFeatureDefn->GetFieldDefn(i)->GetType() != OFTInteger
     763                 :                  && poFeatureDefn->GetFieldDefn(i)->GetType() != OFTReal
     764                 :                  && poFeatureDefn->GetFieldDefn(i)->GetType() != OFTBinary )
     765                 :         {
     766                 :             int         iChar;
     767                 : 
     768                 :             //We need to quote and escape string fields. 
     769              24 :             osCommand += "'";
     770                 : 
     771             158 :             for( iChar = 0; pszStrValue[iChar] != '\0'; iChar++ )
     772                 :             {
     773             135 :                 if( poFeatureDefn->GetFieldDefn(i)->GetType() != OFTIntegerList
     774                 :                     && poFeatureDefn->GetFieldDefn(i)->GetType() != OFTRealList
     775                 :                     && poFeatureDefn->GetFieldDefn(i)->GetWidth() > 0
     776                 :                     && iChar == poFeatureDefn->GetFieldDefn(i)->GetWidth() )
     777                 :                 {
     778                 :                     CPLDebug( "MYSQL",
     779                 :                               "Truncated %s field value, it was too long.",
     780               1 :                               poFeatureDefn->GetFieldDefn(i)->GetNameRef() );
     781               1 :                     break;
     782                 :                 }
     783                 : 
     784             135 :                 if( pszStrValue[iChar] == '\\'
     785                 :                     || pszStrValue[iChar] == '\'' )
     786                 :                 {
     787               1 :                     osCommand += '\\';
     788               1 :                     osCommand += pszStrValue[iChar];
     789                 :                 }
     790                 :                 else
     791             133 :                     osCommand += pszStrValue[iChar];
     792                 :             }
     793                 : 
     794              24 :             osCommand += "'";
     795                 :         }
     796              20 :         else if( poFeatureDefn->GetFieldDefn(i)->GetType() == OFTBinary )
     797                 :         {
     798               0 :             int binaryCount = 0;
     799               0 :             GByte* binaryData = poFeature->GetFieldAsBinary(i, &binaryCount);
     800               0 :             char* pszHexValue = CPLBinaryToHex( binaryCount, binaryData );
     801                 : 
     802               0 :             osCommand += "x'";
     803               0 :             osCommand += pszHexValue;
     804               0 :             osCommand += "'";
     805                 : 
     806               0 :             CPLFree( pszHexValue );
     807                 :         }
     808                 :         else
     809                 :         {
     810              20 :             osCommand += pszStrValue;
     811                 :         }
     812                 : 
     813                 :     }
     814                 : 
     815              21 :     osCommand += ")";
     816                 :     
     817              21 :     int nQueryResult = mysql_query(poDS->GetConn(), osCommand.c_str() );
     818              21 :     const my_ulonglong nFID = mysql_insert_id( poDS->GetConn() );
     819                 :     
     820              21 :     if( nQueryResult ){   
     821               1 :         int eErrorCode = mysql_errno(poDS->GetConn());
     822               1 :         if (eErrorCode == 1153) {//ER_NET_PACKET_TOO_LARGE)
     823               0 :             poDS->ReportError("CreateFeature failed because the MySQL server " \
     824                 :                               "cannot read the entire query statement.  Increase " \
     825                 :                               "the size of statements your server will allow by " \
     826                 :                               "altering the 'max_allowed_packet' parameter in "\
     827                 :                               "your MySQL server configuration.");
     828                 :         }
     829                 :         else
     830                 :         {
     831               1 :         CPLDebug("MYSQL","Error number %d", eErrorCode);
     832               1 :             poDS->ReportError(  osCommand.c_str() );
     833                 :         }
     834                 : 
     835                 :         // make sure to attempt to free results
     836               1 :         hResult = mysql_store_result( poDS->GetConn() );
     837               1 :         if( hResult != NULL )
     838               0 :             mysql_free_result( hResult );
     839               1 :         hResult = NULL;
     840                 :             
     841               1 :         return OGRERR_FAILURE;   
     842                 :     }
     843                 : 
     844              20 :     if( nFID > 0 ) {
     845              20 :         poFeature->SetFID( nFID );
     846                 :     }
     847                 : 
     848                 :     // make sure to attempt to free results of successful queries
     849              20 :     hResult = mysql_store_result( poDS->GetConn() );
     850              20 :     if( hResult != NULL )
     851               0 :         mysql_free_result( hResult );
     852              20 :     hResult = NULL;
     853                 :     
     854              20 :     return OGRERR_NONE;
     855                 : 
     856                 : }
     857                 : /************************************************************************/
     858                 : /*                            CreateField()                             */
     859                 : /************************************************************************/
     860                 : 
     861               8 : OGRErr OGRMySQLTableLayer::CreateField( OGRFieldDefn *poFieldIn, int bApproxOK )
     862                 : 
     863                 : {
     864                 : 
     865               8 :     MYSQL_RES           *hResult=NULL;
     866                 :     char            szCommand[1024];
     867                 :     
     868                 :     char                szFieldType[256];
     869               8 :     OGRFieldDefn        oField( poFieldIn );
     870                 : 
     871                 : /* -------------------------------------------------------------------- */
     872                 : /*      Do we want to "launder" the column names into Postgres          */
     873                 : /*      friendly format?                                                */
     874                 : /* -------------------------------------------------------------------- */
     875               8 :     if( bLaunderColumnNames )
     876                 :     {
     877               8 :         char    *pszSafeName = poDS->LaunderName( oField.GetNameRef() );
     878                 : 
     879               8 :         oField.SetName( pszSafeName );
     880               8 :         CPLFree( pszSafeName );
     881                 : 
     882                 :     }
     883                 : 
     884                 : /* -------------------------------------------------------------------- */
     885                 : /*      Work out the MySQL type.                                        */
     886                 : /* -------------------------------------------------------------------- */
     887               8 :     if( oField.GetType() == OFTInteger )
     888                 :     {
     889               1 :         if( oField.GetWidth() > 0 && bPreservePrecision )
     890               0 :             sprintf( szFieldType, "DECIMAL(%d,0)", oField.GetWidth() );
     891                 :         else
     892               1 :             strcpy( szFieldType, "INTEGER" );
     893                 :     }
     894               7 :     else if( oField.GetType() == OFTReal )
     895                 :     {
     896               1 :         if( oField.GetWidth() > 0 && oField.GetPrecision() > 0
     897                 :             && bPreservePrecision )
     898                 :             sprintf( szFieldType, "DOUBLE(%d,%d)",
     899               0 :                      oField.GetWidth(), oField.GetPrecision() );
     900                 :         else
     901               1 :             strcpy( szFieldType, "DOUBLE" );
     902                 :     }
     903                 : 
     904               6 :     else if( oField.GetType() == OFTDate )
     905                 :     {
     906               0 :         sprintf( szFieldType, "DATE" );
     907                 :     }
     908                 : 
     909               6 :     else if( oField.GetType() == OFTDateTime )
     910                 :     {
     911               0 :         sprintf( szFieldType, "DATETIME" );
     912                 :     }
     913                 : 
     914               6 :     else if( oField.GetType() == OFTTime )
     915                 :     {
     916               0 :         sprintf( szFieldType, "TIME" );
     917                 :     }
     918                 : 
     919               6 :     else if( oField.GetType() == OFTBinary )
     920                 :     {
     921               0 :         sprintf( szFieldType, "LONGBLOB" );
     922                 :     }
     923                 : 
     924               6 :     else if( oField.GetType() == OFTString )
     925                 :     {
     926               6 :         if( oField.GetWidth() == 0 || !bPreservePrecision )
     927               5 :             strcpy( szFieldType, "TEXT" );
     928                 :         else
     929               1 :             sprintf( szFieldType, "VARCHAR(%d)", oField.GetWidth() );
     930                 :     }
     931               0 :     else if( bApproxOK )
     932                 :     {
     933                 :         CPLError( CE_Warning, CPLE_NotSupported,
     934                 :                   "Can't create field %s with type %s on MySQL layers.  Creating as TEXT.",
     935                 :                   oField.GetNameRef(),
     936               0 :                   OGRFieldDefn::GetFieldTypeName(oField.GetType()) );
     937               0 :         strcpy( szFieldType, "TEXT" );
     938                 :     }
     939                 :     else
     940                 :     {
     941                 :         CPLError( CE_Failure, CPLE_NotSupported,
     942                 :                   "Can't create field %s with type %s on MySQL layers.",
     943                 :                   oField.GetNameRef(),
     944               0 :                   OGRFieldDefn::GetFieldTypeName(oField.GetType()) );
     945                 : 
     946               0 :         return OGRERR_FAILURE;
     947                 :     }
     948                 : 
     949                 :     sprintf( szCommand,
     950                 :              "ALTER TABLE `%s` ADD COLUMN `%s` %s",
     951               8 :              poFeatureDefn->GetName(), oField.GetNameRef(), szFieldType );
     952                 : 
     953               8 :     if( mysql_query(poDS->GetConn(), szCommand ) )
     954                 :     {
     955               0 :         poDS->ReportError( szCommand );
     956               0 :         return OGRERR_FAILURE;
     957                 :     }
     958                 : 
     959                 :     // make sure to attempt to free results of successful queries
     960               8 :     hResult = mysql_store_result( poDS->GetConn() );
     961               8 :     if( hResult != NULL )
     962               0 :         mysql_free_result( hResult );
     963               8 :     hResult = NULL;   
     964                 : 
     965               8 :     poFeatureDefn->AddFieldDefn( &oField );    
     966                 :     
     967               8 :     return OGRERR_NONE;
     968                 : }
     969                 : 
     970                 : 
     971                 : /************************************************************************/
     972                 : /*                             GetFeature()                             */
     973                 : /************************************************************************/
     974                 : 
     975               1 : OGRFeature *OGRMySQLTableLayer::GetFeature( long nFeatureId )
     976                 : 
     977                 : {
     978               1 :     if( pszFIDColumn == NULL )
     979               0 :         return OGRMySQLLayer::GetFeature( nFeatureId );
     980                 : 
     981                 : /* -------------------------------------------------------------------- */
     982                 : /*      Discard any existing resultset.                                 */
     983                 : /* -------------------------------------------------------------------- */
     984               1 :     ResetReading();
     985                 : 
     986                 : /* -------------------------------------------------------------------- */
     987                 : /*      Prepare query command that will just fetch the one record of    */
     988                 : /*      interest.                                                       */
     989                 : /* -------------------------------------------------------------------- */
     990               1 :     char        *pszFieldList = BuildFields();
     991               1 :     char        *pszCommand = (char *) CPLMalloc(strlen(pszFieldList)+2000);
     992                 : 
     993                 :     sprintf( pszCommand, 
     994                 :              "SELECT %s FROM `%s` WHERE `%s` = %ld", 
     995                 :              pszFieldList, poFeatureDefn->GetName(), pszFIDColumn, 
     996               1 :              nFeatureId );
     997               1 :     CPLFree( pszFieldList );
     998                 : 
     999                 : /* -------------------------------------------------------------------- */
    1000                 : /*      Issue the command.                                              */
    1001                 : /* -------------------------------------------------------------------- */
    1002               1 :     if( mysql_query( poDS->GetConn(), pszCommand ) )
    1003                 :     {
    1004               0 :         poDS->ReportError( pszCommand );
    1005               0 :         return NULL;
    1006                 :     }
    1007               1 :     CPLFree( pszCommand );
    1008                 : 
    1009               1 :     hResultSet = mysql_store_result( poDS->GetConn() );
    1010               1 :     if( hResultSet == NULL )
    1011                 :     {
    1012               0 :         poDS->ReportError( "mysql_store_result() failed on query." );
    1013               0 :         return NULL;
    1014                 :     }
    1015                 : 
    1016                 : /* -------------------------------------------------------------------- */
    1017                 : /*      Fetch the result record.                                        */
    1018                 : /* -------------------------------------------------------------------- */
    1019                 :     char **papszRow;
    1020                 :     unsigned long *panLengths;
    1021                 : 
    1022               1 :     papszRow = mysql_fetch_row( hResultSet );
    1023               1 :     if( papszRow == NULL )
    1024               0 :         return NULL;
    1025                 : 
    1026               1 :     panLengths = mysql_fetch_lengths( hResultSet );
    1027                 : 
    1028                 : /* -------------------------------------------------------------------- */
    1029                 : /*      Transform into a feature.                                       */
    1030                 : /* -------------------------------------------------------------------- */
    1031               1 :     iNextShapeId = nFeatureId;
    1032                 : 
    1033               1 :     OGRFeature *poFeature = RecordToFeature( papszRow, panLengths );
    1034                 : 
    1035               1 :     iNextShapeId = 0;
    1036                 : 
    1037                 : /* -------------------------------------------------------------------- */
    1038                 : /*      Cleanup                                                         */
    1039                 : /* -------------------------------------------------------------------- */
    1040               1 :     if( hResultSet != NULL )
    1041               1 :         mysql_free_result( hResultSet );
    1042               1 :     hResultSet = NULL;
    1043                 : 
    1044               1 :     return poFeature;
    1045                 : }
    1046                 : 
    1047                 : /************************************************************************/
    1048                 : /*                          GetFeatureCount()                           */
    1049                 : /*                                                                      */
    1050                 : /*      If a spatial filter is in effect, we turn control over to       */
    1051                 : /*      the generic counter.  Otherwise we return the total count.      */
    1052                 : /*      Eventually we should consider implementing a more efficient     */
    1053                 : /*      way of counting features matching a spatial query.              */
    1054                 : /************************************************************************/
    1055                 : 
    1056               5 : int OGRMySQLTableLayer::GetFeatureCount( int bForce )
    1057                 : 
    1058                 : {
    1059                 : /* -------------------------------------------------------------------- */
    1060                 : /*      Ensure any active long result is interrupted.                   */
    1061                 : /* -------------------------------------------------------------------- */
    1062               5 :     poDS->InterruptLongResult();
    1063                 :     
    1064                 : /* -------------------------------------------------------------------- */
    1065                 : /*      Issue the appropriate select command.                           */
    1066                 : /* -------------------------------------------------------------------- */
    1067                 :     MYSQL_RES    *hResult;
    1068                 :     const char         *pszCommand;
    1069                 : 
    1070                 :     pszCommand = CPLSPrintf( "SELECT COUNT(*) FROM `%s` %s", 
    1071               5 :                              poFeatureDefn->GetName(), pszWHERE );
    1072                 : 
    1073               5 :     if( mysql_query( poDS->GetConn(), pszCommand ) )
    1074                 :     {
    1075               0 :         poDS->ReportError( pszCommand );
    1076               0 :         return FALSE;
    1077                 :     }
    1078                 : 
    1079               5 :     hResult = mysql_store_result( poDS->GetConn() );
    1080               5 :     if( hResult == NULL )
    1081                 :     {
    1082               0 :         poDS->ReportError( "mysql_store_result() failed on SELECT COUNT(*)." );
    1083               0 :         return FALSE;
    1084                 :     }
    1085                 :     
    1086                 : /* -------------------------------------------------------------------- */
    1087                 : /*      Capture the result.                                             */
    1088                 : /* -------------------------------------------------------------------- */
    1089               5 :     char **papszRow = mysql_fetch_row( hResult );
    1090               5 :     int nCount = 0;
    1091                 : 
    1092               5 :     if( papszRow != NULL && papszRow[0] != NULL )
    1093               5 :         nCount = atoi(papszRow[0]);
    1094                 : 
    1095               5 :     if( hResult != NULL )
    1096               5 :         mysql_free_result( hResult );
    1097               5 :     hResult = NULL;
    1098                 :     
    1099               5 :     return nCount;
    1100                 : }
    1101                 : 
    1102                 : /************************************************************************/
    1103                 : /*                          GetExtent()         */
    1104                 : /*                                                                      */
    1105                 : /*      Retrieve the MBR of the MySQL table.  This should be made more  */
    1106                 : /*      in the future when MySQL adds support for a single MBR query    */
    1107                 : /*      like PostgreSQL.            */
    1108                 : /************************************************************************/
    1109                 : 
    1110               1 : OGRErr OGRMySQLTableLayer::GetExtent(OGREnvelope *psExtent, int bForce )
    1111                 : 
    1112                 : {
    1113               1 :   if( GetLayerDefn()->GetGeomType() == wkbNone )
    1114                 :     {
    1115               0 :         psExtent->MinX = 0.0;
    1116               0 :         psExtent->MaxX = 0.0;
    1117               0 :         psExtent->MinY = 0.0;
    1118               0 :         psExtent->MaxY = 0.0;
    1119                 :         
    1120               0 :         return OGRERR_FAILURE;
    1121                 :     }
    1122                 : 
    1123               1 :   OGREnvelope oEnv;
    1124               1 :   CPLString   osCommand;
    1125               1 :   GBool       bExtentSet = FALSE;
    1126                 : 
    1127               1 :   osCommand.Printf( "SELECT Envelope(`%s`) FROM `%s`;", pszGeomColumn, pszGeomColumnTable);
    1128                 : 
    1129               1 :   if (mysql_query(poDS->GetConn(), osCommand) == 0)
    1130                 :   {
    1131               1 :     MYSQL_RES* result = mysql_use_result(poDS->GetConn());
    1132               1 :     if ( result == NULL )
    1133                 :         {
    1134               0 :             poDS->ReportError( "mysql_use_result() failed on extents query." );
    1135               1 :             return OGRERR_FAILURE;
    1136                 :         }
    1137                 : 
    1138                 :     MYSQL_ROW row; 
    1139               1 :     unsigned long *panLengths = NULL;
    1140              12 :     while ((row = mysql_fetch_row(result)))
    1141                 :     {
    1142              10 :       if (panLengths == NULL)
    1143                 :       {
    1144               1 :         panLengths = mysql_fetch_lengths( result );
    1145               1 :         if ( panLengths == NULL )
    1146                 :         {
    1147               0 :           poDS->ReportError( "mysql_fetch_lengths() failed on extents query." );
    1148               0 :           return OGRERR_FAILURE;
    1149                 :         }
    1150                 :       }
    1151                 : 
    1152              10 :       OGRGeometry *poGeometry = NULL;
    1153                 :       // Geometry columns will have the first 4 bytes contain the SRID.
    1154                 :       OGRGeometryFactory::createFromWkb(((GByte *)row[0]) + 4, 
    1155                 :                         NULL,
    1156                 :                         &poGeometry,
    1157              10 :                         panLengths[0] - 4 );
    1158                 : 
    1159              10 :       if ( poGeometry != NULL )
    1160                 :       {
    1161              11 :         if (poGeometry && !bExtentSet)
    1162                 :         {
    1163               1 :           poGeometry->getEnvelope(psExtent);
    1164               1 :           bExtentSet = TRUE;
    1165                 :         }
    1166               9 :         else if (poGeometry)
    1167                 :         {
    1168               9 :           poGeometry->getEnvelope(&oEnv);
    1169               9 :           if (oEnv.MinX < psExtent->MinX) 
    1170               2 :             psExtent->MinX = oEnv.MinX;
    1171               9 :           if (oEnv.MinY < psExtent->MinY) 
    1172               3 :             psExtent->MinY = oEnv.MinY;
    1173               9 :           if (oEnv.MaxX > psExtent->MaxX) 
    1174               2 :             psExtent->MaxX = oEnv.MaxX;
    1175               9 :           if (oEnv.MaxY > psExtent->MaxY) 
    1176               0 :             psExtent->MaxY = oEnv.MaxY;
    1177                 :         }
    1178              10 :         delete poGeometry;
    1179                 :       }
    1180                 :     }
    1181                 : 
    1182               1 :     mysql_free_result(result);      
    1183                 :   }
    1184                 : 
    1185               1 :   return (bExtentSet ? OGRERR_NONE : OGRERR_FAILURE);
    1186                 : }

Generated by: LTP GCOV extension version 1.5