Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: FileGDB Translator
4 : * Purpose: Implements FileGDB OGR driver.
5 : * Author: Even Rouault, <even.rouault at spatialys.com>
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2010, Ragi Yaser Burhum
9 : * Copyright (c) 2011, Paul Ramsey <pramsey at cleverelephant.ca>
10 : * Copyright (c) 2011-2023, 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 : #include "ogrsf_frmts.h"
32 : #include "FGdbDriverCore.h"
33 :
34 : #define ENDS_WITH(str, strLen, end) \
35 : (strLen >= strlen(end) && EQUAL(str + strLen - strlen(end), end))
36 :
37 : /************************************************************************/
38 : /* OGRFileGDBDriverIdentifyInternal() */
39 : /************************************************************************/
40 :
41 40723 : GDALIdentifyEnum OGRFileGDBDriverIdentifyInternal(GDALOpenInfo *poOpenInfo,
42 : const char *&pszFilename)
43 : {
44 : // First check if we have to do any work.
45 40723 : size_t nLen = strlen(pszFilename);
46 40723 : if (ENDS_WITH(pszFilename, nLen, ".gdb") ||
47 39671 : ENDS_WITH(pszFilename, nLen, ".gdb/"))
48 : {
49 : // Check that the filename is really a directory, to avoid confusion
50 : // with Garmin MapSource - gdb format which can be a problem when the
51 : // driver is loaded as a plugin, and loaded before the GPSBabel driver
52 : // (http://trac.osgeo.org/osgeo4w/ticket/245)
53 238 : if (STARTS_WITH(pszFilename, "/vsi") || !poOpenInfo->bStatOK ||
54 109 : !poOpenInfo->bIsDirectory)
55 : {
56 132 : return GDAL_IDENTIFY_FALSE;
57 : }
58 106 : return GDAL_IDENTIFY_TRUE;
59 : }
60 40485 : else if (EQUAL(pszFilename, "."))
61 : {
62 3 : GDALIdentifyEnum eRet = GDAL_IDENTIFY_FALSE;
63 3 : char *pszCurrentDir = CPLGetCurrentDir();
64 3 : if (pszCurrentDir)
65 : {
66 3 : const char *pszTmp = pszCurrentDir;
67 3 : eRet = OGRFileGDBDriverIdentifyInternal(poOpenInfo, pszTmp);
68 3 : CPLFree(pszCurrentDir);
69 : }
70 3 : return eRet;
71 : }
72 : else
73 : {
74 40482 : return GDAL_IDENTIFY_FALSE;
75 : }
76 : }
77 :
78 : /************************************************************************/
79 : /* OGRFileGDBDriverIdentify() */
80 : /************************************************************************/
81 :
82 40667 : static int OGRFileGDBDriverIdentify(GDALOpenInfo *poOpenInfo)
83 : {
84 40667 : const char *pszFilename = poOpenInfo->pszFilename;
85 81334 : return OGRFileGDBDriverIdentifyInternal(poOpenInfo, pszFilename);
86 : }
87 :
88 : /************************************************************************/
89 : /* OGRFileGDBDriverSetCommonMetadata() */
90 : /************************************************************************/
91 :
92 1232 : void OGRFileGDBDriverSetCommonMetadata(GDALDriver *poDriver)
93 : {
94 1232 : poDriver->SetDescription(DRIVER_NAME);
95 1232 : poDriver->SetMetadataItem(GDAL_DMD_LONGNAME, "ESRI FileGDB");
96 1232 : poDriver->SetMetadataItem(GDAL_DCAP_VECTOR, "YES");
97 1232 : poDriver->SetMetadataItem(GDAL_DCAP_DELETE_LAYER, "YES");
98 1232 : poDriver->SetMetadataItem(GDAL_DCAP_CREATE_LAYER, "YES");
99 1232 : poDriver->SetMetadataItem(GDAL_DCAP_CREATE_FIELD, "YES");
100 1232 : poDriver->SetMetadataItem(GDAL_DCAP_DELETE_FIELD, "YES");
101 1232 : poDriver->SetMetadataItem(GDAL_DMD_EXTENSION, "gdb");
102 1232 : poDriver->SetMetadataItem(GDAL_DMD_HELPTOPIC,
103 1232 : "drivers/vector/filegdb.html");
104 :
105 1232 : poDriver->SetMetadataItem(GDAL_DMD_CREATIONOPTIONLIST,
106 1232 : "<CreationOptionList/>");
107 :
108 1232 : poDriver->SetMetadataItem(
109 : GDAL_DS_LAYER_CREATIONOPTIONLIST,
110 : "<LayerCreationOptionList>"
111 : " <Option name='FEATURE_DATASET' type='string' "
112 : "description='FeatureDataset folder into to put the new layer'/>"
113 : " <Option name='LAYER_ALIAS' type='string' description='Alias of "
114 : "layer name'/>"
115 : " <Option name='GEOMETRY_NAME' type='string' description='Name of "
116 : "geometry column' default='SHAPE'/>"
117 : " <Option name='GEOMETRY_NULLABLE' type='boolean' "
118 : "description='Whether the values of the geometry column can be NULL' "
119 : "default='YES'/>"
120 : " <Option name='FID' type='string' description='Name of OID column' "
121 : "default='OBJECTID' deprecated_alias='OID_NAME'/>"
122 : " <Option name='XYTOLERANCE' type='float' description='Snapping "
123 : "tolerance, used for advanced ArcGIS features like network and "
124 : "topology rules, on 2D coordinates, in the units of the CRS'/>"
125 : " <Option name='ZTOLERANCE' type='float' description='Snapping "
126 : "tolerance, used for advanced ArcGIS features like network and "
127 : "topology rules, on Z coordinates, in the units of the CRS'/>"
128 : " <Option name='MTOLERANCE' type='float' description='Snapping "
129 : "tolerance, used for advanced ArcGIS features like network and "
130 : "topology rules, on M coordinates'/>"
131 : " <Option name='XORIGIN' type='float' description='X origin of the "
132 : "coordinate precision grid'/>"
133 : " <Option name='YORIGIN' type='float' description='Y origin of the "
134 : "coordinate precision grid'/>"
135 : " <Option name='ZORIGIN' type='float' description='Z origin of the "
136 : "coordinate precision grid'/>"
137 : " <Option name='MORIGIN' type='float' description='M origin of the "
138 : "coordinate precision grid'/>"
139 : " <Option name='XYSCALE' type='float' description='X,Y scale of the "
140 : "coordinate precision grid'/>"
141 : " <Option name='ZSCALE' type='float' description='Z scale of the "
142 : "coordinate precision grid'/>"
143 : " <Option name='MSCALE' type='float' description='M scale of the "
144 : "coordinate precision grid'/>"
145 : " <Option name='XML_DEFINITION' type='string' description='XML "
146 : "definition to create the new table. The root node of such a XML "
147 : "definition must be a <esri:DataElement> element conformant to "
148 : "FileGDBAPI.xsd'/>"
149 : " <Option name='CREATE_MULTIPATCH' type='boolean' "
150 : "description='Whether to write geometries of layers of type "
151 : "MultiPolygon as MultiPatch' default='NO'/>"
152 : " <Option name='COLUMN_TYPES' type='string' description='A list of "
153 : "strings of format field_name=fgdb_field_type (separated by comma) to "
154 : "force the FileGDB column type of fields to be created'/>"
155 : " <Option name='CONFIGURATION_KEYWORD' type='string-select' "
156 : "description='Customize how data is stored. By default text in UTF-8 "
157 : "and data up to 1TB'>"
158 : " <Value>DEFAULTS</Value>"
159 : " <Value>TEXT_UTF16</Value>"
160 : " <Value>MAX_FILE_SIZE_4GB</Value>"
161 : " <Value>MAX_FILE_SIZE_256TB</Value>"
162 : " <Value>GEOMETRY_OUTOFLINE</Value>"
163 : " <Value>BLOB_OUTOFLINE</Value>"
164 : " <Value>GEOMETRY_AND_BLOB_OUTOFLINE</Value>"
165 : " </Option>"
166 : " <Option name='CREATE_SHAPE_AREA_AND_LENGTH_FIELDS' type='boolean' "
167 : "description='Whether to create special Shape_Length and Shape_Area "
168 : "fields' default='NO'/>"
169 1232 : "</LayerCreationOptionList>");
170 :
171 : // Setting to another value than the default one doesn't really work
172 : // with the SDK
173 : // Option name='AREA_FIELD_NAME' type='string' description='Name of
174 : // the column that contains the geometry area' default='Shape_Area'
175 : // Option name='length_field_name' type='string' description='Name of
176 : // the column that contains the geometry length'
177 : // default='Shape_Length'
178 :
179 1232 : poDriver->SetMetadataItem(GDAL_DMD_CREATIONFIELDDATATYPES,
180 1232 : "Integer Real String Date DateTime Binary");
181 1232 : poDriver->SetMetadataItem(GDAL_DMD_CREATIONFIELDDATASUBTYPES,
182 1232 : "Int16 Float32");
183 1232 : poDriver->SetMetadataItem(GDAL_DMD_CREATION_FIELD_DEFN_FLAGS,
184 : "Nullable Default "
185 1232 : "AlternativeName Domain");
186 1232 : poDriver->SetMetadataItem(GDAL_DCAP_NOTNULL_FIELDS, "YES");
187 1232 : poDriver->SetMetadataItem(GDAL_DCAP_DEFAULT_FIELDS, "YES");
188 1232 : poDriver->SetMetadataItem(GDAL_DCAP_NOTNULL_GEOMFIELDS, "YES");
189 1232 : poDriver->SetMetadataItem(GDAL_DCAP_MULTIPLE_VECTOR_LAYERS, "YES");
190 1232 : poDriver->SetMetadataItem(GDAL_DCAP_FIELD_DOMAINS, "YES");
191 1232 : poDriver->SetMetadataItem(GDAL_DCAP_RELATIONSHIPS, "YES");
192 1232 : poDriver->SetMetadataItem(GDAL_DCAP_RENAME_LAYERS, "YES");
193 1232 : poDriver->SetMetadataItem(GDAL_DCAP_MEASURED_GEOMETRIES, "YES");
194 1232 : poDriver->SetMetadataItem(GDAL_DCAP_Z_GEOMETRIES, "YES");
195 1232 : poDriver->SetMetadataItem(GDAL_DMD_GEOMETRY_FLAGS,
196 : "EquatesMultiAndSingleLineStringDuringWrite "
197 1232 : "EquatesMultiAndSinglePolygonDuringWrite");
198 : // see https://support.esri.com/en/technical-article/000010906
199 1232 : poDriver->SetMetadataItem(
200 : GDAL_DMD_ILLEGAL_FIELD_NAMES,
201 : "ADD ALTER AND BETWEEN BY COLUMN CREATE DELETE DROP EXISTS FOR FROM "
202 : "GROUP IN INSERT INTO IS LIKE NOT NULL OR ORDER SELECT SET TABLE "
203 1232 : "UPDATE VALUES WHERE");
204 1232 : poDriver->SetMetadataItem(GDAL_DMD_CREATION_FIELD_DOMAIN_TYPES,
205 1232 : "Coded Range");
206 1232 : poDriver->SetMetadataItem(GDAL_DMD_SUPPORTED_SQL_DIALECTS,
207 1232 : "NATIVE OGRSQL SQLITE");
208 1232 : poDriver->SetMetadataItem(GDAL_DMD_RELATIONSHIP_RELATED_TABLE_TYPES,
209 1232 : "features media");
210 1232 : poDriver->SetMetadataItem(GDAL_DCAP_HONOR_GEOM_COORDINATE_PRECISION, "YES");
211 :
212 1232 : poDriver->pfnIdentify = OGRFileGDBDriverIdentify;
213 1232 : poDriver->SetMetadataItem(GDAL_DCAP_OPEN, "YES");
214 1232 : poDriver->SetMetadataItem(GDAL_DCAP_CREATE, "YES");
215 1232 : }
216 :
217 : /************************************************************************/
218 : /* DeclareDeferredOGRFileGDBPlugin() */
219 : /************************************************************************/
220 :
221 : #ifdef PLUGIN_FILENAME
222 1520 : void DeclareDeferredOGRFileGDBPlugin()
223 : {
224 1520 : if (GDALGetDriverByName(DRIVER_NAME) != nullptr)
225 : {
226 301 : return;
227 : }
228 1219 : auto poDriver = new GDALPluginDriverProxy(PLUGIN_FILENAME);
229 : #ifdef PLUGIN_INSTALLATION_MESSAGE
230 : poDriver->SetMetadataItem(GDAL_DMD_PLUGIN_INSTALLATION_MESSAGE,
231 : PLUGIN_INSTALLATION_MESSAGE);
232 : #endif
233 1219 : OGRFileGDBDriverSetCommonMetadata(poDriver);
234 1219 : GetGDALDriverManager()->DeclareDeferredPluginDriver(poDriver);
235 : }
236 : #endif
|