Line data Source code
1 : /******************************************************************************
2 : * $Id$
3 : *
4 : * Project: MSSQL Spatial driver
5 : * Purpose: Definition of classes for OGR MSSQL Spatial driver.
6 : * Author: Tamas Szekeres, szekerest at gmail.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2010, Tamas Szekeres
10 : *
11 : * SPDX-License-Identifier: MIT
12 : ****************************************************************************/
13 :
14 : #ifndef OGR_MSSQLSPATIAL_H_INCLUDED
15 : #define OGR_MSSQLSPATIAL_H_INCLUDED
16 :
17 : #include "ogrsf_frmts.h"
18 : #include "cpl_odbc.h"
19 : #include "cpl_error.h"
20 :
21 : #ifdef SQLNCLI_VERSION
22 : #include <sqlncli.h>
23 : #endif
24 : #ifdef MSODBCSQL_VERSION
25 : #include "include_msodbcsql.h"
26 : #endif
27 :
28 : #include <map>
29 :
30 : class OGRMSSQLSpatialDataSource;
31 :
32 : /* layer status */
33 : #define MSSQLLAYERSTATUS_ORIGINAL 0
34 : #define MSSQLLAYERSTATUS_INITIAL 1
35 : #define MSSQLLAYERSTATUS_CREATED 2
36 : #define MSSQLLAYERSTATUS_DISABLED 3
37 :
38 : /* geometry format to transfer geometry column */
39 : #define MSSQLGEOMETRY_NATIVE 0
40 : #define MSSQLGEOMETRY_WKB 1
41 : #define MSSQLGEOMETRY_WKT 2
42 : #define MSSQLGEOMETRY_WKBZM 3 /* SQL Server 2012 */
43 :
44 : /* geometry column types */
45 : #define MSSQLCOLTYPE_GEOMETRY 0
46 : #define MSSQLCOLTYPE_GEOGRAPHY 1
47 : #define MSSQLCOLTYPE_BINARY 2
48 : #define MSSQLCOLTYPE_TEXT 3
49 :
50 : /* sqlgeometry constants */
51 :
52 : #define VA_KATMAI 0x01
53 : #define VA_DENALI 0x02
54 :
55 : #define SP_NONE 0
56 : #define SP_HASZVALUES 1
57 : #define SP_HASMVALUES 2
58 : #define SP_ISVALID 4
59 : #define SP_ISSINGLEPOINT 8
60 : #define SP_ISSINGLELINESEGMENT 0x10
61 : #define SP_ISLARGERTHANAHEMISPHERE 0x20
62 :
63 : #define ST_UNKNOWN 0
64 : #define ST_POINT 1
65 : #define ST_LINESTRING 2
66 : #define ST_POLYGON 3
67 : #define ST_MULTIPOINT 4
68 : #define ST_MULTILINESTRING 5
69 : #define ST_MULTIPOLYGON 6
70 : #define ST_GEOMETRYCOLLECTION 7
71 : #define ST_CIRCULARSTRING 8
72 : #define ST_COMPOUNDCURVE 9
73 : #define ST_CURVEPOLYGON 10
74 : #define ST_FULLGLOBE 11
75 :
76 : #define FA_INTERIORRING 0x00
77 : #define FA_STROKE 0x01
78 : #define FA_EXTERIORRING 0x02
79 :
80 : #define FA_NONE 0x00
81 : #define FA_LINE 0x01
82 : #define FA_ARC 0x02
83 : #define FA_CURVE 0x03
84 :
85 : #define SMT_LINE 0
86 : #define SMT_ARC 1
87 : #define SMT_FIRSTLINE 2
88 : #define SMT_FIRSTARC 3
89 :
90 : /************************************************************************/
91 : /* OGRMSSQLAppendEscaped( ) */
92 : /************************************************************************/
93 :
94 : void OGRMSSQLAppendEscaped(CPLODBCStatement *poStatement,
95 : const char *pszStrValue);
96 :
97 : /************************************************************************/
98 : /* OGRMSSQLGeometryParser */
99 : /************************************************************************/
100 :
101 : class OGRMSSQLGeometryValidator
102 : {
103 : protected:
104 : bool bIsValid;
105 : OGRGeometry *poValidGeometry;
106 : OGRGeometry *poOriginalGeometry;
107 : int nGeomColumnType;
108 :
109 : public:
110 : explicit OGRMSSQLGeometryValidator(OGRGeometry *poGeom,
111 : int nGeomColumnType);
112 : ~OGRMSSQLGeometryValidator();
113 :
114 : bool IsValidLatLon(double longitude, double latitude);
115 : bool IsValidCircularZ(double z1, double z2);
116 : bool IsValidPolygonRingCount(const OGRCurve *poGeom);
117 : bool IsValidPolygonRingClosed(const OGRCurve *poGeom);
118 : bool IsValid(const OGRPoint *poGeom);
119 : bool IsValid(const OGRMultiPoint *poGeom);
120 : bool IsValid(const OGRCircularString *poGeom);
121 : bool IsValid(const OGRSimpleCurve *poGeom);
122 : bool IsValid(const OGRCompoundCurve *poGeom);
123 : bool IsValid(const OGRMultiLineString *poGeom);
124 : bool IsValid(const OGRCurvePolygon *poGeom);
125 : bool IsValid(const OGRMultiPolygon *poGeom);
126 : bool IsValid(const OGRGeometryCollection *poGeom);
127 : bool IsValid(const OGRGeometry *poGeom);
128 : void MakeValid(OGRPoint *poGeom);
129 : void MakeValid(OGRMultiPoint *poGeom);
130 : void MakeValid(OGRCircularString *poGeom);
131 : void MakeValid(OGRSimpleCurve *poGeom);
132 : void MakeValid(OGRCompoundCurve *poGeom);
133 : void MakeValid(OGRMultiLineString *poGeom);
134 : void MakeValid(OGRPolygon *poGeom);
135 : void MakeValid(OGRCurvePolygon *poGeom);
136 : void MakeValid(OGRMultiPolygon *poGeom);
137 : void MakeValid(OGRGeometryCollection *poGeom);
138 : void MakeValid(OGRGeometry *poGeom);
139 : bool ValidateGeometry(OGRGeometry *poGeom);
140 :
141 : OGRGeometry *GetValidGeometryRef();
142 :
143 0 : bool IsValid()
144 : {
145 0 : return bIsValid;
146 : }
147 : };
148 :
149 : /************************************************************************/
150 : /* OGRMSSQLGeometryParser */
151 : /************************************************************************/
152 :
153 : class OGRMSSQLGeometryParser
154 : {
155 : protected:
156 : unsigned char *pszData;
157 : /* version information */
158 : char chVersion;
159 : /* serialization properties */
160 : char chProps;
161 : /* point array */
162 : int nPointSize;
163 : int nPointPos;
164 : int nNumPoints;
165 : /* figure array */
166 : int nFigurePos;
167 : int nNumFigures;
168 : /* shape array */
169 : int nShapePos;
170 : int nNumShapes;
171 : /* segmenttype array */
172 : int nSegmentPos;
173 : int nNumSegments;
174 : int iSegment;
175 : int nSRSId;
176 : /* geometry or geography */
177 : int nColType;
178 :
179 : protected:
180 : OGRPoint *ReadPoint(int iFigure);
181 : OGRMultiPoint *ReadMultiPoint(int iShape);
182 : OGRErr ReadSimpleCurve(OGRSimpleCurve *poCurve, int iPoint, int iNextPoint);
183 : OGRLineString *ReadLineString(int iFigure);
184 : OGRLinearRing *ReadLinearRing(int iFigure);
185 : OGRMultiLineString *ReadMultiLineString(int iShape);
186 : OGRPolygon *ReadPolygon(int iShape);
187 : OGRMultiPolygon *ReadMultiPolygon(int iShape);
188 : OGRGeometryCollection *ReadGeometryCollection(int iShape);
189 : OGRCircularString *ReadCircularString(int iFigure);
190 : OGRCompoundCurve *ReadCompoundCurve(int iFigure);
191 : void AddCurveSegment(OGRCompoundCurve *poCompoundCurve,
192 : OGRSimpleCurve *poCurve, int iPoint, int iNextPoint);
193 : OGRCurvePolygon *ReadCurvePolygon(int iShape);
194 :
195 : public:
196 : explicit OGRMSSQLGeometryParser(int nGeomColumnType);
197 : OGRErr ParseSqlGeometry(unsigned char *pszInput, int nLen,
198 : OGRGeometry **poGeom);
199 :
200 0 : int GetSRSId()
201 : {
202 0 : return nSRSId;
203 : }
204 : };
205 :
206 : /************************************************************************/
207 : /* OGRMSSQLGeometryWriter */
208 : /************************************************************************/
209 :
210 : class OGRMSSQLGeometryWriter
211 : {
212 : protected:
213 : OGRGeometry *poGeom2;
214 : unsigned char *pszData;
215 : int nLen;
216 : /* version information */
217 : char chVersion;
218 : /* serialization properties */
219 : char chProps;
220 : /* point array */
221 : int nPointSize;
222 : int nPointPos;
223 : int nNumPoints;
224 : int iPoint;
225 : /* figure array */
226 : int nFigurePos;
227 : int nNumFigures;
228 : int iFigure;
229 : /* shape array */
230 : int nShapePos;
231 : int nNumShapes;
232 : int iShape;
233 : /* segmenttype array */
234 : int nSegmentPos;
235 : int nNumSegments;
236 : int iSegment;
237 : int nSRSId;
238 : /* geometry or geography */
239 : int nColType;
240 :
241 : protected:
242 : void WritePoint(OGRPoint *poGeom);
243 : void WritePoint(double x, double y);
244 : void WritePoint(double x, double y, double z);
245 : void WritePoint(double x, double y, double z, double m);
246 : void WriteSimpleCurve(OGRSimpleCurve *poGeom, bool bReversePoints);
247 : void WriteSimpleCurve(OGRSimpleCurve *poGeom, int iStartIndex,
248 : bool bReversePoints);
249 : void WriteSimpleCurve(OGRSimpleCurve *poGeom, int iStartIndex, int nCount,
250 : bool bReversePoints);
251 : void WriteCompoundCurve(OGRCompoundCurve *poGeom);
252 : void WriteCurve(OGRCurve *poGeom, bool bReversePoints);
253 : void WritePolygon(OGRPolygon *poGeom);
254 : void WriteCurvePolygon(OGRCurvePolygon *poGeom);
255 : void WriteGeometryCollection(OGRGeometryCollection *poGeom, int iParent);
256 : void WriteGeometry(OGRGeometry *poGeom, int iParent);
257 : void TrackGeometry(OGRGeometry *poGeom);
258 :
259 : public:
260 : OGRMSSQLGeometryWriter(OGRGeometry *poGeometry, int nGeomColumnType,
261 : int nSRS);
262 : OGRErr WriteSqlGeometry(unsigned char *pszBuffer, int nBufLen);
263 :
264 0 : int GetDataLen()
265 : {
266 0 : return nLen;
267 : }
268 : };
269 :
270 : /************************************************************************/
271 : /* OGRMSSQLSpatialLayer */
272 : /************************************************************************/
273 :
274 : class OGRMSSQLSpatialLayer CPL_NON_FINAL : public OGRLayer
275 : {
276 : protected:
277 : OGRFeatureDefn *poFeatureDefn = nullptr;
278 : int nRawColumns = 0;
279 :
280 : CPLODBCStatement *poStmt = nullptr;
281 : bool m_bEOF = false;
282 : bool m_bResetNeeded = false;
283 :
284 : // Layer spatial reference system, and srid.
285 : OGRSpatialReference *poSRS = nullptr;
286 : int nSRSId = 0;
287 :
288 : GIntBig iNextShapeId = 0;
289 :
290 : OGRMSSQLSpatialDataSource *poDS = nullptr;
291 :
292 : int nGeomColumnType = -1;
293 : char *pszGeomColumn = nullptr;
294 : int nGeomColumnIndex = -1;
295 : char *pszFIDColumn = nullptr;
296 : int nFIDColumnIndex = -1;
297 :
298 : // UUID doesn't work for now in bulk copy mode
299 : bool m_bHasUUIDColumn = false;
300 :
301 : int bIsIdentityFid = FALSE;
302 :
303 : int nLayerStatus = MSSQLLAYERSTATUS_ORIGINAL;
304 :
305 : int *panFieldOrdinals = nullptr;
306 :
307 : void BuildFeatureDefn(const char *pszLayerName, CPLODBCStatement *poStmt);
308 :
309 0 : virtual CPLODBCStatement *GetStatement()
310 : {
311 0 : return poStmt;
312 : }
313 :
314 : void ClearStatement();
315 : OGRFeature *GetNextRawFeature();
316 : bool bLayerDefnNeedsRefresh = false;
317 :
318 : public:
319 : explicit OGRMSSQLSpatialLayer(OGRMSSQLSpatialDataSource *);
320 : virtual ~OGRMSSQLSpatialLayer();
321 :
322 : virtual void ResetReading() override;
323 : virtual OGRFeature *GetNextFeature() override;
324 :
325 : virtual OGRFeature *GetFeature(GIntBig nFeatureId) override;
326 :
327 0 : virtual OGRFeatureDefn *GetLayerDefn() override
328 : {
329 0 : return poFeatureDefn;
330 : }
331 :
332 : virtual OGRSpatialReference *GetSpatialRef() override;
333 :
334 : virtual OGRErr StartTransaction() override;
335 : virtual OGRErr CommitTransaction() override;
336 : virtual OGRErr RollbackTransaction() override;
337 :
338 : virtual const char *GetFIDColumn() override;
339 : virtual const char *GetGeometryColumn() override;
340 :
341 : virtual int TestCapability(const char *) override;
342 : static char *GByteArrayToHexString(const GByte *pabyData, int nLen);
343 :
344 0 : void SetLayerStatus(int nStatus)
345 : {
346 0 : nLayerStatus = nStatus;
347 0 : }
348 :
349 0 : int GetLayerStatus()
350 : {
351 0 : return nLayerStatus;
352 : }
353 :
354 : GDALDataset *GetDataset() override;
355 : };
356 :
357 : /************************************************************************/
358 : /* OGRMSSQLSpatialTableLayer */
359 : /************************************************************************/
360 :
361 : typedef union
362 : {
363 : struct
364 : {
365 : int iIndicator;
366 : int Value;
367 : } Integer;
368 :
369 : struct
370 : {
371 : int iIndicator;
372 : GIntBig Value;
373 : } Integer64;
374 :
375 : struct
376 : {
377 : int iIndicator;
378 : double Value;
379 : } Float;
380 :
381 : struct
382 : {
383 : SQLLEN nSize;
384 : char *pData[8000];
385 : } VarChar;
386 :
387 : struct
388 : {
389 : SQLLEN nSize;
390 : GByte *pData;
391 : } RawData;
392 :
393 : } BCPData;
394 :
395 : class OGRMSSQLSpatialTableLayer final : public OGRMSSQLSpatialLayer
396 : {
397 : bool bUpdateAccess = true;
398 : bool bUseGeometryValidation = false;
399 : int bLaunderColumnNames = FALSE;
400 : int bPreservePrecision = FALSE;
401 : int bNeedSpatialIndex = FALSE;
402 : int bUseCopy = FALSE;
403 : int nBCPSize = 1000;
404 :
405 : #ifdef SQL_SS_UDT
406 : int nUploadGeometryFormat = MSSQLGEOMETRY_NATIVE;
407 : #else
408 : int nUploadGeometryFormat = MSSQLGEOMETRY_WKB;
409 : #endif
410 :
411 : char *pszQuery = nullptr;
412 :
413 : SQLHANDLE hEnvBCP = nullptr;
414 : #ifdef MSSQL_BCP_SUPPORTED
415 : SQLHANDLE hDBCBCP = nullptr;
416 : int nBCPCount = 0;
417 : BCPData **papstBindBuffer = nullptr;
418 :
419 : int bIdentityInsert = FALSE;
420 : #endif
421 :
422 : CPLODBCStatement *BuildStatement(const char *pszColumns);
423 :
424 : CPLString BuildFields();
425 :
426 : virtual CPLODBCStatement *GetStatement() override;
427 :
428 : char *pszTableName = nullptr;
429 : char *pszLayerName = nullptr;
430 : char *pszSchemaName = nullptr;
431 :
432 : OGRwkbGeometryType eGeomType = wkbNone;
433 :
434 : public:
435 : explicit OGRMSSQLSpatialTableLayer(OGRMSSQLSpatialDataSource *);
436 : virtual ~OGRMSSQLSpatialTableLayer();
437 :
438 : CPLErr Initialize(const char *pszSchema, const char *pszTableName,
439 : const char *pszGeomCol, int nCoordDimension, int nSRId,
440 : const char *pszSRText, OGRwkbGeometryType eType);
441 :
442 : OGRErr CreateSpatialIndex();
443 : void DropSpatialIndex();
444 :
445 0 : virtual OGRErr GetExtent(OGREnvelope *psExtent, int bForce) override
446 : {
447 0 : return GetExtent(0, psExtent, bForce);
448 : }
449 :
450 : virtual OGRErr GetExtent(int iGeomField, OGREnvelope *psExtent,
451 : int bForce) override;
452 :
453 : virtual GIntBig GetFeatureCount(int) override;
454 :
455 : virtual OGRFeatureDefn *GetLayerDefn() override;
456 :
457 : virtual const char *GetName() override;
458 :
459 : virtual OGRErr SetAttributeFilter(const char *) override;
460 : virtual OGRFeature *GetNextFeature() override;
461 :
462 : virtual OGRErr ISetFeature(OGRFeature *poFeature) override;
463 : virtual OGRErr DeleteFeature(GIntBig nFID) override;
464 : virtual OGRErr ICreateFeature(OGRFeature *poFeature) override;
465 :
466 0 : const char *GetTableName()
467 : {
468 0 : return pszTableName;
469 : }
470 :
471 : const char *GetLayerName()
472 : {
473 : return pszLayerName;
474 : }
475 :
476 0 : const char *GetSchemaName()
477 : {
478 0 : return pszSchemaName;
479 : }
480 :
481 : virtual OGRErr CreateField(const OGRFieldDefn *poField,
482 : int bApproxOK = TRUE) override;
483 :
484 : virtual OGRFeature *GetFeature(GIntBig nFeatureId) override;
485 :
486 : virtual int TestCapability(const char *) override;
487 :
488 0 : void SetLaunderFlag(int bFlag)
489 : {
490 0 : bLaunderColumnNames = bFlag;
491 0 : }
492 :
493 0 : void SetPrecisionFlag(int bFlag)
494 : {
495 0 : bPreservePrecision = bFlag;
496 0 : }
497 :
498 0 : void SetSpatialIndexFlag(int bFlag)
499 : {
500 0 : bNeedSpatialIndex = bFlag;
501 0 : }
502 :
503 0 : void SetUploadGeometryFormat(int nGeometryFormat)
504 : {
505 0 : nUploadGeometryFormat = nGeometryFormat;
506 0 : }
507 :
508 : void AppendFieldValue(CPLODBCStatement *poStatement, OGRFeature *poFeature,
509 : int i, int *bind_num, void **bind_buffer);
510 :
511 : int FetchSRSId();
512 :
513 0 : void SetUseCopy(int bcpSize)
514 : {
515 0 : bUseCopy = TRUE;
516 0 : nBCPSize = bcpSize;
517 0 : }
518 :
519 0 : void SetUpdate(bool bFlag)
520 : {
521 0 : bUpdateAccess = bFlag;
522 0 : }
523 :
524 : // cppcheck-suppress functionStatic
525 : OGRErr StartCopy();
526 : // cppcheck-suppress functionStatic
527 : OGRErr EndCopy();
528 :
529 : int Failed(int nRetCode);
530 : #ifdef MSSQL_BCP_SUPPORTED
531 : OGRErr CreateFeatureBCP(OGRFeature *poFeature);
532 : int Failed2(int nRetCode);
533 : int InitBCP(const char *pszDSN);
534 : void CloseBCP();
535 : #endif
536 : };
537 :
538 : /************************************************************************/
539 : /* OGRMSSQLSpatialSelectLayer */
540 : /************************************************************************/
541 :
542 : class OGRMSSQLSpatialSelectLayer final : public OGRMSSQLSpatialLayer
543 : {
544 : char *pszBaseStatement;
545 :
546 : virtual CPLODBCStatement *GetStatement() override;
547 :
548 : public:
549 : OGRMSSQLSpatialSelectLayer(OGRMSSQLSpatialDataSource *, CPLODBCStatement *);
550 : virtual ~OGRMSSQLSpatialSelectLayer();
551 :
552 : virtual GIntBig GetFeatureCount(int) override;
553 :
554 : virtual OGRFeature *GetFeature(GIntBig nFeatureId) override;
555 :
556 : virtual OGRErr GetExtent(OGREnvelope *psExtent, int bForce = TRUE) override;
557 :
558 0 : virtual OGRErr GetExtent(int iGeomField, OGREnvelope *psExtent,
559 : int bForce) override
560 : {
561 0 : return OGRLayer::GetExtent(iGeomField, psExtent, bForce);
562 : }
563 :
564 : virtual int TestCapability(const char *) override;
565 : };
566 :
567 : /************************************************************************/
568 : /* OGRODBCDataSource */
569 : /************************************************************************/
570 :
571 : class OGRMSSQLSpatialDataSource final : public GDALDataset
572 : {
573 : typedef struct
574 : {
575 : int nMajor;
576 : int nMinor;
577 : int nBuild;
578 : int nRevision;
579 : } MSSQLVer;
580 :
581 : OGRMSSQLSpatialTableLayer **papoLayers;
582 : int nLayers;
583 :
584 : char *pszCatalog;
585 :
586 : bool bDSUpdate;
587 : CPLODBCSession oSession;
588 :
589 : int nGeometryFormat;
590 :
591 : int bUseGeometryColumns;
592 : bool bAlwaysOutputFid;
593 :
594 : int bListAllTables;
595 :
596 : int nBCPSize;
597 : int bUseCopy;
598 :
599 : // We maintain a list of known SRID to reduce the number of trips to
600 : // the database to get SRSes.
601 : std::map<int,
602 : std::unique_ptr<OGRSpatialReference, OGRSpatialReferenceReleaser>>
603 : m_oSRSCache{};
604 :
605 : OGRMSSQLSpatialTableLayer *poLayerInCopyMode;
606 :
607 : static void OGRMSSQLDecodeVersionString(MSSQLVer *psVersion,
608 : const char *pszVer);
609 :
610 : char *pszConnection;
611 :
612 : public:
613 : MSSQLVer sMSSQLVersion;
614 :
615 : OGRMSSQLSpatialDataSource();
616 : virtual ~OGRMSSQLSpatialDataSource();
617 :
618 0 : const char *GetCatalog()
619 : {
620 0 : return pszCatalog;
621 : }
622 :
623 : static int ParseValue(char **pszValue, char *pszSource, const char *pszKey,
624 : int nStart, int nNext, int nTerm, int bRemove);
625 :
626 : int Open(const char *, bool bUpdate, int bTestOpen);
627 : int OpenTable(const char *pszSchemaName, const char *pszTableName,
628 : const char *pszGeomCol, int nCoordDimension, int nSRID,
629 : const char *pszSRText, OGRwkbGeometryType eType,
630 : bool bUpdate);
631 :
632 : int GetLayerCount() override;
633 : OGRLayer *GetLayer(int) override;
634 : OGRLayer *GetLayerByName(const char *pszLayerName) override;
635 :
636 0 : int GetGeometryFormat()
637 : {
638 0 : return nGeometryFormat;
639 : }
640 :
641 0 : int UseGeometryColumns()
642 : {
643 0 : return bUseGeometryColumns;
644 : }
645 :
646 0 : bool AlwaysOutputFid()
647 : {
648 0 : return bAlwaysOutputFid;
649 : }
650 :
651 : virtual OGRErr DeleteLayer(int iLayer) override;
652 : OGRLayer *ICreateLayer(const char *pszName,
653 : const OGRGeomFieldDefn *poGeomFieldDefn,
654 : CSLConstList papszOptions) override;
655 :
656 : int TestCapability(const char *) override;
657 :
658 : virtual OGRLayer *ExecuteSQL(const char *pszSQLCommand,
659 : OGRGeometry *poSpatialFilter,
660 : const char *pszDialect) override;
661 : virtual void ReleaseResultSet(OGRLayer *poLayer) override;
662 :
663 : static char *LaunderName(const char *pszSrcName);
664 : OGRErr InitializeMetadataTables();
665 :
666 : OGRSpatialReference *AddSRIDToCache(
667 : int nId,
668 : std::unique_ptr<OGRSpatialReference, OGRSpatialReferenceReleaser>
669 : &&poSRS);
670 :
671 : OGRSpatialReference *FetchSRS(int nId);
672 : int FetchSRSId(const OGRSpatialReference *poSRS);
673 :
674 : OGRErr StartTransaction(CPL_UNUSED int bForce) override;
675 : OGRErr CommitTransaction() override;
676 : OGRErr RollbackTransaction() override;
677 :
678 : // Internal use
679 0 : CPLODBCSession *GetSession()
680 : {
681 0 : return &oSession;
682 : }
683 :
684 : const char *GetConnectionString()
685 : {
686 : return pszConnection;
687 : }
688 :
689 : void StartCopy(OGRMSSQLSpatialTableLayer *poMSSQLSpatialLayer);
690 : OGRErr EndCopy();
691 : };
692 :
693 : #endif /* ndef OGR_MSSQLSPATIAL_H_INCLUDED */
|