1 : /******************************************************************************
2 : * $Id: ogrmysqlresultlayer.cpp 18362 2009-12-21 05:47:06Z chaitanya $
3 : *
4 : * Project: OpenGIS Simple Features Reference Implementation
5 : * Purpose: Implements OGRMySQLResultLayer class.
6 : * Author: Frank Warmerdam, warmerdam@pobox.com
7 : * Author: Howard Butler, hobu@hobu.net
8 : *
9 : ******************************************************************************
10 : * Copyright (c) 2004, Frank Warmerdam <warmerdam@pobox.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 "cpl_conv.h"
32 : #include "ogr_mysql.h"
33 :
34 : CPL_CVSID("$Id: ogrmysqlresultlayer.cpp 18362 2009-12-21 05:47:06Z chaitanya $");
35 :
36 : /************************************************************************/
37 : /* OGRMySQLResultLayer() */
38 : /************************************************************************/
39 :
40 3 : OGRMySQLResultLayer::OGRMySQLResultLayer( OGRMySQLDataSource *poDSIn,
41 : const char * pszRawQueryIn,
42 3 : MYSQL_RES *hResultSetIn )
43 : {
44 3 : poDS = poDSIn;
45 :
46 3 : iNextShapeId = 0;
47 :
48 3 : pszRawStatement = CPLStrdup(pszRawQueryIn);
49 :
50 3 : hResultSet = hResultSetIn;
51 :
52 3 : BuildFullQueryStatement();
53 :
54 3 : poFeatureDefn = ReadResultDefinition();
55 3 : }
56 :
57 : /************************************************************************/
58 : /* ~OGRMySQLResultLayer() */
59 : /************************************************************************/
60 :
61 6 : OGRMySQLResultLayer::~OGRMySQLResultLayer()
62 :
63 : {
64 3 : CPLFree( pszRawStatement );
65 6 : }
66 :
67 : /************************************************************************/
68 : /* ReadResultDefinition() */
69 : /* */
70 : /* Build a schema from the current resultset. */
71 : /************************************************************************/
72 :
73 3 : OGRFeatureDefn *OGRMySQLResultLayer::ReadResultDefinition()
74 :
75 : {
76 :
77 : /* -------------------------------------------------------------------- */
78 : /* Parse the returned table information. */
79 : /* -------------------------------------------------------------------- */
80 3 : OGRFeatureDefn *poDefn = new OGRFeatureDefn( "sql_statement" );
81 : int iRawField;
82 :
83 3 : poDefn->Reference();
84 : int width;
85 : int precision;
86 :
87 3 : mysql_field_seek( hResultSet, 0 );
88 3 : for( iRawField = 0;
89 : iRawField < (int) mysql_num_fields(hResultSet);
90 : iRawField++ )
91 : {
92 8 : MYSQL_FIELD *psMSField = mysql_fetch_field( hResultSet );
93 8 : OGRFieldDefn oField( psMSField->name, OFTString);
94 :
95 8 : switch( psMSField->type )
96 : {
97 : case FIELD_TYPE_TINY:
98 : case FIELD_TYPE_SHORT:
99 : case FIELD_TYPE_LONG:
100 : case FIELD_TYPE_INT24:
101 : case FIELD_TYPE_LONGLONG:
102 4 : oField.SetType( OFTInteger );
103 4 : width = (int)psMSField->length;
104 4 : oField.SetWidth(width);
105 4 : poDefn->AddFieldDefn( &oField );
106 4 : break;
107 :
108 : case FIELD_TYPE_DECIMAL:
109 : #ifdef FIELD_TYPE_NEWDECIMAL
110 : case FIELD_TYPE_NEWDECIMAL:
111 : #endif
112 0 : oField.SetType( OFTReal );
113 :
114 : // a bunch of hackery to munge the widths that MySQL gives
115 : // us into corresponding widths and precisions for OGR
116 0 : precision = (int)psMSField->decimals;
117 0 : width = (int)psMSField->length;
118 0 : if (!precision)
119 0 : width = width - 1;
120 0 : width = width - precision;
121 :
122 0 : oField.SetWidth(width);
123 0 : oField.SetPrecision(precision);
124 0 : poDefn->AddFieldDefn( &oField );
125 0 : break;
126 :
127 : case FIELD_TYPE_FLOAT:
128 : case FIELD_TYPE_DOUBLE:
129 : /* MYSQL_FIELD is always reporting ->length = 22 and ->decimals = 31
130 : for double type regardless of the data it returned. In an example,
131 : the data it returned had only 5 or 6 decimal places which were
132 : exactly as entered into the database but reported the decimals
133 : as 31. */
134 : /* Assuming that a length of 22 means no particular width and 31
135 : decimals means no particular precision. */
136 1 : width = (int)psMSField->length;
137 1 : precision = (int)psMSField->decimals;
138 1 : oField.SetType( OFTReal );
139 1 : if( width != 22 )
140 0 : oField.SetWidth(width);
141 1 : if( precision != 31 )
142 0 : oField.SetPrecision(precision);
143 1 : poDefn->AddFieldDefn( &oField );
144 1 : break;
145 :
146 : case FIELD_TYPE_DATE:
147 0 : oField.SetType( OFTDate );
148 0 : oField.SetWidth(0);
149 0 : poDefn->AddFieldDefn( &oField );
150 0 : break;
151 :
152 : case FIELD_TYPE_TIME:
153 0 : oField.SetType( OFTTime );
154 0 : oField.SetWidth(0);
155 0 : poDefn->AddFieldDefn( &oField );
156 0 : break;
157 :
158 : case FIELD_TYPE_TIMESTAMP:
159 : case FIELD_TYPE_DATETIME:
160 0 : oField.SetType( OFTDateTime );
161 0 : oField.SetWidth(0);
162 0 : poDefn->AddFieldDefn( &oField );
163 0 : break;
164 :
165 : case FIELD_TYPE_YEAR:
166 : case FIELD_TYPE_STRING:
167 : case FIELD_TYPE_VAR_STRING:
168 1 : oField.SetType( OFTString );
169 1 : oField.SetWidth((int)psMSField->length);
170 1 : poDefn->AddFieldDefn( &oField );
171 1 : break;
172 :
173 : case FIELD_TYPE_TINY_BLOB:
174 : case FIELD_TYPE_MEDIUM_BLOB:
175 : case FIELD_TYPE_LONG_BLOB:
176 : case FIELD_TYPE_BLOB:
177 1 : if( psMSField->charsetnr == 63 )
178 0 : oField.SetType( OFTBinary );
179 : else
180 1 : oField.SetType( OFTString );
181 1 : oField.SetWidth((int)psMSField->max_length);
182 1 : poDefn->AddFieldDefn( &oField );
183 1 : break;
184 :
185 : case FIELD_TYPE_GEOMETRY:
186 1 : pszGeomColumnTable = CPLStrdup( psMSField->table);
187 1 : pszGeomColumn = CPLStrdup( psMSField->name);
188 : break;
189 :
190 : default:
191 : // any other field we ignore.
192 : break;
193 : }
194 :
195 : // assume a FID name first, and if it isn't there
196 : // take a field that is not null, a primary key,
197 : // and is an integer-like field
198 8 : if( EQUAL(psMSField->name,"ogc_fid") )
199 : {
200 0 : bHasFid = TRUE;
201 0 : pszFIDColumn = CPLStrdup(oField.GetNameRef());
202 0 : continue;
203 : } else
204 8 : if (IS_NOT_NULL(psMSField->flags)
205 : && IS_PRI_KEY(psMSField->flags)
206 : &&
207 : (
208 : psMSField->type == FIELD_TYPE_TINY
209 : || psMSField->type == FIELD_TYPE_SHORT
210 : || psMSField->type == FIELD_TYPE_LONG
211 : || psMSField->type == FIELD_TYPE_INT24
212 : || psMSField->type == FIELD_TYPE_LONGLONG
213 : )
214 : )
215 : {
216 1 : bHasFid = TRUE;
217 1 : pszFIDColumn = CPLStrdup(oField.GetNameRef());
218 1 : continue;
219 : }
220 : }
221 :
222 :
223 3 : poDefn->SetGeomType( wkbNone );
224 :
225 3 : if (pszGeomColumn)
226 : {
227 1 : char* pszType=NULL;
228 : char szCommand[1024];
229 : char **papszRow;
230 :
231 : // set to unknown first
232 1 : poDefn->SetGeomType( wkbUnknown );
233 :
234 : sprintf(szCommand,
235 : "SELECT type FROM geometry_columns WHERE f_table_name='%s'",
236 1 : pszGeomColumnTable );
237 :
238 1 : if( hResultSet != NULL )
239 1 : mysql_free_result( hResultSet );
240 1 : hResultSet = NULL;
241 :
242 1 : if( !mysql_query( poDS->GetConn(), szCommand ) )
243 1 : hResultSet = mysql_store_result( poDS->GetConn() );
244 :
245 1 : papszRow = NULL;
246 1 : if( hResultSet != NULL )
247 1 : papszRow = mysql_fetch_row( hResultSet );
248 :
249 :
250 1 : if( papszRow != NULL && papszRow[0] != NULL )
251 : {
252 1 : pszType = papszRow[0];
253 :
254 1 : OGRwkbGeometryType nGeomType = wkbUnknown;
255 :
256 : // check only standard OGC geometry types
257 1 : if ( EQUAL(pszType, "POINT") )
258 0 : nGeomType = wkbPoint;
259 1 : else if ( EQUAL(pszType,"LINESTRING"))
260 0 : nGeomType = wkbLineString;
261 1 : else if ( EQUAL(pszType,"POLYGON"))
262 0 : nGeomType = wkbPolygon;
263 1 : else if ( EQUAL(pszType,"MULTIPOINT"))
264 0 : nGeomType = wkbMultiPoint;
265 1 : else if ( EQUAL(pszType,"MULTILINESTRING"))
266 0 : nGeomType = wkbMultiLineString;
267 1 : else if ( EQUAL(pszType,"MULTIPOLYGON"))
268 0 : nGeomType = wkbMultiPolygon;
269 1 : else if ( EQUAL(pszType,"GEOMETRYCOLLECTION"))
270 0 : nGeomType = wkbGeometryCollection;
271 :
272 1 : poDefn->SetGeomType( nGeomType );
273 :
274 : }
275 :
276 1 : nSRSId = FetchSRSId();
277 : }
278 :
279 :
280 3 : return poDefn;
281 : }
282 :
283 : /************************************************************************/
284 : /* BuildFullQueryStatement() */
285 : /************************************************************************/
286 :
287 3 : void OGRMySQLResultLayer::BuildFullQueryStatement()
288 :
289 : {
290 3 : if( pszQueryStatement != NULL )
291 : {
292 0 : CPLFree( pszQueryStatement );
293 0 : pszQueryStatement = NULL;
294 : }
295 :
296 3 : pszQueryStatement = CPLStrdup(pszRawStatement);
297 3 : }
298 :
299 : /************************************************************************/
300 : /* ResetReading() */
301 : /************************************************************************/
302 :
303 19 : void OGRMySQLResultLayer::ResetReading()
304 :
305 : {
306 19 : OGRMySQLLayer::ResetReading();
307 19 : }
308 :
309 : /************************************************************************/
310 : /* GetFeatureCount() */
311 : /************************************************************************/
312 :
313 2 : int OGRMySQLResultLayer::GetFeatureCount( int bForce )
314 :
315 : {
316 : // I wonder if we could do anything smart here...
317 : // ... not till MySQL grows up (HB)
318 2 : return OGRMySQLLayer::GetFeatureCount( bForce );
319 : }
320 :
321 : /************************************************************************/
322 : /* TestCapability() */
323 : /************************************************************************/
324 :
325 0 : int OGRMySQLResultLayer::TestCapability( const char * pszCap )
326 :
327 : {
328 0 : return FALSE;
329 : }
330 :
|