Line data Source code
1 : /****************************************************************************** 2 : * 3 : * Project: OpenGIS Simple Features Reference Implementation 4 : * Purpose: Declarations for MySQL OGR Driver Classes. 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 : * Copyright (c) 2008-2012, Even Rouault <even dot rouault at spatialys.com> 11 : * 12 : * SPDX-License-Identifier: MIT 13 : ****************************************************************************/ 14 : 15 : #ifndef OGR_MYSQL_H_INCLUDED 16 : #define OGR_MYSQL_H_INCLUDED 17 : 18 : // Include cpl_port.h before mysql stuff to avoid issues with CPLIsFinite() 19 : // See https://trac.osgeo.org/gdal/ticket/6899 20 : #include "cpl_port.h" 21 : 22 : #ifdef _MSC_VER 23 : #pragma warning(push) 24 : // 'my_alignment_imp<0x02>' : structure was padded due to __declspec(align()) 25 : #pragma warning(disable : 4324) 26 : // nonstandard extension used : nameless struct/union 27 : #pragma warning(disable : 4201) 28 : // nonstandard extension used : redefined extern to static 29 : #pragma warning(disable : 4211) 30 : // warning C4005: 'HAVE_STRUCT_TIMESPEC': macro redefinition 31 : #pragma warning(disable : 4005) 32 : #endif 33 : 34 : #include <mysql.h> 35 : 36 : #ifdef _MSC_VER 37 : #pragma warning(pop) 38 : #endif 39 : 40 : /* my_global.h from mysql 5.1 declares the min and max macros. */ 41 : /* This conflicts with templates in g++-4.3.2 header files. Grrr */ 42 : #ifdef min 43 : #undef min 44 : #endif 45 : 46 : #ifdef max 47 : #undef max 48 : #endif 49 : 50 : #ifdef bool 51 : #undef bool 52 : #endif 53 : 54 : #include "ogrsf_frmts.h" 55 : 56 : #include <map> 57 : 58 : class OGRMySQLDataSource; 59 : 60 : /************************************************************************/ 61 : /* OGRMySQLGeomFieldDefn */ 62 : /************************************************************************/ 63 : 64 : class OGRMySQLGeomFieldDefn final : public OGRGeomFieldDefn 65 : { 66 : OGRMySQLGeomFieldDefn(const OGRMySQLGeomFieldDefn &) = delete; 67 : OGRMySQLGeomFieldDefn &operator=(const OGRMySQLGeomFieldDefn &) = delete; 68 : 69 : protected: 70 : OGRMySQLDataSource *poDS; 71 : 72 : public: 73 194 : OGRMySQLGeomFieldDefn(OGRMySQLDataSource *poDSIn, const char *pszFieldName) 74 194 : : OGRGeomFieldDefn(pszFieldName, wkbUnknown), poDS(poDSIn) 75 : { 76 194 : } 77 : 78 : const OGRSpatialReference *GetSpatialRef() const override; 79 : 80 194 : void UnsetDataSource() 81 : { 82 194 : poDS = nullptr; 83 194 : } 84 : 85 : mutable int nSRSId = -1; 86 : }; 87 : 88 : /************************************************************************/ 89 : /* OGRMySQLLayer */ 90 : /************************************************************************/ 91 : 92 : class OGRMySQLLayer CPL_NON_FINAL : public OGRLayer 93 : { 94 : protected: 95 : OGRMySQLDataSource *poDS; 96 : 97 : OGRFeatureDefn *poFeatureDefn = nullptr; 98 : 99 : // Layer srid. 100 : int nSRSId = -2; // we haven't even queried the database for it yet. 101 : 102 : GIntBig iNextShapeId = 0; 103 : 104 : char *pszQueryStatement = nullptr; 105 : 106 : int nResultOffset = 0; 107 : 108 : char *pszGeomColumn = nullptr; 109 : char *pszGeomColumnTable = nullptr; 110 : int nGeomType = 0; 111 : 112 : int bHasFid = FALSE; 113 : char *pszFIDColumn = nullptr; 114 : 115 : MYSQL_RES *hResultSet = nullptr; 116 : bool m_bEOF = false; 117 : 118 : int FetchSRSId(); 119 : 120 : public: 121 : explicit OGRMySQLLayer(OGRMySQLDataSource *poDSIn); 122 : ~OGRMySQLLayer() override; 123 : 124 : void ResetReading() override; 125 : 126 : OGRFeature *GetNextFeature() override; 127 : 128 : OGRFeature *GetFeature(GIntBig nFeatureId) override; 129 : 130 : using OGRLayer::GetLayerDefn; 131 : 132 10076 : const OGRFeatureDefn *GetLayerDefn() const override 133 : { 134 10076 : return poFeatureDefn; 135 : } 136 : 137 : const char *GetFIDColumn() const override; 138 : 139 : /* custom methods */ 140 : virtual OGRFeature *RecordToFeature(char **papszRow, unsigned long *); 141 : virtual OGRFeature *GetNextRawFeature(); 142 : 143 : GDALDataset *GetDataset() override; 144 : }; 145 : 146 : /************************************************************************/ 147 : /* OGRMySQLTableLayer */ 148 : /************************************************************************/ 149 : 150 : class OGRMySQLTableLayer final : public OGRMySQLLayer 151 : { 152 : int bUpdateAccess; 153 : 154 : OGRFeatureDefn *ReadTableDefinition(const char *); 155 : 156 : void BuildWhere(); 157 : char *BuildFields(); 158 : void BuildFullQueryStatement(); 159 : 160 : char *pszQuery; 161 : char *pszWHERE; 162 : 163 : int bLaunderColumnNames; 164 : int bPreservePrecision; 165 : 166 : public: 167 : OGRMySQLTableLayer(OGRMySQLDataSource *, const char *pszName, int bUpdate, 168 : int nSRSId = -2); 169 : ~OGRMySQLTableLayer() override; 170 : 171 : OGRErr Initialize(const char *pszTableName); 172 : 173 : OGRFeature *GetFeature(GIntBig nFeatureId) override; 174 : void ResetReading() override; 175 : GIntBig GetFeatureCount(int) override; 176 : 177 : OGRErr ISetSpatialFilter(int iGeomField, 178 : const OGRGeometry *poGeom) override; 179 : 180 : OGRErr SetAttributeFilter(const char *) override; 181 : OGRErr ICreateFeature(OGRFeature *poFeature) override; 182 : OGRErr DeleteFeature(GIntBig nFID) override; 183 : OGRErr ISetFeature(OGRFeature *poFeature) override; 184 : 185 : virtual OGRErr CreateField(const OGRFieldDefn *poField, 186 : int bApproxOK = TRUE) override; 187 : 188 176 : void SetLaunderFlag(int bFlag) 189 : { 190 176 : bLaunderColumnNames = bFlag; 191 176 : } 192 : 193 176 : void SetPrecisionFlag(int bFlag) 194 : { 195 176 : bPreservePrecision = bFlag; 196 176 : } 197 : 198 : int TestCapability(const char *) const override; 199 : 200 : OGRErr IGetExtent(int iGeomField, OGREnvelope *psExtent, 201 : bool bForce) override; 202 : }; 203 : 204 : /************************************************************************/ 205 : /* OGRMySQLResultLayer */ 206 : /************************************************************************/ 207 : 208 : class OGRMySQLResultLayer final : public OGRMySQLLayer 209 : { 210 : void BuildFullQueryStatement(); 211 : 212 : char *pszRawStatement; 213 : 214 : public: 215 : OGRMySQLResultLayer(OGRMySQLDataSource *, const char *pszRawStatement, 216 : MYSQL_RES *hResultSetIn); 217 : ~OGRMySQLResultLayer() override; 218 : 219 : OGRFeatureDefn *ReadResultDefinition(); 220 : 221 : void ResetReading() override; 222 : GIntBig GetFeatureCount(int) override; 223 : 224 : int TestCapability(const char *) const override; 225 : }; 226 : 227 : /************************************************************************/ 228 : /* OGRMySQLDataSource */ 229 : /************************************************************************/ 230 : 231 : class OGRMySQLDataSource final : public GDALDataset 232 : { 233 : OGRMySQLLayer **papoLayers; 234 : int nLayers; 235 : 236 : int bDSUpdate; 237 : 238 : MYSQL *hConn; 239 : 240 : OGRErr DeleteLayer(int iLayer) override; 241 : 242 : // We maintain a list of known SRID to reduce the number of trips to 243 : // the database to get SRSes. 244 : std::map<int, 245 : std::unique_ptr<OGRSpatialReference, OGRSpatialReferenceReleaser>> 246 : m_oSRSCache{}; 247 : 248 : OGRMySQLLayer *poLongResultLayer; 249 : 250 : bool m_bIsMariaDB = false; 251 : int m_nMajor = 0; 252 : int m_nMinor = 0; 253 : 254 : public: 255 : OGRMySQLDataSource(); 256 : ~OGRMySQLDataSource() override; 257 : 258 5677 : MYSQL *GetConn() 259 : { 260 5677 : return hConn; 261 : } 262 : 263 : int FetchSRSId(const OGRSpatialReference *poSRS); 264 : 265 : const OGRSpatialReference *FetchSRS(int nSRSId); 266 : 267 : OGRErr InitializeMetadataTables(); 268 : OGRErr UpdateMetadataTables(const char *pszLayerName, 269 : OGRwkbGeometryType eType, 270 : const char *pszGeomColumnName, 271 : const int nSRSId); 272 : 273 : int Open(const char *, char **papszOpenOptions, int bUpdate); 274 : int OpenTable(const char *, int bUpdate); 275 : 276 3995 : int GetLayerCount() const override 277 : { 278 3995 : return nLayers; 279 : } 280 : 281 : const OGRLayer *GetLayer(int) const override; 282 : 283 : OGRLayer *ICreateLayer(const char *pszName, 284 : const OGRGeomFieldDefn *poGeomFieldDefn, 285 : CSLConstList papszOptions) override; 286 : 287 : int TestCapability(const char *) const override; 288 : 289 : OGRLayer *ExecuteSQL(const char *pszSQLCommand, 290 : OGRGeometry *poSpatialFilter, 291 : const char *pszDialect) override; 292 : void ReleaseResultSet(OGRLayer *poLayer) override; 293 : 294 : // nonstandard 295 : 296 : void ReportError(const char * = nullptr); 297 : 298 : static char *LaunderName(const char *); 299 : 300 : void RequestLongResult(OGRMySQLLayer *); 301 : void InterruptLongResult(); 302 : 303 1879 : bool IsMariaDB() const 304 : { 305 1879 : return m_bIsMariaDB; 306 : } 307 : 308 2337 : int GetMajorVersion() const 309 : { 310 2337 : return m_nMajor; 311 : } 312 : 313 : int GetUnknownSRID() const; 314 : }; 315 : 316 : std::string OGRMySQLEscapeLiteral(const char *pszLiteral); 317 : 318 : #endif /* ndef OGR_MYSQL_H_INCLUDED */