Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: GDAL/OGR Geography Network support (Geographic Network Model)
4 : * Purpose: GNM db based generic driver.
5 : * Authors: Mikhail Gusev (gusevmihs at gmail dot com)
6 : * Dmitry Baryshnikov, polimax@mail.ru
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2014, Mikhail Gusev
10 : * Copyright (c) 2014-2015, NextGIS <info@nextgis.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 "gnmdb.h"
32 : #include "gnm_priv.h"
33 :
34 0 : GNMDatabaseNetwork::GNMDatabaseNetwork() : GNMGenericNetwork()
35 : {
36 0 : m_poDS = nullptr;
37 0 : }
38 :
39 0 : GNMDatabaseNetwork::~GNMDatabaseNetwork()
40 : {
41 0 : FlushCache(true);
42 :
43 0 : GDALClose(m_poDS);
44 0 : }
45 :
46 0 : CPLErr GNMDatabaseNetwork::Open(GDALOpenInfo *poOpenInfo)
47 : {
48 0 : FormName(poOpenInfo->pszFilename, poOpenInfo->papszOpenOptions);
49 :
50 0 : if (CSLFindName(poOpenInfo->papszOpenOptions, "LIST_ALL_TABLES") == -1)
51 0 : poOpenInfo->papszOpenOptions = CSLAddNameValue(
52 : poOpenInfo->papszOpenOptions, "LIST_ALL_TABLES", "YES");
53 :
54 0 : m_poDS = (GDALDataset *)GDALOpenEx(m_soNetworkFullName,
55 : GDAL_OF_VECTOR | GDAL_OF_UPDATE, nullptr,
56 0 : nullptr, poOpenInfo->papszOpenOptions);
57 :
58 0 : if (nullptr == m_poDS)
59 : {
60 0 : CPLError(CE_Failure, CPLE_OpenFailed, "Open '%s' failed",
61 : m_soNetworkFullName.c_str());
62 0 : return CE_Failure;
63 : }
64 :
65 : // There should be only one schema so no schema name can be in table name
66 0 : if (LoadMetadataLayer(m_poDS) != CE_None)
67 : {
68 0 : return CE_Failure;
69 : }
70 :
71 0 : if (LoadGraphLayer(m_poDS) != CE_None)
72 : {
73 0 : return CE_Failure;
74 : }
75 :
76 0 : if (LoadFeaturesLayer(m_poDS) != CE_None)
77 : {
78 0 : return CE_Failure;
79 : }
80 :
81 0 : return CE_None;
82 : }
83 :
84 0 : CPLErr GNMDatabaseNetwork::Create(const char *pszFilename, char **papszOptions)
85 : {
86 0 : FormName(pszFilename, papszOptions);
87 :
88 0 : if (m_soName.empty() || m_soNetworkFullName.empty())
89 : {
90 0 : CPLError(CE_Failure, CPLE_IllegalArg,
91 : "The network name should be present");
92 0 : return CE_Failure;
93 : }
94 :
95 0 : if (nullptr == m_poDS)
96 : {
97 0 : m_poDS = (GDALDataset *)GDALOpenEx(m_soNetworkFullName,
98 : GDAL_OF_VECTOR | GDAL_OF_UPDATE,
99 : nullptr, nullptr, papszOptions);
100 : }
101 :
102 0 : if (nullptr == m_poDS)
103 : {
104 0 : CPLError(CE_Failure, CPLE_OpenFailed, "Open '%s' failed",
105 : m_soNetworkFullName.c_str());
106 0 : return CE_Failure;
107 : }
108 :
109 0 : GDALDriver *l_poDriver = m_poDS->GetDriver();
110 0 : if (nullptr == l_poDriver)
111 : {
112 0 : CPLError(CE_Failure, CPLE_OpenFailed, "Get dataset driver failed");
113 0 : return CE_Failure;
114 : }
115 :
116 0 : if (!CheckStorageDriverSupport(l_poDriver->GetDescription()))
117 : {
118 0 : return CE_Failure;
119 : }
120 :
121 : // check required options
122 :
123 : const char *pszNetworkDescription =
124 0 : CSLFetchNameValue(papszOptions, GNM_MD_DESCR);
125 0 : if (nullptr != pszNetworkDescription)
126 0 : sDescription = pszNetworkDescription;
127 :
128 : // check Spatial reference
129 0 : const char *pszSRS = CSLFetchNameValue(papszOptions, GNM_MD_SRS);
130 0 : if (nullptr == pszSRS)
131 : {
132 0 : CPLError(CE_Failure, CPLE_IllegalArg,
133 : "The network spatial reference should be present");
134 0 : return CE_Failure;
135 : }
136 : else
137 : {
138 0 : OGRSpatialReference spatialRef;
139 0 : spatialRef.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
140 0 : if (spatialRef.SetFromUserInput(pszSRS) != OGRERR_NONE)
141 : {
142 0 : CPLError(CE_Failure, CPLE_IllegalArg,
143 : "The network spatial reference should be present");
144 0 : return CE_Failure;
145 : }
146 :
147 0 : m_oSRS = std::move(spatialRef);
148 : }
149 :
150 0 : int nResult = CheckNetworkExist(pszFilename, papszOptions);
151 :
152 0 : if (TRUE == nResult)
153 : {
154 0 : CPLError(CE_Failure, CPLE_IllegalArg, "The network already exist");
155 0 : return CE_Failure;
156 : }
157 :
158 : // Create the necessary system layers and fields
159 :
160 : // Create meta layer
161 :
162 0 : CPLErr eResult = CreateMetadataLayer(m_poDS, GNM_VERSION_NUM);
163 :
164 0 : if (CE_None != eResult)
165 : {
166 : // an error message should come from function
167 0 : return CE_Failure;
168 : }
169 :
170 : // Create graph layer
171 :
172 0 : eResult = CreateGraphLayer(m_poDS);
173 :
174 0 : if (CE_None != eResult)
175 : {
176 0 : DeleteMetadataLayer();
177 0 : return CE_Failure;
178 : }
179 :
180 : // Create features layer
181 :
182 0 : eResult = CreateFeaturesLayer(m_poDS);
183 :
184 0 : if (CE_None != eResult)
185 : {
186 0 : DeleteMetadataLayer();
187 0 : DeleteGraphLayer();
188 0 : return CE_Failure;
189 : }
190 :
191 0 : return CE_None;
192 : }
193 :
194 0 : int GNMDatabaseNetwork::CheckNetworkExist(const char *pszFilename,
195 : char **papszOptions)
196 : {
197 : // check if path exist
198 : // if path exist check if network already present and OVERWRITE option
199 : // else create the path
200 :
201 0 : if (FormName(pszFilename, papszOptions) != CE_None)
202 : {
203 0 : return TRUE;
204 : }
205 :
206 0 : if (nullptr == m_poDS)
207 : {
208 0 : m_poDS = (GDALDataset *)GDALOpenEx(m_soNetworkFullName,
209 : GDAL_OF_VECTOR | GDAL_OF_UPDATE,
210 : nullptr, nullptr, papszOptions);
211 : }
212 :
213 0 : const bool bOverwrite = CPLFetchBool(papszOptions, "OVERWRITE", false);
214 :
215 0 : std::vector<int> anDeleteLayers;
216 : int i;
217 0 : for (i = 0; i < m_poDS->GetLayerCount(); ++i)
218 : {
219 0 : OGRLayer *poLayer = m_poDS->GetLayer(i);
220 0 : if (nullptr == poLayer)
221 0 : continue;
222 :
223 0 : if (EQUAL(poLayer->GetName(), GNM_SYSLAYER_META) ||
224 0 : EQUAL(poLayer->GetName(), GNM_SYSLAYER_GRAPH) ||
225 0 : EQUAL(poLayer->GetName(), GNM_SYSLAYER_FEATURES))
226 : {
227 0 : anDeleteLayers.push_back(i);
228 : }
229 : }
230 :
231 0 : if (anDeleteLayers.empty())
232 0 : return FALSE;
233 :
234 0 : if (bOverwrite)
235 : {
236 0 : for (i = (int)anDeleteLayers.size(); i > 0; i--)
237 : {
238 0 : CPLDebug("GNM", "Delete layer: %d", i);
239 0 : if (m_poDS->DeleteLayer(anDeleteLayers[i - 1]) != OGRERR_NONE)
240 0 : return TRUE;
241 : }
242 0 : return FALSE;
243 : }
244 : else
245 : {
246 0 : return TRUE;
247 : }
248 : }
249 :
250 0 : CPLErr GNMDatabaseNetwork::DeleteMetadataLayer()
251 : {
252 0 : return DeleteLayerByName(GNM_SYSLAYER_META);
253 : }
254 :
255 0 : CPLErr GNMDatabaseNetwork::DeleteGraphLayer()
256 : {
257 0 : return DeleteLayerByName(GNM_SYSLAYER_GRAPH);
258 : }
259 :
260 0 : CPLErr GNMDatabaseNetwork::DeleteFeaturesLayer()
261 : {
262 0 : return DeleteLayerByName(GNM_SYSLAYER_FEATURES);
263 : }
264 :
265 0 : CPLErr GNMDatabaseNetwork::DeleteLayerByName(const char *pszLayerName)
266 : {
267 0 : if (nullptr == m_poDS)
268 0 : return CE_Failure;
269 :
270 0 : for (int i = 0; i < m_poDS->GetLayerCount(); ++i)
271 : {
272 0 : OGRLayer *poLayer = m_poDS->GetLayer(i);
273 0 : if (nullptr == poLayer)
274 0 : continue;
275 :
276 0 : if (EQUAL(poLayer->GetName(), pszLayerName))
277 0 : return m_poDS->DeleteLayer(i) == OGRERR_NONE ? CE_None : CE_Failure;
278 : }
279 :
280 0 : CPLError(CE_Failure, CPLE_IllegalArg, "The layer %s not exist",
281 : pszLayerName);
282 0 : return CE_Failure;
283 : }
284 :
285 0 : CPLErr GNMDatabaseNetwork::DeleteNetworkLayers()
286 : {
287 0 : while (GetLayerCount() > 0)
288 : {
289 0 : OGRErr eErr = DeleteLayer(0);
290 0 : if (eErr != OGRERR_NONE)
291 0 : return CE_Failure;
292 : }
293 0 : return CE_None;
294 : }
295 :
296 0 : CPLErr GNMDatabaseNetwork::LoadNetworkLayer(const char *pszLayername)
297 : {
298 : // check if not loaded
299 0 : for (size_t i = 0; i < m_apoLayers.size(); ++i)
300 : {
301 0 : if (EQUAL(m_apoLayers[i]->GetName(), pszLayername))
302 0 : return CE_None;
303 : }
304 :
305 0 : OGRLayer *poLayer = m_poDS->GetLayerByName(pszLayername);
306 0 : if (nullptr == poLayer)
307 : {
308 0 : CPLError(CE_Failure, CPLE_OpenFailed, "Layer '%s' is not exist",
309 : pszLayername);
310 0 : return CE_Failure;
311 : }
312 :
313 0 : CPLDebug("GNM", "Layer '%s' loaded", poLayer->GetName());
314 :
315 0 : GNMGenericLayer *pGNMLayer = new GNMGenericLayer(poLayer, this);
316 0 : m_apoLayers.push_back(pGNMLayer);
317 :
318 0 : return CE_None;
319 : }
320 :
321 0 : bool GNMDatabaseNetwork::CheckStorageDriverSupport(const char *pszDriverName)
322 : {
323 0 : if (EQUAL(pszDriverName, "PostgreSQL"))
324 0 : return true;
325 : // TODO: expand this list with supported OGR direvers
326 0 : return false;
327 : }
328 :
329 0 : CPLErr GNMDatabaseNetwork::FormName(const char *pszFilename,
330 : char **papszOptions)
331 : {
332 0 : if (m_soNetworkFullName.empty())
333 0 : m_soNetworkFullName = pszFilename;
334 :
335 0 : if (m_soName.empty())
336 : {
337 : const char *pszNetworkName =
338 0 : CSLFetchNameValue(papszOptions, GNM_MD_NAME);
339 0 : if (nullptr != pszNetworkName)
340 : {
341 0 : m_soName = pszNetworkName;
342 : }
343 :
344 : char *pszActiveSchemaStart;
345 0 : pszActiveSchemaStart = (char *)strstr(pszFilename, "active_schema=");
346 0 : if (pszActiveSchemaStart == nullptr)
347 : pszActiveSchemaStart =
348 0 : (char *)strstr(pszFilename, "ACTIVE_SCHEMA=");
349 0 : if (pszActiveSchemaStart != nullptr)
350 : {
351 : char *pszActiveSchema;
352 :
353 : pszActiveSchema =
354 0 : CPLStrdup(pszActiveSchemaStart + strlen("active_schema="));
355 :
356 0 : const char *pszEnd = strchr(pszActiveSchemaStart, ' ');
357 0 : if (pszEnd == nullptr)
358 0 : pszEnd = pszFilename + strlen(pszFilename);
359 :
360 0 : pszActiveSchema[pszEnd - pszActiveSchemaStart -
361 0 : strlen("active_schema=")] = '\0';
362 :
363 0 : m_soName = pszActiveSchema;
364 0 : CPLFree(pszActiveSchema);
365 : }
366 : else
367 : {
368 0 : if (!m_soName.empty())
369 : {
370 : // add active schema
371 0 : m_soNetworkFullName += "ACTIVE_SCHEMA=" + m_soName;
372 : }
373 : else
374 : {
375 0 : m_soName = "public";
376 : }
377 : }
378 :
379 0 : CPLDebug("GNM", "Network name: %s", m_soName.c_str());
380 : }
381 0 : return CE_None;
382 : }
383 :
384 0 : OGRErr GNMDatabaseNetwork::DeleteLayer(int nIndex)
385 : {
386 0 : if (nullptr == m_poDS)
387 : {
388 0 : CPLError(CE_Failure, CPLE_FileIO, "Network not opened.");
389 0 : return OGRERR_FAILURE;
390 : }
391 :
392 0 : OGRLayer *poNetworkLayer = GetLayer(nIndex);
393 :
394 0 : CPLDebug("GNM", "Delete network layer '%s'", poNetworkLayer->GetName());
395 :
396 0 : int nDeleteIndex = -1;
397 0 : for (int i = 0; i < m_poDS->GetLayerCount(); ++i)
398 : {
399 0 : OGRLayer *poLayer = m_poDS->GetLayer(i);
400 0 : if (EQUAL(poNetworkLayer->GetName(), poLayer->GetName()))
401 : {
402 0 : nDeleteIndex = i;
403 0 : break;
404 : }
405 : }
406 :
407 0 : if (m_poDS->DeleteLayer(nDeleteIndex) != OGRERR_NONE)
408 : {
409 0 : return OGRERR_FAILURE;
410 : }
411 :
412 0 : return GNMGenericNetwork::DeleteLayer(nIndex);
413 : }
414 :
415 : OGRLayer *
416 0 : GNMDatabaseNetwork::ICreateLayer(const char *pszName,
417 : const OGRGeomFieldDefn *poGeomFieldDefn,
418 : CSLConstList papszOptions)
419 : {
420 : // check if layer with such name exist
421 0 : for (int i = 0; i < GetLayerCount(); ++i)
422 : {
423 0 : OGRLayer *pLayer = GetLayer(i);
424 0 : if (nullptr == pLayer)
425 0 : continue;
426 0 : if (EQUAL(pLayer->GetName(), pszName))
427 : {
428 0 : CPLError(CE_Failure, CPLE_IllegalArg,
429 : "The network layer '%s' already exist.", pszName);
430 0 : return nullptr;
431 : }
432 : }
433 :
434 0 : OGRSpatialReference oSpaRef(m_oSRS);
435 :
436 0 : const auto eGType = poGeomFieldDefn ? poGeomFieldDefn->GetType() : wkbNone;
437 : OGRLayer *poLayer =
438 0 : m_poDS->CreateLayer(pszName, &oSpaRef, eGType, papszOptions);
439 0 : if (poLayer == nullptr)
440 : {
441 0 : CPLError(CE_Failure, CPLE_FileIO, "Layer creation failed.");
442 0 : return nullptr;
443 : }
444 :
445 0 : OGRFieldDefn oField(GNM_SYSFIELD_GFID, GNMGFIDInt);
446 0 : if (poLayer->CreateField(&oField) != OGRERR_NONE)
447 : {
448 0 : CPLError(CE_Failure, CPLE_FileIO,
449 : "Creating global identificator field failed.");
450 0 : return nullptr;
451 : }
452 :
453 0 : OGRFieldDefn oFieldBlock(GNM_SYSFIELD_BLOCKED, OFTInteger);
454 0 : if (poLayer->CreateField(&oFieldBlock) != OGRERR_NONE)
455 : {
456 0 : CPLError(CE_Failure, CPLE_FileIO, "Creating is blocking field failed.");
457 0 : return nullptr;
458 : }
459 :
460 0 : GNMGenericLayer *pGNMLayer = new GNMGenericLayer(poLayer, this);
461 0 : m_apoLayers.push_back(pGNMLayer);
462 0 : return pGNMLayer;
463 : }
|