1 /******************************************************************************
2  * $Id: ogr_pg.h 3798cbe48457b7127606931896549f26507469db 2021-04-09 15:04:16 +0200 Even Rouault $
3  *
4  * Project:  OpenGIS Simple Features Reference Implementation
5  * Purpose:  Private definitions for OGR/PostgreSQL driver.
6  * Author:   Frank Warmerdam, warmerdam@pobox.com
7  *
8  ******************************************************************************
9  * Copyright (c) 2000, Frank Warmerdam
10  * Copyright (c) 2008-2013, Even Rouault <even dot rouault at spatialys.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 #ifndef OGR_PG_H_INCLUDED
32 #define OGR_PG_H_INCLUDED
33 
34 #include "ogrsf_frmts.h"
35 #include "libpq-fe.h"
36 #include "cpl_string.h"
37 
38 #include "ogrpgutility.h"
39 #include "ogr_pgdump.h"
40 
41 #include <vector>
42 
43 /* These are the OIDs for some builtin types, as returned by PQftype(). */
44 /* They were copied from pg_type.h in src/include/catalog/pg_type.h */
45 
46 #define BOOLOID                 16
47 #define BYTEAOID                17
48 #define CHAROID                 18
49 #define NAMEOID                 19
50 #define INT8OID                 20
51 #define INT2OID                 21
52 #define INT2VECTOROID           22
53 #define INT4OID                 23
54 #define REGPROCOID              24
55 #define TEXTOID                 25
56 #define OIDOID                  26
57 #define TIDOID                  27
58 #define XIDOID                  28
59 #define CIDOID                  29
60 #define OIDVECTOROID            30
61 #define JSONOID                 114
62 #define FLOAT4OID               700
63 #define FLOAT8OID               701
64 #define BOOLARRAYOID            1000
65 #define INT2ARRAYOID            1005
66 #define INT4ARRAYOID            1007
67 #define TEXTARRAYOID            1009
68 #define BPCHARARRAYOID          1014
69 #define VARCHARARRAYOID         1015
70 #define INT8ARRAYOID            1016
71 #define FLOAT4ARRAYOID          1021
72 #define FLOAT8ARRAYOID          1022
73 #define BPCHAROID               1042
74 #define VARCHAROID              1043
75 #define DATEOID                 1082
76 #define TIMEOID                 1083
77 #define TIMESTAMPOID            1114
78 #define TIMESTAMPTZOID          1184
79 #define NUMERICOID              1700
80 #define NUMERICARRAYOID         1231
81 #define UUIDOID                 2950
82 #define JSONBOID                3802
83 
84 CPLString OGRPGEscapeString(void *hPGConn,
85                             const char* pszStrValue, int nMaxLength = -1,
86                             const char* pszTableName = "",
87                             const char* pszFieldName = "");
88 CPLString OGRPGEscapeColumnName(const char* pszColumnName);
89 
90 #define UNDETERMINED_SRID       -2 /* Special value when we haven't yet looked for SRID */
91 
92 class OGRPGDataSource;
93 class OGRPGLayer;
94 
95 typedef enum
96 {
97     GEOM_TYPE_UNKNOWN = 0,
98     GEOM_TYPE_GEOMETRY = 1,
99     GEOM_TYPE_GEOGRAPHY = 2,
100     GEOM_TYPE_WKB = 3
101 } PostgisType;
102 
103 typedef struct
104 {
105     char* pszName;
106     char* pszGeomType;
107     int   GeometryTypeFlags;
108     int   nSRID;
109     PostgisType   ePostgisType;
110     int   bNullable;
111 } PGGeomColumnDesc;
112 
113 /************************************************************************/
114 /*                         OGRPGGeomFieldDefn                           */
115 /************************************************************************/
116 
117 class OGRPGGeomFieldDefn final: public OGRGeomFieldDefn
118 {
119         OGRPGGeomFieldDefn( const OGRPGGeomFieldDefn& ) = delete;
120         OGRPGGeomFieldDefn& operator= ( const OGRPGGeomFieldDefn& ) = delete;
121 
122     protected:
123         OGRPGLayer* poLayer;
124 
125     public:
OGRPGGeomFieldDefn(OGRPGLayer * poLayerIn,const char * pszFieldName)126         OGRPGGeomFieldDefn( OGRPGLayer* poLayerIn,
127                                 const char* pszFieldName ) :
128             OGRGeomFieldDefn(pszFieldName, wkbUnknown), poLayer(poLayerIn),
129             nSRSId(UNDETERMINED_SRID), GeometryTypeFlags(0), ePostgisType(GEOM_TYPE_UNKNOWN)
130             {
131             }
132 
133         virtual OGRSpatialReference* GetSpatialRef() const override;
134 
UnsetLayer()135         void UnsetLayer() { poLayer = nullptr; }
136 
137         mutable int nSRSId;
138         mutable int GeometryTypeFlags;
139         mutable PostgisType   ePostgisType;
140 };
141 
142 /************************************************************************/
143 /*                          OGRPGFeatureDefn                            */
144 /************************************************************************/
145 
146 class OGRPGFeatureDefn CPL_NON_FINAL: public OGRFeatureDefn
147 {
148     public:
149         explicit OGRPGFeatureDefn( const char * pszName = nullptr ) :
OGRFeatureDefn(pszName)150             OGRFeatureDefn(pszName)
151         {
152             SetGeomType(wkbNone);
153         }
154 
UnsetLayer()155         virtual void UnsetLayer()
156         {
157             for(int i=0;i<nGeomFieldCount;i++)
158                 cpl::down_cast<OGRPGGeomFieldDefn*>(papoGeomFieldDefn[i])->UnsetLayer();
159         }
160 
GetGeomFieldDefn(int i)161         OGRPGGeomFieldDefn *GetGeomFieldDefn( int i ) override
162         {
163             return cpl::down_cast<OGRPGGeomFieldDefn*>(OGRFeatureDefn::GetGeomFieldDefn(i));
164         }
165 
GetGeomFieldDefn(int i)166         const OGRPGGeomFieldDefn *GetGeomFieldDefn( int i ) const override
167         {
168             return cpl::down_cast<const OGRPGGeomFieldDefn*>(OGRFeatureDefn::GetGeomFieldDefn(i));
169         }
170 };
171 
172 /************************************************************************/
173 /*                            OGRPGLayer                                */
174 /************************************************************************/
175 
176 class OGRPGLayer CPL_NON_FINAL: public OGRLayer
177 {
178     OGRPGLayer( const OGRPGLayer&) = delete;
179     OGRPGLayer& operator=( const OGRPGLayer&) = delete;
180 
181   protected:
182     OGRPGFeatureDefn   *poFeatureDefn = nullptr;
183 
184     int                 nCursorPage = 0;
185     GIntBig             iNextShapeId = 0;
186 
187     static char        *GByteArrayToBYTEA( const GByte* pabyData, size_t nLen);
188     static char        *GeometryToBYTEA( const OGRGeometry *, int nPostGISMajor, int nPostGISMinor );
189     static GByte       *BYTEAToGByteArray( const char *pszBytea, int* pnLength );
190     static OGRGeometry *BYTEAToGeometry( const char *, int bIsPostGIS1 );
191     Oid                 GeometryToOID( OGRGeometry * );
192     OGRGeometry        *OIDToGeometry( Oid );
193 
194     OGRPGDataSource    *poDS = nullptr;
195 
196     char               *pszQueryStatement = nullptr;
197 
198     char               *pszCursorName = nullptr;
199     PGresult           *hCursorResult = nullptr;
200     int                 bInvalidated = false;
201 
202     int                 nResultOffset = 0;
203 
204     int                 bWkbAsOid = false;
205 
206     char                *pszFIDColumn = nullptr;
207 
208     int                 bCanUseBinaryCursor = true;
209     int                *m_panMapFieldNameToIndex = nullptr;
210     int                *m_panMapFieldNameToGeomIndex = nullptr;
211 
212     int                 ParsePGDate( const char *, OGRField * );
213 
214     void                SetInitialQueryCursor();
215     void                CloseCursor();
216 
217     virtual CPLString   GetFromClauseForGetExtent() = 0;
218     OGRErr              RunGetExtentRequest( OGREnvelope *psExtent, int bForce,
219                                              CPLString osCommand, int bErrorAsDebug );
220     static void         CreateMapFromFieldNameToIndex(PGresult* hResult,
221                                                       OGRFeatureDefn* poFeatureDefn,
222                                                       int*& panMapFieldNameToIndex,
223                                                       int*& panMapFieldNameToGeomIndex);
224 
225     int                 ReadResultDefinition(PGresult *hInitialResultIn);
226 
227     OGRFeature         *RecordToFeature( PGresult* hResult,
228                                          const int* panMapFieldNameToIndex,
229                                          const int* panMapFieldNameToGeomIndex,
230                                          int iRecord );
231     OGRFeature         *GetNextRawFeature();
232 
233   public:
234                         OGRPGLayer();
235     virtual             ~OGRPGLayer();
236 
237     virtual void        ResetReading() override;
238 
GetLayerDefn()239     virtual OGRPGFeatureDefn *    GetLayerDefn() override { return poFeatureDefn; }
240 
GetExtent(OGREnvelope * psExtent,int bForce)241     virtual OGRErr      GetExtent( OGREnvelope *psExtent, int bForce ) override { return GetExtent(0, psExtent, bForce); }
242     virtual OGRErr      GetExtent( int iGeomField, OGREnvelope *psExtent, int bForce ) override;
243 
244     virtual OGRErr      StartTransaction() override;
245     virtual OGRErr      CommitTransaction() override;
246     virtual OGRErr      RollbackTransaction() override;
247 
248     void                InvalidateCursor();
249 
250     virtual const char *GetFIDColumn() override;
251 
252     virtual OGRErr      SetNextByIndex( GIntBig nIndex ) override;
253 
GetDS()254     OGRPGDataSource    *GetDS() { return poDS; }
255 
256     virtual void        ResolveSRID(const OGRPGGeomFieldDefn* poGFldDefn) = 0;
257 };
258 
259 /************************************************************************/
260 /*                           OGRPGTableLayer                            */
261 /************************************************************************/
262 
263 class OGRPGTableLayer final: public OGRPGLayer
264 {
265     OGRPGTableLayer( const OGRPGTableLayer&) = delete;
266     OGRPGTableLayer& operator=( const OGRPGTableLayer&) = delete;
267 
268     static constexpr int USE_COPY_UNSET = -10;
269 
270     int                 bUpdateAccess = false;
271 
272     void                BuildWhere();
273     CPLString           BuildFields();
274     void                BuildFullQueryStatement();
275 
276     char               *pszTableName = nullptr;
277     char               *pszSchemaName = nullptr;
278     char               *pszDescription = nullptr;
279     CPLString           osForcedDescription{};
280     char               *pszSqlTableName = nullptr;
281     int                 bTableDefinitionValid = -1;
282 
283     CPLString           osPrimaryKey{};
284 
285     int                 bGeometryInformationSet = false;
286 
287     /* Name of the parent table with the geometry definition if it is a derived table or NULL */
288     char               *pszSqlGeomParentTableName = nullptr;
289 
290     char               *pszGeomColForced = nullptr;
291 
292     CPLString           osQuery{};
293     CPLString           osWHERE{};
294 
295     int                 bLaunderColumnNames = true;
296     int                 bPreservePrecision = true;
297     int                 bUseCopy = USE_COPY_UNSET;
298     int                 bCopyActive = false;
299     bool                bFIDColumnInCopyFields = false;
300     int                 bFirstInsertion = true;
301 
302     OGRErr              CreateFeatureViaCopy( OGRFeature *poFeature );
303     OGRErr              CreateFeatureViaInsert( OGRFeature *poFeature );
304     CPLString           BuildCopyFields();
305 
306     int                 bHasWarnedIncompatibleGeom = false;
307     void                CheckGeomTypeCompatibility(int iGeomField, OGRGeometry* poGeom);
308 
309     int                 bRetrieveFID = true;
310     int                 bHasWarnedAlreadySetFID = false;
311 
312     char              **papszOverrideColumnTypes = nullptr;
313     int                 nForcedSRSId = UNDETERMINED_SRID;
314     int                 nForcedGeometryTypeFlags = -1;
315     bool                bCreateSpatialIndexFlag = true;
316     CPLString           osSpatialIndexType = "GIST";
317     int                 bInResetReading = false;
318 
319     int                 bAutoFIDOnCreateViaCopy = false;
320     int                 bUseCopyByDefault = false;
321     bool                bNeedToUpdateSequence = false;
322 
323     int                 bDeferredCreation = false;
324     CPLString           osCreateTable{};
325 
326     int                 iFIDAsRegularColumnIndex = -1;
327 
328     CPLString           m_osFirstGeometryFieldName{};
329 
330     std::vector<bool>   m_abGeneratedColumns{};
331 
GetFromClauseForGetExtent()332     virtual CPLString   GetFromClauseForGetExtent() override { return pszSqlTableName; }
333 
334     OGRErr              RunAddGeometryColumn( OGRPGGeomFieldDefn *poGeomField );
335     OGRErr              RunCreateSpatialIndex( OGRPGGeomFieldDefn *poGeomField );
336 
337     void                UpdateSequenceIfNeeded();
338 
339 public:
340                         OGRPGTableLayer( OGRPGDataSource *,
341                                          CPLString& osCurrentSchema,
342                                          const char * pszTableName,
343                                          const char * pszSchemaName,
344                                          const char * pszDescriptionIn,
345                                          const char * pszGeomColForced,
346                                          int bUpdate );
347                         virtual ~OGRPGTableLayer();
348 
349     void                SetGeometryInformation(PGGeomColumnDesc* pasDesc,
350                                                int nGeomFieldCount);
351 
352     virtual OGRFeature *GetFeature( GIntBig nFeatureId ) override;
353     virtual void        ResetReading() override;
354     virtual OGRFeature *GetNextFeature() override;
355     virtual GIntBig     GetFeatureCount( int ) override;
356 
SetSpatialFilter(OGRGeometry * poGeom)357     virtual void        SetSpatialFilter( OGRGeometry *poGeom ) override { SetSpatialFilter(0, poGeom); }
358     virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom ) override;
359 
360     virtual OGRErr      SetAttributeFilter( const char * ) override;
361 
362     virtual OGRErr      ISetFeature( OGRFeature *poFeature ) override;
363     virtual OGRErr      DeleteFeature( GIntBig nFID ) override;
364     virtual OGRErr      ICreateFeature( OGRFeature *poFeature ) override;
365 
366     virtual OGRErr      CreateField( OGRFieldDefn *poField,
367                                      int bApproxOK = TRUE ) override;
368     virtual OGRErr      CreateGeomField( OGRGeomFieldDefn *poGeomField,
369                                          int bApproxOK = TRUE ) override;
370     virtual OGRErr      DeleteField( int iField ) override;
371     virtual OGRErr      AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn, int nFlags ) override;
372 
373     virtual int         TestCapability( const char * ) override;
374 
GetExtent(OGREnvelope * psExtent,int bForce)375     virtual OGRErr      GetExtent( OGREnvelope *psExtent, int bForce ) override { return GetExtent(0, psExtent, bForce); }
376     virtual OGRErr      GetExtent( int iGeomField, OGREnvelope *psExtent, int bForce ) override;
377 
GetTableName()378     const char*         GetTableName() { return pszTableName; }
GetSchemaName()379     const char*         GetSchemaName() { return pszSchemaName; }
380 
381     virtual const char *GetFIDColumn() override;
382 
383     virtual char      **GetMetadataDomainList() override;
384     virtual char      **GetMetadata(const char* pszDomain = "") override;
385     virtual const char *GetMetadataItem(const char* pszName, const char* pszDomain = "") override;
386     virtual CPLErr      SetMetadata(char** papszMD, const char* pszDomain = "") override;
387     virtual CPLErr      SetMetadataItem(const char* pszName, const char* pszValue, const char* pszDomain = "") override;
388 
389     // follow methods are not base class overrides
SetLaunderFlag(int bFlag)390     void                SetLaunderFlag( int bFlag )
391                                 { bLaunderColumnNames = bFlag; }
SetPrecisionFlag(int bFlag)392     void                SetPrecisionFlag( int bFlag )
393                                 { bPreservePrecision = bFlag; }
394 
395     void                SetOverrideColumnTypes( const char* pszOverrideColumnTypes );
396 
397     OGRErr              StartCopy();
398     OGRErr              EndCopy();
399 
400     int                 ReadTableDefinition();
HasGeometryInformation()401     int                 HasGeometryInformation() { return bGeometryInformationSet; }
402     void                SetTableDefinition(const char* pszFIDColumnName,
403                                            const char* pszGFldName,
404                                            OGRwkbGeometryType eType,
405                                            const char* pszGeomType,
406                                            int nSRSId,
407                                            int GeometryTypeFlags);
408 
SetForcedSRSId(int nForcedSRSIdIn)409     void                SetForcedSRSId( int nForcedSRSIdIn )
410                                 { nForcedSRSId = nForcedSRSIdIn; }
SetForcedGeometryTypeFlags(int GeometryTypeFlagsIn)411     void                SetForcedGeometryTypeFlags( int GeometryTypeFlagsIn )
412                                 { nForcedGeometryTypeFlags = GeometryTypeFlagsIn; }
SetCreateSpatialIndex(bool bFlag,const char * pszSpatialIndexType)413     void                SetCreateSpatialIndex( bool bFlag, const char* pszSpatialIndexType )
414                                 { bCreateSpatialIndexFlag = bFlag;
415                                   osSpatialIndexType = pszSpatialIndexType; }
416     void                SetForcedDescription( const char* pszDescriptionIn );
AllowAutoFIDOnCreateViaCopy()417     void                AllowAutoFIDOnCreateViaCopy() { bAutoFIDOnCreateViaCopy = TRUE; }
SetUseCopy()418     void                SetUseCopy() { bUseCopy = TRUE; bUseCopyByDefault = TRUE; }
419 
420     void                SetDeferredCreation(int bDeferredCreationIn, CPLString osCreateTable);
421     OGRErr              RunDeferredCreationIfNecessary();
422 
423     virtual void        ResolveSRID(const OGRPGGeomFieldDefn* poGFldDefn) override;
424 };
425 
426 /************************************************************************/
427 /*                           OGRPGResultLayer                           */
428 /************************************************************************/
429 
430 class OGRPGResultLayer final: public OGRPGLayer
431 {
432     OGRPGResultLayer( const OGRPGResultLayer&) = delete;
433     OGRPGResultLayer& operator=( const OGRPGResultLayer&) = delete;
434 
435     void                BuildFullQueryStatement();
436 
437     char                *pszRawStatement = nullptr;
438 
439     char                *pszGeomTableName = nullptr;
440     char                *pszGeomTableSchemaName = nullptr;
441 
442     CPLString           osWHERE{};
443 
GetFromClauseForGetExtent()444     virtual CPLString   GetFromClauseForGetExtent() override
445         { CPLString osStr("(");
446           osStr += pszRawStatement; osStr += ")"; return osStr; }
447 
448   public:
449                         OGRPGResultLayer( OGRPGDataSource *,
450                                           const char * pszRawStatement,
451                                           PGresult *hInitialResult );
452     virtual             ~OGRPGResultLayer();
453 
454     virtual void        ResetReading() override;
455     virtual GIntBig     GetFeatureCount( int ) override;
456 
SetSpatialFilter(OGRGeometry * poGeom)457     virtual void        SetSpatialFilter( OGRGeometry *poGeom ) override { SetSpatialFilter(0, poGeom); }
458     virtual void        SetSpatialFilter( int iGeomField, OGRGeometry *poGeom ) override;
459 
460     virtual int         TestCapability( const char * ) override;
461 
462     virtual OGRFeature *GetNextFeature() override;
463 
464     virtual void        ResolveSRID(const OGRPGGeomFieldDefn* poGFldDefn) override;
465 };
466 
467 /************************************************************************/
468 /*                           OGRPGDataSource                            */
469 /************************************************************************/
470 
471 class OGRPGDataSource final: public OGRDataSource
472 {
473     OGRPGDataSource( const OGRPGDataSource&) = delete;
474     OGRPGDataSource& operator=( const OGRPGDataSource&) = delete;
475 
476     typedef struct
477     {
478         int nMajor;
479         int nMinor;
480         int nRelease;
481     } PGver;
482 
483     OGRPGTableLayer   **papoLayers = nullptr;
484     int                 nLayers = 0;
485 
486     char               *pszName = nullptr;
487 
488     int                 bDSUpdate = false;
489     int                 bHavePostGIS = false;
490     int                 bHaveGeography = false;
491 
492     int                 bUserTransactionActive = false;
493     int                 bSavePointActive = false;
494     int                 nSoftTransactionLevel = 0;
495 
496     PGconn              *hPGConn = nullptr;
497 
498     OGRErr              DeleteLayer( int iLayer ) override;
499 
500     Oid                 nGeometryOID = static_cast<Oid>(0);
501     Oid                 nGeographyOID = static_cast<Oid>(0);
502 
503     // We maintain a list of known SRID to reduce the number of trips to
504     // the database to get SRSes.
505     int                 nKnownSRID = 0;
506     int                 *panSRID = nullptr;
507     OGRSpatialReference **papoSRS = nullptr;
508 
509     OGRPGTableLayer     *poLayerInCopyMode = nullptr;
510 
511     static void                OGRPGDecodeVersionString(PGver* psVersion, const char* pszVer);
512 
513     CPLString           osCurrentSchema{};
514     CPLString           GetCurrentSchema();
515 
516     // Actual value will be auto-detected if PostGIS >= 2.0 detected.
517     int                 nUndefinedSRID = -1;
518 
519     char               *pszForcedTables = nullptr;
520     char              **papszSchemaList = nullptr;
521     int                 bHasLoadTables = false;
522     CPLString           osActiveSchema{};
523     int                 bListAllTables = false;
524     void                LoadTables();
525 
526     CPLString           osDebugLastTransactionCommand{};
527     OGRErr              DoTransactionCommand(const char* pszCommand);
528 
529     OGRErr              FlushSoftTransaction();
530 
531   public:
532     PGver               sPostgreSQLVersion = {0,0,0};
533     PGver               sPostGISVersion = {0,0,0};
534 
535     int                 bUseBinaryCursor = false;
536     int                 bBinaryTimeFormatIsInt8 = false;
537     int                 bUseEscapeStringSyntax = false;
538 
539     bool                m_bHasGeometryColumns = false;
540     bool                m_bHasSpatialRefSys = false;
541 
GetUndefinedSRID()542     int                GetUndefinedSRID() const { return nUndefinedSRID; }
543 
544   public:
545                         OGRPGDataSource();
546                         virtual ~OGRPGDataSource();
547 
GetPGConn()548     PGconn              *GetPGConn() { return hPGConn; }
549 
550     int                 FetchSRSId( OGRSpatialReference * poSRS );
551     OGRSpatialReference *FetchSRS( int nSRSId );
552     static OGRErr              InitializeMetadataTables();
553 
554     int                 Open( const char *, int bUpdate, int bTestOpen,
555                               char** papszOpenOptions );
556     OGRPGTableLayer*    OpenTable( CPLString& osCurrentSchema,
557                                    const char * pszTableName,
558                                    const char * pszSchemaName,
559                                    const char * pszDescription,
560                                    const char * pszGeomColForced,
561                                    int bUpdate, int bTestOpen );
562 
GetName()563     const char          *GetName() override { return pszName; }
564     int                 GetLayerCount() override;
565     OGRLayer            *GetLayer( int ) override;
566     OGRLayer            *GetLayerByName(const char * pszName) override;
567 
568     virtual void        FlushCache() override;
569 
570     virtual OGRLayer    *ICreateLayer( const char *,
571                                       OGRSpatialReference * = nullptr,
572                                       OGRwkbGeometryType = wkbUnknown,
573                                       char ** = nullptr ) override;
574 
575     int                 TestCapability( const char * ) override;
576 
577     virtual OGRErr      StartTransaction(int bForce = FALSE) override;
578     virtual OGRErr      CommitTransaction() override;
579     virtual OGRErr      RollbackTransaction() override;
580 
581     OGRErr              SoftStartTransaction();
582     OGRErr              SoftCommitTransaction();
583     OGRErr              SoftRollbackTransaction();
584 
GetGeometryOID()585     Oid                 GetGeometryOID() { return nGeometryOID; }
GetGeographyOID()586     Oid                 GetGeographyOID() { return nGeographyOID; }
587 
588     virtual OGRLayer *  ExecuteSQL( const char *pszSQLCommand,
589                                     OGRGeometry *poSpatialFilter,
590                                     const char *pszDialect ) override;
591     virtual OGRErr      AbortSQL() override;
592     virtual void        ReleaseResultSet( OGRLayer * poLayer ) override;
593 
594     virtual const char* GetMetadataItem(const char* pszKey,
595                                              const char* pszDomain) override;
596 
597     int                 UseCopy();
598     void                StartCopy( OGRPGTableLayer *poPGLayer );
599     OGRErr              EndCopy( );
600 };
601 
602 #endif /* ndef OGR_PG_H_INCLUDED */
603