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