LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/mysql - ogrmysqllayer.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 119 130 91.5 %
Date: 2024-05-03 15:49:35 Functions: 10 12 83.3 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  OpenGIS Simple Features Reference Implementation
       4             :  * Purpose:  Implements OGRMySQLLayer class.
       5             :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       6             :  * Author:   Howard Butler, hobu@hobu.net
       7             :  *
       8             :  ******************************************************************************
       9             :  * Copyright (c) 2004, Frank Warmerdam <warmerdam@pobox.com>
      10             :  *
      11             :  * Permission is hereby granted, free of charge, to any person obtaining a
      12             :  * copy of this software and associated documentation files (the "Software"),
      13             :  * to deal in the Software without restriction, including without limitation
      14             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15             :  * and/or sell copies of the Software, and to permit persons to whom the
      16             :  * Software is furnished to do so, subject to the following conditions:
      17             :  *
      18             :  * The above copyright notice and this permission notice shall be included
      19             :  * in all copies or substantial portions of the Software.
      20             :  *
      21             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22             :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27             :  * DEALINGS IN THE SOFTWARE.
      28             :  ****************************************************************************/
      29             : 
      30             : #include "ogr_mysql.h"
      31             : #include "cpl_conv.h"
      32             : #include "cpl_string.h"
      33             : 
      34             : /************************************************************************/
      35             : /*                           OGRMySQLLayer()                            */
      36             : /************************************************************************/
      37             : 
      38         272 : OGRMySQLLayer::OGRMySQLLayer(OGRMySQLDataSource *poDSIn) : poDS(poDSIn)
      39             : {
      40         272 : }
      41             : 
      42             : /************************************************************************/
      43             : /*                           ~OGRMySQLLayer()                           */
      44             : /************************************************************************/
      45             : 
      46         272 : OGRMySQLLayer::~OGRMySQLLayer()
      47             : 
      48             : {
      49         272 :     if (m_nFeaturesRead > 0 && poFeatureDefn != nullptr)
      50             :     {
      51         470 :         CPLDebug("MySQL", "%d features read on layer '%s'.",
      52         235 :                  (int)m_nFeaturesRead, poFeatureDefn->GetName());
      53             :     }
      54             : 
      55         272 :     if (poFeatureDefn && poFeatureDefn->GetGeomFieldCount() > 0)
      56             :     {
      57           0 :         auto poGeomFieldDefn = dynamic_cast<OGRMySQLGeomFieldDefn *>(
      58         194 :             poFeatureDefn->GetGeomFieldDefn(0));
      59         194 :         if (poGeomFieldDefn)
      60         194 :             poGeomFieldDefn->UnsetDataSource();
      61             :     }
      62             : 
      63         272 :     OGRMySQLLayer::ResetReading();
      64             : 
      65         272 :     CPLFree(pszGeomColumn);
      66         272 :     CPLFree(pszGeomColumnTable);
      67         272 :     CPLFree(pszFIDColumn);
      68         272 :     CPLFree(pszQueryStatement);
      69             : 
      70         272 :     if (poFeatureDefn)
      71         272 :         poFeatureDefn->Release();
      72         272 : }
      73             : 
      74             : /************************************************************************/
      75             : /*                            ResetReading()                            */
      76             : /************************************************************************/
      77             : 
      78        1169 : void OGRMySQLLayer::ResetReading()
      79             : 
      80             : {
      81        1169 :     iNextShapeId = 0;
      82             : 
      83        1169 :     if (hResultSet != nullptr)
      84             :     {
      85         335 :         mysql_free_result(hResultSet);
      86         335 :         hResultSet = nullptr;
      87             : 
      88         335 :         poDS->InterruptLongResult();
      89             :     }
      90        1169 :     m_bEOF = false;
      91        1169 : }
      92             : 
      93             : /************************************************************************/
      94             : /*                           GetNextFeature()                           */
      95             : /************************************************************************/
      96             : 
      97         710 : OGRFeature *OGRMySQLLayer::GetNextFeature()
      98             : 
      99             : {
     100         710 :     if (m_bEOF)
     101           2 :         return nullptr;
     102             : 
     103             :     while (true)
     104             :     {
     105             :         OGRFeature *poFeature;
     106             : 
     107         712 :         poFeature = GetNextRawFeature();
     108         712 :         if (poFeature == nullptr)
     109             :         {
     110          63 :             m_bEOF = true;
     111          63 :             return nullptr;
     112             :         }
     113             : 
     114        1380 :         if ((m_poFilterGeom == nullptr ||
     115        1294 :              FilterGeometry(poFeature->GetGeometryRef())) &&
     116         645 :             (m_poAttrQuery == nullptr || m_poAttrQuery->Evaluate(poFeature)))
     117         645 :             return poFeature;
     118             : 
     119           4 :         delete poFeature;
     120           4 :     }
     121             : }
     122             : 
     123             : /************************************************************************/
     124             : /*                          RecordToFeature()                           */
     125             : /*                                                                      */
     126             : /*      Convert the indicated record of the current result set into     */
     127             : /*      a feature.                                                      */
     128             : /************************************************************************/
     129             : 
     130         667 : OGRFeature *OGRMySQLLayer::RecordToFeature(char **papszRow,
     131             :                                            unsigned long *panLengths)
     132             : 
     133             : {
     134         667 :     mysql_field_seek(hResultSet, 0);
     135             : 
     136             :     /* -------------------------------------------------------------------- */
     137             :     /*      Create a feature from the current result.                       */
     138             :     /* -------------------------------------------------------------------- */
     139         667 :     OGRFeature *poFeature = new OGRFeature(poFeatureDefn);
     140             : 
     141         667 :     poFeature->SetFID(iNextShapeId);
     142         667 :     m_nFeaturesRead++;
     143             : 
     144             :     /* ==================================================================== */
     145             :     /*      Transfer all result fields we can.                              */
     146             :     /* ==================================================================== */
     147        3965 :     for (int iField = 0; iField < (int)mysql_num_fields(hResultSet); iField++)
     148             :     {
     149        3298 :         MYSQL_FIELD *psMSField = mysql_fetch_field(hResultSet);
     150             : 
     151             :         /* --------------------------------------------------------------------
     152             :          */
     153             :         /*      Handle FID. */
     154             :         /* --------------------------------------------------------------------
     155             :          */
     156        3298 :         if (bHasFid && EQUAL(psMSField->name, pszFIDColumn))
     157             :         {
     158         551 :             if (papszRow[iField] == nullptr)
     159             :             {
     160           0 :                 CPLError(CE_Failure, CPLE_AppDefined,
     161             :                          "NULL primary key in RecordToFeature()");
     162           0 :                 return nullptr;
     163             :             }
     164             : 
     165         551 :             poFeature->SetFID(CPLAtoGIntBig(papszRow[iField]));
     166             :         }
     167             : 
     168        3298 :         if (papszRow[iField] == nullptr)
     169             :         {
     170         458 :             const int iOGRField = poFeatureDefn->GetFieldIndex(psMSField->name);
     171         458 :             if (iOGRField >= 0)
     172         456 :                 poFeature->SetFieldNull(iOGRField);
     173             : 
     174         458 :             continue;
     175             :         }
     176             : 
     177             :         /* --------------------------------------------------------------------
     178             :          */
     179             :         /*      Handle MySQL geometry */
     180             :         /* --------------------------------------------------------------------
     181             :          */
     182        2840 :         if (pszGeomColumn && EQUAL(psMSField->name, pszGeomColumn))
     183             :         {
     184         547 :             OGRGeometry *poGeometry = nullptr;
     185             : 
     186             :             // Geometry columns will have the first 4 bytes contain the SRID.
     187         547 :             OGRGeometryFactory::createFromWkb(
     188         547 :                 papszRow[iField] + 4, nullptr, &poGeometry,
     189         547 :                 static_cast<int>(panLengths[iField] - 4));
     190             : 
     191         547 :             if (poGeometry != nullptr)
     192             :             {
     193         547 :                 poGeometry->assignSpatialReference(GetSpatialRef());
     194         547 :                 poFeature->SetGeometryDirectly(poGeometry);
     195             :             }
     196         547 :             continue;
     197             :         }
     198             : 
     199             :         /* --------------------------------------------------------------------
     200             :          */
     201             :         /*      Transfer regular data fields. */
     202             :         /* --------------------------------------------------------------------
     203             :          */
     204        2293 :         const int iOGRField = poFeatureDefn->GetFieldIndex(psMSField->name);
     205        2293 :         if (iOGRField < 0)
     206         537 :             continue;
     207             : 
     208        1756 :         OGRFieldDefn *psFieldDefn = poFeatureDefn->GetFieldDefn(iOGRField);
     209             : 
     210        1756 :         if (psFieldDefn->GetType() == OFTBinary)
     211             :         {
     212           0 :             poFeature->SetField(iOGRField, static_cast<int>(panLengths[iField]),
     213           0 :                                 (GByte *)papszRow[iField]);
     214             :         }
     215             :         else
     216             :         {
     217        1756 :             poFeature->SetField(iOGRField, papszRow[iField]);
     218             :         }
     219             :     }
     220             : 
     221         667 :     return poFeature;
     222             : }
     223             : 
     224             : /************************************************************************/
     225             : /*                         GetNextRawFeature()                          */
     226             : /************************************************************************/
     227             : 
     228         712 : OGRFeature *OGRMySQLLayer::GetNextRawFeature()
     229             : 
     230             : {
     231             :     /* -------------------------------------------------------------------- */
     232             :     /*      Do we need to establish an initial query?                       */
     233             :     /* -------------------------------------------------------------------- */
     234         712 :     if (iNextShapeId == 0 && hResultSet == nullptr)
     235             :     {
     236         256 :         CPLAssert(pszQueryStatement != nullptr);
     237             : 
     238         256 :         poDS->RequestLongResult(this);
     239             : 
     240         256 :         if (mysql_query(poDS->GetConn(), pszQueryStatement))
     241             :         {
     242           1 :             poDS->ReportError(pszQueryStatement);
     243           1 :             return nullptr;
     244             :         }
     245             : 
     246         255 :         hResultSet = mysql_use_result(poDS->GetConn());
     247         255 :         if (hResultSet == nullptr)
     248             :         {
     249           0 :             poDS->ReportError("mysql_use_result() failed on query.");
     250           0 :             return nullptr;
     251             :         }
     252             :     }
     253             : 
     254             :     /* -------------------------------------------------------------------- */
     255             :     /*      Fetch next record.                                              */
     256             :     /* -------------------------------------------------------------------- */
     257             :     char **papszRow;
     258             :     unsigned long *panLengths;
     259             : 
     260         711 :     papszRow = mysql_fetch_row(hResultSet);
     261         711 :     if (papszRow == nullptr)
     262             :     {
     263          62 :         ResetReading();
     264          62 :         return nullptr;
     265             :     }
     266             : 
     267         649 :     panLengths = mysql_fetch_lengths(hResultSet);
     268             : 
     269             :     /* -------------------------------------------------------------------- */
     270             :     /*      Process record.                                                 */
     271             :     /* -------------------------------------------------------------------- */
     272         649 :     OGRFeature *poFeature = RecordToFeature(papszRow, panLengths);
     273             : 
     274         649 :     iNextShapeId++;
     275             : 
     276         649 :     return poFeature;
     277             : }
     278             : 
     279             : /************************************************************************/
     280             : /*                             GetFeature()                             */
     281             : /*                                                                      */
     282             : /*      Note that we actually override this in OGRMySQLTableLayer.      */
     283             : /************************************************************************/
     284             : 
     285           0 : OGRFeature *OGRMySQLLayer::GetFeature(GIntBig nFeatureId)
     286             : 
     287             : {
     288           0 :     return OGRLayer::GetFeature(nFeatureId);
     289             : }
     290             : 
     291             : /************************************************************************/
     292             : /*                            GetFIDColumn()                            */
     293             : /************************************************************************/
     294             : 
     295          24 : const char *OGRMySQLLayer::GetFIDColumn()
     296             : 
     297             : {
     298          24 :     if (pszFIDColumn != nullptr)
     299          24 :         return pszFIDColumn;
     300             :     else
     301           0 :         return "";
     302             : }
     303             : 
     304             : /************************************************************************/
     305             : /*                         FetchSRSId()                                 */
     306             : /************************************************************************/
     307             : 
     308         194 : int OGRMySQLLayer::FetchSRSId()
     309             : {
     310         194 :     CPLString osCommand;
     311             :     char **papszRow;
     312             : 
     313         194 :     if (hResultSet != nullptr)
     314          11 :         mysql_free_result(hResultSet);
     315         194 :     hResultSet = nullptr;
     316             : 
     317         194 :     if (poDS->GetMajorVersion() < 8 || poDS->IsMariaDB())
     318             :     {
     319             :         osCommand.Printf("SELECT srid FROM geometry_columns "
     320             :                          "WHERE f_table_name = '%s'",
     321          63 :                          pszGeomColumnTable);
     322             :     }
     323             :     else
     324             :     {
     325             :         osCommand.Printf(
     326             :             "SELECT SRS_ID FROM INFORMATION_SCHEMA.ST_GEOMETRY_COLUMNS "
     327             :             "WHERE TABLE_NAME = '%s'",
     328         131 :             pszGeomColumnTable);
     329             :     }
     330             : 
     331         194 :     if (!mysql_query(poDS->GetConn(), osCommand))
     332         193 :         hResultSet = mysql_store_result(poDS->GetConn());
     333             : 
     334         194 :     papszRow = nullptr;
     335         194 :     if (hResultSet != nullptr)
     336         193 :         papszRow = mysql_fetch_row(hResultSet);
     337             : 
     338         194 :     if (papszRow != nullptr && papszRow[0] != nullptr)
     339             :     {
     340         178 :         nSRSId = atoi(papszRow[0]);
     341             :     }
     342             : 
     343             :     // make sure to free our results
     344         194 :     if (hResultSet != nullptr)
     345         193 :         mysql_free_result(hResultSet);
     346         194 :     hResultSet = nullptr;
     347             : 
     348         388 :     return nSRSId;
     349             : }
     350             : 
     351             : /************************************************************************/
     352             : /*                           GetSpatialRef()                            */
     353             : /************************************************************************/
     354             : 
     355        1055 : const OGRSpatialReference *OGRMySQLGeomFieldDefn::GetSpatialRef() const
     356             : 
     357             : {
     358        1055 :     if (!poDS)
     359           0 :         return poSRS;
     360             : 
     361        1055 :     if (poSRS == nullptr && nSRSId > -1)
     362             :     {
     363         172 :         poSRS = poDS->FetchSRS(nSRSId);
     364         172 :         if (poSRS != nullptr)
     365         168 :             const_cast<OGRSpatialReference *>(poSRS)->Reference();
     366             :         else
     367           4 :             nSRSId = poDS->GetUnknownSRID();
     368             :     }
     369             : 
     370        1055 :     return poSRS;
     371             : }
     372             : 
     373             : /************************************************************************/
     374             : /*                             GetDataset()                             */
     375             : /************************************************************************/
     376             : 
     377           2 : GDALDataset *OGRMySQLLayer::GetDataset()
     378             : {
     379           2 :     return poDS;
     380             : }

Generated by: LCOV version 1.14