1 : /******************************************************************************
2 : * $Id: ogrpgeodatasource.cpp 10645 2007-01-18 02:22:39Z warmerdam $
3 : *
4 : * Project: OpenGIS Simple Features Reference Implementation
5 : * Purpose: Implements OGRPGeoDataSource class.
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2005, Frank Warmerdam <warmerdam@pobox.com>
10 : *
11 : * Permission is hereby granted, free of charge, to any person obtaining a
12 : * copy of this software and associated documentation files (the "Software"),
13 : * to deal in the Software without restriction, including without limitation
14 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 : * and/or sell copies of the Software, and to permit persons to whom the
16 : * Software is furnished to do so, subject to the following conditions:
17 : *
18 : * The above copyright notice and this permission notice shall be included
19 : * in all copies or substantial portions of the Software.
20 : *
21 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 : * DEALINGS IN THE SOFTWARE.
28 : ****************************************************************************/
29 :
30 : #include "ogr_pgeo.h"
31 : #include "cpl_conv.h"
32 : #include "cpl_string.h"
33 : #include <vector>
34 :
35 : CPL_CVSID("$Id: ogrpgeodatasource.cpp 10645 2007-01-18 02:22:39Z warmerdam $");
36 :
37 : /************************************************************************/
38 : /* OGRPGeoDataSource() */
39 : /************************************************************************/
40 :
41 0 : OGRPGeoDataSource::OGRPGeoDataSource()
42 :
43 : {
44 0 : pszName = NULL;
45 0 : papoLayers = NULL;
46 0 : nLayers = 0;
47 0 : }
48 :
49 : /************************************************************************/
50 : /* ~OGRPGeoDataSource() */
51 : /************************************************************************/
52 :
53 0 : OGRPGeoDataSource::~OGRPGeoDataSource()
54 :
55 : {
56 : int i;
57 :
58 0 : CPLFree( pszName );
59 :
60 0 : for( i = 0; i < nLayers; i++ )
61 0 : delete papoLayers[i];
62 :
63 0 : CPLFree( papoLayers );
64 0 : }
65 :
66 : /************************************************************************/
67 : /* Open() */
68 : /************************************************************************/
69 :
70 : int OGRPGeoDataSource::Open( const char * pszNewName, int bUpdate,
71 0 : int bTestOpen )
72 :
73 : {
74 0 : CPLAssert( nLayers == 0 );
75 :
76 : /* -------------------------------------------------------------------- */
77 : /* If this is the name of an MDB file, then construct the */
78 : /* appropriate connection string. Otherwise clip of PGEO: to */
79 : /* get the DSN. */
80 : /* */
81 : /* -------------------------------------------------------------------- */
82 : char *pszDSN;
83 0 : if( EQUALN(pszNewName,"PGEO:",5) )
84 0 : pszDSN = CPLStrdup( pszNewName + 5 );
85 : else
86 : {
87 0 : pszDSN = (char *) CPLMalloc(strlen(pszNewName)+50);
88 : sprintf( pszDSN, "DRIVER=Microsoft Access Driver (*.mdb);DBQ=%s",
89 0 : pszNewName );
90 : }
91 :
92 : /* -------------------------------------------------------------------- */
93 : /* Initialize based on the DSN. */
94 : /* -------------------------------------------------------------------- */
95 0 : CPLDebug( "PGeo", "EstablishSession(%s)", pszDSN );
96 :
97 0 : if( !oSession.EstablishSession( pszDSN, NULL, NULL ) )
98 : {
99 : CPLError( CE_Failure, CPLE_AppDefined,
100 : "Unable to initialize ODBC connection to DSN for %s,\n"
101 0 : "%s", pszDSN, oSession.GetLastError() );
102 0 : CPLFree( pszDSN );
103 0 : return FALSE;
104 : }
105 :
106 0 : CPLFree( pszDSN );
107 :
108 0 : pszName = CPLStrdup( pszNewName );
109 :
110 0 : bDSUpdate = bUpdate;
111 :
112 : /* -------------------------------------------------------------------- */
113 : /* Collect list of tables and their supporting info from */
114 : /* GDB_GeomColumns. */
115 : /* -------------------------------------------------------------------- */
116 0 : std::vector<char **> apapszGeomColumns;
117 0 : CPLODBCStatement oStmt( &oSession );
118 :
119 0 : oStmt.Append( "SELECT TableName, FieldName, ShapeType, ExtentLeft, ExtentRight, ExtentBottom, ExtentTop, SRID, HasZ FROM GDB_GeomColumns" );
120 :
121 0 : if( !oStmt.ExecuteSQL() )
122 : {
123 : CPLDebug( "PGEO",
124 : "SELECT on GDB_GeomColumns fails, perhaps not a personal geodatabase?\n%s",
125 0 : oSession.GetLastError() );
126 0 : return FALSE;
127 : }
128 :
129 0 : while( oStmt.Fetch() )
130 : {
131 0 : int i, iNew = apapszGeomColumns.size();
132 0 : char **papszRecord = NULL;
133 0 : for( i = 0; i < 9; i++ )
134 : papszRecord = CSLAddString( papszRecord,
135 0 : oStmt.GetColData(i) );
136 0 : apapszGeomColumns.resize(iNew+1);
137 0 : apapszGeomColumns[iNew] = papszRecord;
138 : }
139 :
140 : /* -------------------------------------------------------------------- */
141 : /* Create a layer for each spatial table. */
142 : /* -------------------------------------------------------------------- */
143 : unsigned int iTable;
144 :
145 : papoLayers = (OGRPGeoLayer **) CPLCalloc(apapszGeomColumns.size(),
146 0 : sizeof(void*));
147 :
148 0 : for( iTable = 0; iTable < apapszGeomColumns.size(); iTable++ )
149 : {
150 0 : char **papszRecord = apapszGeomColumns[iTable];
151 : OGRPGeoTableLayer *poLayer;
152 :
153 0 : poLayer = new OGRPGeoTableLayer( this );
154 :
155 0 : if( poLayer->Initialize( papszRecord[0], // TableName
156 : papszRecord[1], // FieldName
157 : atoi(papszRecord[2]), // ShapeType
158 : atof(papszRecord[3]), // ExtentLeft
159 : atof(papszRecord[4]), // ExtentRight
160 : atof(papszRecord[5]), // ExtentBottom
161 : atof(papszRecord[6]), // ExtentTop
162 : atoi(papszRecord[7]), // SRID
163 : atoi(papszRecord[8])) // HasZ
164 : != CE_None )
165 : {
166 0 : delete poLayer;
167 : }
168 : else
169 0 : papoLayers[nLayers++] = poLayer;
170 :
171 0 : CSLDestroy( papszRecord );
172 : }
173 :
174 0 : return TRUE;
175 : }
176 :
177 : /************************************************************************/
178 : /* TestCapability() */
179 : /************************************************************************/
180 :
181 0 : int OGRPGeoDataSource::TestCapability( const char * pszCap )
182 :
183 : {
184 0 : return FALSE;
185 : }
186 :
187 : /************************************************************************/
188 : /* GetLayer() */
189 : /************************************************************************/
190 :
191 0 : OGRLayer *OGRPGeoDataSource::GetLayer( int iLayer )
192 :
193 : {
194 0 : if( iLayer < 0 || iLayer >= nLayers )
195 0 : return NULL;
196 : else
197 0 : return papoLayers[iLayer];
198 : }
199 :
200 :
201 : /************************************************************************/
202 : /* ExecuteSQL() */
203 : /************************************************************************/
204 :
205 : OGRLayer * OGRPGeoDataSource::ExecuteSQL( const char *pszSQLCommand,
206 : OGRGeometry *poSpatialFilter,
207 0 : const char *pszDialect )
208 :
209 : {
210 : /* -------------------------------------------------------------------- */
211 : /* Use generic imlplementation for OGRSQL dialect. */
212 : /* -------------------------------------------------------------------- */
213 0 : if( pszDialect != NULL && EQUAL(pszDialect,"OGRSQL") )
214 : return OGRDataSource::ExecuteSQL( pszSQLCommand,
215 : poSpatialFilter,
216 0 : pszDialect );
217 :
218 : /* -------------------------------------------------------------------- */
219 : /* Execute statement. */
220 : /* -------------------------------------------------------------------- */
221 0 : CPLODBCStatement *poStmt = new CPLODBCStatement( &oSession );
222 :
223 0 : poStmt->Append( pszSQLCommand );
224 0 : if( !poStmt->ExecuteSQL() )
225 : {
226 : CPLError( CE_Failure, CPLE_AppDefined,
227 0 : "%s", oSession.GetLastError() );
228 0 : return NULL;
229 : }
230 :
231 : /* -------------------------------------------------------------------- */
232 : /* Are there result columns for this statement? */
233 : /* -------------------------------------------------------------------- */
234 0 : if( poStmt->GetColCount() == 0 )
235 : {
236 0 : delete poStmt;
237 0 : CPLErrorReset();
238 0 : return NULL;
239 : }
240 :
241 : /* -------------------------------------------------------------------- */
242 : /* Create a results layer. It will take ownership of the */
243 : /* statement. */
244 : /* -------------------------------------------------------------------- */
245 0 : OGRPGeoSelectLayer *poLayer = NULL;
246 :
247 0 : poLayer = new OGRPGeoSelectLayer( this, poStmt );
248 :
249 0 : if( poSpatialFilter != NULL )
250 0 : poLayer->SetSpatialFilter( poSpatialFilter );
251 :
252 0 : return poLayer;
253 : }
254 :
255 : /************************************************************************/
256 : /* ReleaseResultSet() */
257 : /************************************************************************/
258 :
259 0 : void OGRPGeoDataSource::ReleaseResultSet( OGRLayer * poLayer )
260 :
261 : {
262 0 : delete poLayer;
263 0 : }
|