LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/mysql - ogrmysqlresultlayer.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 122 83 68.0 %
Date: 2010-01-09 Functions: 8 7 87.5 %

       1                 : /******************************************************************************
       2                 :  * $Id: ogrmysqlresultlayer.cpp 18362 2009-12-21 05:47:06Z chaitanya $
       3                 :  *
       4                 :  * Project:  OpenGIS Simple Features Reference Implementation
       5                 :  * Purpose:  Implements OGRMySQLResultLayer 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 "ogr_mysql.h"
      33                 : 
      34                 : CPL_CVSID("$Id: ogrmysqlresultlayer.cpp 18362 2009-12-21 05:47:06Z chaitanya $");
      35                 : 
      36                 : /************************************************************************/
      37                 : /*                        OGRMySQLResultLayer()                         */
      38                 : /************************************************************************/
      39                 : 
      40               3 : OGRMySQLResultLayer::OGRMySQLResultLayer( OGRMySQLDataSource *poDSIn, 
      41                 :                                           const char * pszRawQueryIn,
      42               3 :                                           MYSQL_RES *hResultSetIn )
      43                 : {
      44               3 :     poDS = poDSIn;
      45                 : 
      46               3 :     iNextShapeId = 0;
      47                 : 
      48               3 :     pszRawStatement = CPLStrdup(pszRawQueryIn);
      49                 : 
      50               3 :     hResultSet = hResultSetIn;
      51                 : 
      52               3 :     BuildFullQueryStatement();
      53                 : 
      54               3 :     poFeatureDefn = ReadResultDefinition();
      55               3 : }
      56                 : 
      57                 : /************************************************************************/
      58                 : /*                        ~OGRMySQLResultLayer()                        */
      59                 : /************************************************************************/
      60                 : 
      61               6 : OGRMySQLResultLayer::~OGRMySQLResultLayer()
      62                 : 
      63                 : {
      64               3 :     CPLFree( pszRawStatement );
      65               6 : }
      66                 : 
      67                 : /************************************************************************/
      68                 : /*                        ReadResultDefinition()                        */
      69                 : /*                                                                      */
      70                 : /*      Build a schema from the current resultset.                      */
      71                 : /************************************************************************/
      72                 : 
      73               3 : OGRFeatureDefn *OGRMySQLResultLayer::ReadResultDefinition()
      74                 : 
      75                 : {
      76                 : 
      77                 : /* -------------------------------------------------------------------- */
      78                 : /*      Parse the returned table information.                           */
      79                 : /* -------------------------------------------------------------------- */
      80               3 :     OGRFeatureDefn *poDefn = new OGRFeatureDefn( "sql_statement" );
      81                 :     int            iRawField;
      82                 : 
      83               3 :     poDefn->Reference();
      84                 :     int width;
      85                 :     int precision;
      86                 : 
      87               3 :     mysql_field_seek( hResultSet, 0 );
      88               3 :     for( iRawField = 0; 
      89                 :          iRawField < (int) mysql_num_fields(hResultSet); 
      90                 :          iRawField++ )
      91                 :     {
      92               8 :         MYSQL_FIELD *psMSField = mysql_fetch_field( hResultSet );
      93               8 :         OGRFieldDefn    oField( psMSField->name, OFTString);
      94                 : 
      95               8 :         switch( psMSField->type )
      96                 :         {
      97                 :           case FIELD_TYPE_TINY:
      98                 :           case FIELD_TYPE_SHORT:
      99                 :           case FIELD_TYPE_LONG:
     100                 :           case FIELD_TYPE_INT24:
     101                 :           case FIELD_TYPE_LONGLONG:
     102               4 :             oField.SetType( OFTInteger );
     103               4 :             width = (int)psMSField->length;
     104               4 :             oField.SetWidth(width);
     105               4 :             poDefn->AddFieldDefn( &oField );
     106               4 :             break;
     107                 : 
     108                 :           case FIELD_TYPE_DECIMAL:
     109                 : #ifdef FIELD_TYPE_NEWDECIMAL
     110                 :           case FIELD_TYPE_NEWDECIMAL:
     111                 : #endif
     112               0 :             oField.SetType( OFTReal );
     113                 :             
     114                 :             // a bunch of hackery to munge the widths that MySQL gives 
     115                 :             // us into corresponding widths and precisions for OGR
     116               0 :             precision =    (int)psMSField->decimals;
     117               0 :             width = (int)psMSField->length;
     118               0 :             if (!precision)
     119               0 :                 width = width - 1;
     120               0 :             width = width - precision;
     121                 :             
     122               0 :             oField.SetWidth(width);
     123               0 :             oField.SetPrecision(precision);
     124               0 :             poDefn->AddFieldDefn( &oField );
     125               0 :             break;
     126                 : 
     127                 :           case FIELD_TYPE_FLOAT:
     128                 :           case FIELD_TYPE_DOUBLE:
     129                 :          /* MYSQL_FIELD is always reporting ->length = 22 and ->decimals = 31
     130                 :             for double type regardless of the data it returned. In an example,
     131                 :             the data it returned had only 5 or 6 decimal places which were
     132                 :             exactly as entered into the database but reported the decimals
     133                 :             as 31. */
     134                 :          /* Assuming that a length of 22 means no particular width and 31
     135                 :             decimals means no particular precision. */
     136               1 :             width = (int)psMSField->length;
     137               1 :             precision = (int)psMSField->decimals;
     138               1 :             oField.SetType( OFTReal );
     139               1 :             if( width != 22 )
     140               0 :                 oField.SetWidth(width);
     141               1 :             if( precision != 31 )
     142               0 :                 oField.SetPrecision(precision);
     143               1 :             poDefn->AddFieldDefn( &oField );
     144               1 :             break;
     145                 : 
     146                 :           case FIELD_TYPE_DATE:
     147               0 :             oField.SetType( OFTDate );
     148               0 :             oField.SetWidth(0);
     149               0 :             poDefn->AddFieldDefn( &oField );
     150               0 :             break;
     151                 : 
     152                 :           case FIELD_TYPE_TIME:
     153               0 :             oField.SetType( OFTTime );
     154               0 :             oField.SetWidth(0);
     155               0 :             poDefn->AddFieldDefn( &oField );
     156               0 :             break;
     157                 : 
     158                 :           case FIELD_TYPE_TIMESTAMP:
     159                 :           case FIELD_TYPE_DATETIME:
     160               0 :             oField.SetType( OFTDateTime );
     161               0 :             oField.SetWidth(0);
     162               0 :             poDefn->AddFieldDefn( &oField );
     163               0 :             break;
     164                 : 
     165                 :           case FIELD_TYPE_YEAR:
     166                 :           case FIELD_TYPE_STRING:
     167                 :           case FIELD_TYPE_VAR_STRING:
     168               1 :             oField.SetType( OFTString );
     169               1 :             oField.SetWidth((int)psMSField->length);
     170               1 :             poDefn->AddFieldDefn( &oField );
     171               1 :             break;
     172                 : 
     173                 :           case FIELD_TYPE_TINY_BLOB:
     174                 :           case FIELD_TYPE_MEDIUM_BLOB:
     175                 :           case FIELD_TYPE_LONG_BLOB:
     176                 :           case FIELD_TYPE_BLOB:
     177               1 :             if( psMSField->charsetnr == 63 )
     178               0 :                 oField.SetType( OFTBinary );
     179                 :             else
     180               1 :                 oField.SetType( OFTString );
     181               1 :             oField.SetWidth((int)psMSField->max_length);
     182               1 :             poDefn->AddFieldDefn( &oField );
     183               1 :             break;
     184                 :                         
     185                 :           case FIELD_TYPE_GEOMETRY:
     186               1 :             pszGeomColumnTable = CPLStrdup( psMSField->table);
     187               1 :             pszGeomColumn = CPLStrdup( psMSField->name);            
     188                 :             break;
     189                 :             
     190                 :           default:
     191                 :             // any other field we ignore. 
     192                 :             break;
     193                 :         }
     194                 :         
     195                 :         // assume a FID name first, and if it isn't there
     196                 :         // take a field that is not null, a primary key, 
     197                 :         // and is an integer-like field
     198               8 :         if( EQUAL(psMSField->name,"ogc_fid") )
     199                 :         {
     200               0 :             bHasFid = TRUE;
     201               0 :             pszFIDColumn = CPLStrdup(oField.GetNameRef());
     202               0 :             continue;
     203                 :         } else  
     204               8 :         if (IS_NOT_NULL(psMSField->flags)
     205                 :             && IS_PRI_KEY(psMSField->flags)
     206                 :             && 
     207                 :                 (
     208                 :                     psMSField->type == FIELD_TYPE_TINY
     209                 :                     || psMSField->type == FIELD_TYPE_SHORT
     210                 :                     || psMSField->type == FIELD_TYPE_LONG
     211                 :                     || psMSField->type == FIELD_TYPE_INT24
     212                 :                     || psMSField->type == FIELD_TYPE_LONGLONG
     213                 :                 )
     214                 :             )
     215                 :         {
     216               1 :            bHasFid = TRUE;
     217               1 :            pszFIDColumn = CPLStrdup(oField.GetNameRef());
     218               1 :            continue;
     219                 :         }
     220                 :     }
     221                 : 
     222                 : 
     223               3 :     poDefn->SetGeomType( wkbNone );
     224                 : 
     225               3 :     if (pszGeomColumn) 
     226                 :     {
     227               1 :         char*        pszType=NULL;
     228                 :         char         szCommand[1024];
     229                 :         char           **papszRow;  
     230                 :          
     231                 :         // set to unknown first
     232               1 :         poDefn->SetGeomType( wkbUnknown );
     233                 :         
     234                 :         sprintf(szCommand, 
     235                 :                 "SELECT type FROM geometry_columns WHERE f_table_name='%s'",
     236               1 :                 pszGeomColumnTable );
     237                 : 
     238               1 :         if( hResultSet != NULL )
     239               1 :             mysql_free_result( hResultSet );
     240               1 :         hResultSet = NULL;
     241                 : 
     242               1 :         if( !mysql_query( poDS->GetConn(), szCommand ) )
     243               1 :             hResultSet = mysql_store_result( poDS->GetConn() );
     244                 : 
     245               1 :         papszRow = NULL;
     246               1 :         if( hResultSet != NULL )
     247               1 :             papszRow = mysql_fetch_row( hResultSet );
     248                 : 
     249                 : 
     250               1 :         if( papszRow != NULL && papszRow[0] != NULL )
     251                 :         {
     252               1 :             pszType = papszRow[0];
     253                 : 
     254               1 :             OGRwkbGeometryType nGeomType = wkbUnknown;
     255                 : 
     256                 :             // check only standard OGC geometry types
     257               1 :             if ( EQUAL(pszType, "POINT") )
     258               0 :                 nGeomType = wkbPoint;
     259               1 :             else if ( EQUAL(pszType,"LINESTRING"))
     260               0 :                 nGeomType = wkbLineString;
     261               1 :             else if ( EQUAL(pszType,"POLYGON"))
     262               0 :                 nGeomType = wkbPolygon;
     263               1 :             else if ( EQUAL(pszType,"MULTIPOINT"))
     264               0 :                 nGeomType = wkbMultiPoint;
     265               1 :             else if ( EQUAL(pszType,"MULTILINESTRING"))
     266               0 :                 nGeomType = wkbMultiLineString;
     267               1 :             else if ( EQUAL(pszType,"MULTIPOLYGON"))
     268               0 :                 nGeomType = wkbMultiPolygon;
     269               1 :             else if ( EQUAL(pszType,"GEOMETRYCOLLECTION"))
     270               0 :                 nGeomType = wkbGeometryCollection;
     271                 : 
     272               1 :             poDefn->SetGeomType( nGeomType );
     273                 : 
     274                 :         } 
     275                 : 
     276               1 :     nSRSId = FetchSRSId();
     277                 :     } 
     278                 : 
     279                 : 
     280               3 :     return poDefn;
     281                 : }
     282                 : 
     283                 : /************************************************************************/
     284                 : /*                      BuildFullQueryStatement()                       */
     285                 : /************************************************************************/
     286                 : 
     287               3 : void OGRMySQLResultLayer::BuildFullQueryStatement()
     288                 : 
     289                 : {
     290               3 :     if( pszQueryStatement != NULL )
     291                 :     {
     292               0 :         CPLFree( pszQueryStatement );
     293               0 :         pszQueryStatement = NULL;
     294                 :     }
     295                 : 
     296               3 :     pszQueryStatement = CPLStrdup(pszRawStatement);
     297               3 : }
     298                 : 
     299                 : /************************************************************************/
     300                 : /*                            ResetReading()                            */
     301                 : /************************************************************************/
     302                 : 
     303              19 : void OGRMySQLResultLayer::ResetReading()
     304                 : 
     305                 : {
     306              19 :     OGRMySQLLayer::ResetReading();
     307              19 : }
     308                 : 
     309                 : /************************************************************************/
     310                 : /*                          GetFeatureCount()                           */
     311                 : /************************************************************************/
     312                 : 
     313               2 : int OGRMySQLResultLayer::GetFeatureCount( int bForce )
     314                 : 
     315                 : {
     316                 :     // I wonder if we could do anything smart here...
     317                 :     // ... not till MySQL grows up (HB)
     318               2 :     return OGRMySQLLayer::GetFeatureCount( bForce );
     319                 : }
     320                 : 
     321                 : /************************************************************************/
     322                 : /*                           TestCapability()                           */
     323                 : /************************************************************************/
     324                 : 
     325               0 : int OGRMySQLResultLayer::TestCapability( const char * pszCap )
     326                 : 
     327                 : {
     328               0 :     return FALSE;
     329                 : }
     330                 : 

Generated by: LCOV version 1.7